where the secondary configuration file should be located to e.g. `/etc` by
adding `-DCMAKE_INSTALL_SYSCONFDIR=/etc`.
-There are two ways to use ccache. You can either prefix your compilation
-commands with `ccache` or you can create a symbolic link (named as your
-compiler) to ccache. The first method is most convenient if you just want to
-try out ccache or wish to use it for some specific projects. The second method
-is most useful for when you wish to use ccache for all your compilations.
-
-To install for usage by the first method just copy ccache to somewhere in your
-path.
-
-To install for the second method, do something like this:
-
- cp ccache /usr/local/bin/
- ln -s ccache /usr/local/bin/gcc
- ln -s ccache /usr/local/bin/g++
- ln -s ccache /usr/local/bin/cc
- ln -s ccache /usr/local/bin/c++
-
-And so forth. This will work as long as `/usr/local/bin` comes before the path
-to the compiler (which is usually in `/usr/bin`). After installing you may wish
-to run `which gcc` to make sure that the correct link is being used.
-
-NOTE: Do not use a hard link, use a symbolic link. A hard link will cause
-"interesting" problems.
+There are two different ways to use ccache to cache a compilation:
+
+1. Prefix your compilation command with `ccache`. This method is most convenient
+ if you just want to try out ccache or wish to use it for some specific
+ projects.
+2. Let ccache masquerade as the compiler. This method is most useful when you
+ wish to use ccache for all your compilations. To do this, create a symbolic
+ link to ccache named as the compiler. For example, here is set up ccache to
+ masquerade as `gcc` and `g++`:
++
+-------------------------------------------------------------------------------
+cp ccache /usr/local/bin/
+ln -s ccache /usr/local/bin/gcc
+ln -s ccache /usr/local/bin/g++
+-------------------------------------------------------------------------------
++
+On platforms that don't support symbolic links you can simply copy ccache to the
+compiler name instead for a similar effect:
++
+-------------------------------------------------------------------------------
+cp ccache /usr/local/bin/gcc
+cp ccache /usr/local/bin/g++
+-------------------------------------------------------------------------------
++
+And so forth. This will work as long as the directory with symbolic links or
+ccache copies comes before the directory with the compiler (typically
+`/usr/bin`) in `PATH`.
[verse]
*ccache* [_options_]
*ccache* _compiler_ [_compiler options_]
-_compiler_ [_compiler options_] (via symbolic link)
+_compiler_ [_compiler options_] (ccache masquerading as the compiler)
== Description
== Run modes
-There are two ways to use ccache. You can either prefix your compilation
-commands with `ccache` or you can let ccache masquerade as the compiler by
-creating a symbolic link (named as the compiler) to ccache. The first method is
-most convenient if you just want to try out ccache or wish to use it for some
-specific projects. The second method is most useful for when you wish to use
-ccache for all your compilations.
-
-To use the first method, just make sure that `ccache` is in your `PATH`.
-
-To use the symlinks method, do something like this:
+There are two different ways to use ccache to cache a compilation:
+1. Prefix your compilation command with `ccache`. This method is most convenient
+ if you just want to try out ccache or wish to use it for some specific
+ projects. Example:
++
+-------------------------------------------------------------------------------
+ccache gcc -c example.c
+-------------------------------------------------------------------------------
++
+2. Let ccache masquerade as the compiler. This method is most useful when you
+ wish to use ccache for all your compilations. To do this, create a symbolic
+ link to ccache named as the compiler. For example, here is set up ccache to
+ masquerade as `gcc` and `g++`:
++
-------------------------------------------------------------------------------
cp ccache /usr/local/bin/
ln -s ccache /usr/local/bin/gcc
ln -s ccache /usr/local/bin/g++
-ln -s ccache /usr/local/bin/cc
-ln -s ccache /usr/local/bin/c++
-------------------------------------------------------------------------------
-
-And so forth. This will work as long as the directory with symlinks comes
-before the path to the compiler (which is usually in `/usr/bin`). After
-installing you may wish to run "`which gcc`" to make sure that the correct link
-is being used.
-
++
+On platforms that don't support symbolic links you can simply copy ccache to the
+compiler name instead for a similar effect:
++
+-------------------------------------------------------------------------------
+cp ccache /usr/local/bin/gcc
+cp ccache /usr/local/bin/g++
+-------------------------------------------------------------------------------
++
+And so forth. This will work as long as the directory with symbolic links or
+ccache copies comes before the directory with the compiler (typically
+`/usr/bin`) in `PATH`.
++
WARNING: The technique of letting ccache masquerade as the compiler works well,
but currently doesn't interact well with other tools that do the same thing. See
_<<Using ccache with other compiler wrappers>>_.
-WARNING: Use a symbolic links for masquerading, not hard links.
-
== Command line options
-These command line options only apply when you invoke ccache as "`ccache`".
-When invoked as a compiler (via a symlink as described in the previous
-section), the normal compiler options apply and you should refer to the
-compiler's documentation.
+These command line options only apply when you invoke ccache as "`ccache`". When
+ccache masquerades as a compiler (as described in the previous section), the
+normal compiler options apply and you should refer to the compiler's
+documentation.
=== Common options
return std::nullopt;
}
+bool
+is_ccache_executable(const std::string_view path)
+{
+ std::string name(Util::base_name(path));
+#ifdef _WIN32
+ name = Util::to_lowercase(name);
+#endif
+ return util::starts_with(name, "ccache");
+}
+
#if defined(HAVE_LINUX_FS_H) || defined(HAVE_STRUCT_STATFS_F_FSTYPENAME)
int
is_nfs_fd(int fd, bool* is_nfs)
#endif
}
-bool
-same_program_name(std::string_view program_name,
- std::string_view canonical_program_name)
-{
-#ifdef _WIN32
- std::string lowercase_program_name = Util::to_lowercase(program_name);
- return lowercase_program_name == canonical_program_name
- || lowercase_program_name == FMT("{}.exe", canonical_program_name);
-#else
- return program_name == canonical_program_name;
-#endif
-}
-
void
send_to_fd(const Context& ctx, const std::string& text, int fd)
{
// point.
std::optional<size_t> is_absolute_path_with_prefix(std::string_view path);
+// Detmine if `path` refers to a ccache executable.
+bool is_ccache_executable(std::string_view path);
+
// Test if a file is on nfs.
//
// Sets is_nfs to the result if fstatfs is available and no error occurred.
// error.
void rename(const std::string& oldpath, const std::string& newpath);
-// Detmine if `program_name` is equal to `canonical_program_name`. On Windows,
-// this means performing a case insensitive equality check with and without a
-// ".exe" suffix. On non-Windows, it is a simple equality check.
-bool same_program_name(std::string_view program_name,
- std::string_view canonical_program_name);
-
// Send `text` to file descriptor `fd`, optionally stripping ANSI color
// sequences if `ctx.args_info.strip_diagnostics_colors` is true and rewriting
// paths to absolute if `ctx.config.absolute_paths_in_stderr` is true. Throws
#include <limits>
#include <memory>
-#ifndef MYNAME
-# define MYNAME "ccache"
-#endif
-const char CCACHE_NAME[] = MYNAME;
-
using core::Statistic;
// This is a string that identifies the current "version" of the hash sum
Args prefix;
for (const auto& word : Util::split_into_strings(prefix_command, " ")) {
- std::string path = find_executable(ctx, word, CCACHE_NAME);
+ std::string path = find_executable(ctx, word, ctx.orig_args[0]);
if (path.empty()) {
throw core::Fatal("{}: {}", word, strerror(errno));
}
TRY(hash_compiler(ctx, hash, st, path, false));
}
} else {
- std::string path = find_executable(ctx, compiler, CCACHE_NAME);
+ std::string path = find_executable(ctx, compiler, ctx.orig_args[0]);
if (!path.empty()) {
auto st = Stat::stat(path, Stat::OnError::log);
TRY(hash_compiler(ctx, hash, st, ccbin, false));
}
// Find the real compiler and put it into ctx.orig_args[0]. We just search the
-// PATH to find an executable of the same name that isn't a link to ourselves.
-// Pass find_executable function as second parameter.
+// PATH to find an executable of the same name that isn't ourselves.
void
find_compiler(Context& ctx,
const FindExecutableFunction& find_executable_function)
// ccache ccache gcc --> 2
size_t compiler_pos = 0;
while (compiler_pos < ctx.orig_args.size()
- && Util::same_program_name(
- Util::base_name(ctx.orig_args[compiler_pos]), CCACHE_NAME)) {
+ && Util::is_ccache_executable(ctx.orig_args[compiler_pos])) {
++compiler_pos;
}
const std::string resolved_compiler =
util::is_full_path(compiler)
? compiler
- : find_executable_function(ctx, compiler, CCACHE_NAME);
+ : find_executable_function(ctx, compiler, ctx.orig_args[0]);
if (resolved_compiler.empty()) {
throw core::Fatal("Could not find compiler \"{}\" in PATH", compiler);
}
- if (Util::same_program_name(Util::base_name(resolved_compiler),
- CCACHE_NAME)) {
- throw core::Fatal(
- "Recursive invocation (the name of the ccache binary must be \"{}\")",
- CCACHE_NAME);
+ if (Util::is_ccache_executable(resolved_compiler)) {
+ throw core::Fatal("Recursive invocation of ccache");
}
ctx.orig_args.pop_front(compiler_pos);
ccache_main(int argc, const char* const* argv)
{
try {
- // Check if we are being invoked as "ccache".
- std::string program_name(Util::base_name(argv[0]));
- if (Util::same_program_name(program_name, CCACHE_NAME)) {
+ if (Util::is_ccache_executable(argv[0])) {
if (argc < 2) {
- PRINT_RAW(stderr, core::get_usage_text());
+ PRINT_RAW(stderr, core::get_usage_text(Util::base_name(argv[0])));
exit(EXIT_FAILURE);
}
// If the first argument isn't an option, then assume we are being
// Copyright (C) 2002-2007 Andrew Tridgell
-// Copyright (C) 2009-2021 Joel Rosdahl and other contributors
+// Copyright (C) 2009-2022 Joel Rosdahl and other contributors
//
// See doc/AUTHORS.adoc for a complete list of contributors.
//
class Context;
-extern const char CCACHE_NAME[];
extern const char CCACHE_VERSION[];
using FindExecutableFunction =
std::function<std::string(const Context& ctx,
const std::string& name,
- const std::string& exclude_name)>;
+ const std::string& exclude_path)>;
int ccache_main(int argc, const char* const* argv);
R"(Usage:
{0} [options]
{0} compiler [compiler options]
- compiler [compiler options] (via symbolic link)
+ compiler [compiler options] (ccache masquerading as the compiler)
Common options:
-c, --cleanup delete old files and recalculate size counters
}
static std::string
-get_version_text()
+get_version_text(const std::string_view ccache_name)
{
return FMT(
- VERSION_TEXT, CCACHE_NAME, CCACHE_VERSION, storage::get_features());
+ VERSION_TEXT, ccache_name, CCACHE_VERSION, storage::get_features());
}
std::string
-get_usage_text()
+get_usage_text(const std::string_view ccache_name)
{
- return FMT(USAGE_TEXT, CCACHE_NAME);
+ return FMT(USAGE_TEXT, ccache_name);
}
enum {
}
case 'h': // --help
- PRINT(stdout, USAGE_TEXT, CCACHE_NAME, CCACHE_NAME);
+ PRINT(stdout, USAGE_TEXT, Util::base_name(argv[0]));
return EXIT_SUCCESS;
case 'k': // --get-config
break;
case 'V': // --version
- PRINT_RAW(stdout, get_version_text());
+ PRINT_RAW(stdout, get_version_text(Util::base_name(argv[0])));
break;
case 'x': // --show-compression
break;
default:
- PRINT(stderr, USAGE_TEXT, CCACHE_NAME, CCACHE_NAME);
+ PRINT(stderr, USAGE_TEXT, Util::base_name(argv[0]));
return EXIT_FAILURE;
}
}
-// Copyright (C) 2021 Joel Rosdahl and other contributors
+// Copyright (C) 2021-2022 Joel Rosdahl and other contributors
//
// See doc/AUTHORS.adoc for a complete list of contributors.
//
#pragma once
#include <string>
+#include <string_view>
namespace core {
// The main program when not doing a compile.
int process_main_options(int argc, const char* const* argv);
-std::string get_usage_text();
+std::string get_usage_text(std::string_view ccache_name);
} // namespace core
std::string
win32getshell(const std::string& path)
{
- const char* path_env = getenv("PATH");
+ const char* path_list = getenv("PATH");
std::string sh;
- if (Util::to_lowercase(Util::get_extension(path)) == ".sh" && path_env) {
- sh = find_executable_in_path("sh.exe", "", path_env);
+ if (Util::to_lowercase(Util::get_extension(path)) == ".sh" && path_list) {
+ sh = find_executable_in_path("sh.exe", path_list);
}
if (sh.empty() && getenv("CCACHE_DETECT_SHEBANG")) {
// Detect shebang.
if (fp) {
char buf[10] = {0};
fgets(buf, sizeof(buf) - 1, fp.get());
- if (std::string(buf) == "#!/bin/sh" && path_env) {
- sh = find_executable_in_path("sh.exe", "", path_env);
+ if (std::string(buf) == "#!/bin/sh" && path_list) {
+ sh = find_executable_in_path("sh.exe", path_list);
}
}
}
std::string
find_executable(const Context& ctx,
const std::string& name,
- const std::string& exclude_name)
+ const std::string& exclude_path)
{
if (util::is_absolute_path(name)) {
return name;
}
- std::string path = ctx.config.path();
- if (path.empty()) {
- path = getenv("PATH");
+ std::string path_list = ctx.config.path();
+ if (path_list.empty()) {
+ path_list = getenv("PATH");
}
- if (path.empty()) {
+ if (path_list.empty()) {
LOG_RAW("No PATH variable");
return {};
}
- return find_executable_in_path(name, exclude_name, path);
+ return find_executable_in_path(name, path_list, exclude_path);
}
std::string
find_executable_in_path(const std::string& name,
- const std::string& exclude_name,
- const std::string& path)
+ const std::string& path_list,
+ std::optional<std::string> exclude_path)
{
- if (path.empty()) {
+ if (path_list.empty()) {
return {};
}
- // Search the path looking for the first compiler of the right name that isn't
- // us.
- for (const std::string& dir : util::split_path_list(path)) {
+ const auto real_exclude_path =
+ exclude_path ? Util::real_path(*exclude_path) : "";
+
+ // Search the path list looking for the first compiler of the right name that
+ // isn't us.
+ for (const std::string& dir : util::split_path_list(path_list)) {
+ const std::vector<std::string> candidates = {
+ FMT("{}/{}", dir, name),
#ifdef _WIN32
- char namebuf[MAX_PATH];
- int ret = SearchPath(
- dir.c_str(), name.c_str(), nullptr, sizeof(namebuf), namebuf, nullptr);
- if (!ret) {
- std::string exename = FMT("{}.exe", name);
- ret = SearchPath(dir.c_str(),
- exename.c_str(),
- nullptr,
- sizeof(namebuf),
- namebuf,
- nullptr);
- }
- (void)exclude_name;
- if (ret) {
- return namebuf;
- }
+ FMT("{}/{}.exe", dir, name),
+#endif
+ };
+ for (const auto& candidate : candidates) {
+ // A valid candidate:
+ //
+ // 1. Must exist (e.g., should not be a broken symlink) and be an
+ // executable.
+ // 2. Must not resolve to the same program as argv[0] (i.e.,
+ // exclude_path). This can happen if ccache is masquerading as the
+ // compiler (with or without using a symlink).
+ // 3. As an extra safety measure: must not be a ccache executable after
+ // resolving symlinks. This can happen if the candidate compiler is a
+ // symlink to another ccache executeable.
+ const bool candidate_exists =
+#ifdef _WIN32
+ Stat::stat(candidate);
#else
- ASSERT(!exclude_name.empty());
- std::string fname = FMT("{}/{}", dir, name);
- auto st1 = Stat::lstat(fname);
- auto st2 = Stat::stat(fname);
- // Look for a normal executable file.
- if (st1 && st2 && st2.is_regular() && access(fname.c_str(), X_OK) == 0) {
- if (st1.is_symlink()) {
- std::string real_path = Util::real_path(fname, true);
- if (Util::base_name(real_path) == exclude_name) {
- // It's a link to "ccache"!
- continue;
+ access(candidate.c_str(), X_OK) == 0;
+#endif
+ if (candidate_exists) {
+ const auto real_candidate = Util::real_path(candidate);
+ if ((real_exclude_path.empty() || real_candidate != real_exclude_path)
+ && !Util::is_ccache_executable(real_candidate)) {
+ return candidate;
}
}
-
- // Found it!
- return fname;
}
-#endif
}
return {};
-// Copyright (C) 2020-2021 Joel Rosdahl and other contributors
+// Copyright (C) 2020-2022 Joel Rosdahl and other contributors
//
// See doc/AUTHORS.adoc for a complete list of contributors.
//
#include "Fd.hpp"
+#include <optional>
#include <string>
class Context;
void execute_noreturn(const char* const* argv, const std::string& temp_dir);
// Find an executable named `name` in `$PATH`. Exclude any executables that are
-// links to `exclude_name`.
+// links to `exclude_path`.
std::string find_executable(const Context& ctx,
const std::string& name,
- const std::string& exclude_name);
+ const std::string& exclude_path);
-std::string find_executable_in_path(const std::string& name,
- const std::string& exclude_name,
- const std::string& path);
+std::string
+find_executable_in_path(const std::string& name,
+ const std::string& path_list,
+ std::optional<std::string> exclude_path = std::nullopt);
#ifdef _WIN32
std::string win32getshell(const std::string& path);
STARTUPINFO si;
memset(&si, 0x00, sizeof(si));
- std::string path = find_executable_in_path(args[0], "", getenv("PATH"));
+ std::string path = find_executable_in_path(args[0], getenv("PATH"));
if (path.empty()) {
path = args[0];
}
}
m_http_client.set_default_headers({
- {"User-Agent", FMT("{}/{}", CCACHE_NAME, CCACHE_VERSION)},
+ {"User-Agent", FMT("ccache/{}", CCACHE_VERSION)},
});
m_http_client.set_keep_alive(true);
#pragma once
+#include <ctime>
#include <optional>
#include <string>
}
SUITE_masquerading_SETUP() {
- ln -s "$CCACHE" $COMPILER_BIN
generate_code 1 test1.c
}
SUITE_masquerading() {
+if ! $HOST_OS_WINDOWS && ! $HOST_OS_CYGWIN; then
# -------------------------------------------------------------------------
TEST "Masquerading via symlink, relative path"
+ ln -s "$CCACHE" $COMPILER_BIN
$COMPILER -c -o reference_test1.o test1.c
- ./$COMPILER_BIN $COMPILER_ARGS -c test1.c
+ PATH="${PWD}:${PATH}" ./$COMPILER_BIN $COMPILER_ARGS -c test1.c
expect_stat preprocessed_cache_hit 0
expect_stat cache_miss 1
expect_stat files_in_cache 1
expect_equal_object_files reference_test1.o test1.o
- ./$COMPILER_BIN $COMPILER_ARGS -c test1.c
+ PATH="${PWD}:${PATH}" ./$COMPILER_BIN $COMPILER_ARGS -c test1.c
expect_stat preprocessed_cache_hit 1
expect_stat cache_miss 1
expect_stat files_in_cache 1
# -------------------------------------------------------------------------
TEST "Masquerading via symlink, absolute path"
+ ln -s "$CCACHE" $COMPILER_BIN
+ $COMPILER -c -o reference_test1.o test1.c
+
+ PATH="${PWD}:${PATH}" $PWD/$COMPILER_BIN $COMPILER_ARGS -c test1.c
+ expect_stat preprocessed_cache_hit 0
+ expect_stat cache_miss 1
+ expect_stat files_in_cache 1
+ expect_equal_object_files reference_test1.o test1.o
+
+ PATH="${PWD}:${PATH}" $PWD/$COMPILER_BIN $COMPILER_ARGS -c test1.c
+ expect_stat preprocessed_cache_hit 1
+ expect_stat cache_miss 1
+ expect_stat files_in_cache 1
+ expect_equal_object_files reference_test1.o test1.o
+fi
+
+ # -------------------------------------------------------------------------
+ TEST "Masquerading via copy or hard link"
+
+ cp "$CCACHE" $COMPILER_BIN
$COMPILER -c -o reference_test1.o test1.c
- $PWD/$COMPILER_BIN $COMPILER_ARGS -c test1.c
+ PATH="${PWD}:${PATH}" ./$COMPILER_BIN $COMPILER_ARGS -c test1.c
expect_stat preprocessed_cache_hit 0
expect_stat cache_miss 1
expect_stat files_in_cache 1
expect_equal_object_files reference_test1.o test1.o
- $PWD/$COMPILER_BIN $COMPILER_ARGS -c test1.c
+ PATH="${PWD}:${PATH}" ./$COMPILER_BIN $COMPILER_ARGS -c test1.c
expect_stat preprocessed_cache_hit 1
expect_stat cache_miss 1
expect_stat files_in_cache 1
#endif
}
+TEST_CASE("Util::is_ccache_executable")
+{
+ CHECK(Util::is_ccache_executable("ccache"));
+ CHECK(Util::is_ccache_executable("ccache-1.2.3"));
+ CHECK(!Util::is_ccache_executable("fooccache"));
+ CHECK(!Util::is_ccache_executable("gcc"));
+#ifdef _WIN32
+ CHECK(Util::is_ccache_executable("CCACHE"));
+ CHECK(Util::is_ccache_executable("CCACHE.exe"));
+ CHECK(Util::is_ccache_executable("CCACHE-1.2.3"));
+ CHECK(Util::is_ccache_executable("CCACHE.EXE"));
+ CHECK(Util::is_ccache_executable("CCACHE-1.2.3.EXE"));
+#endif
+}
+
TEST_CASE("Util::is_dir_separator")
{
CHECK(!Util::is_dir_separator('x'));
CHECK(Util::remove_extension("/foo/bar/f.abc.txt") == "/foo/bar/f.abc");
}
-TEST_CASE("Util::same_program_name")
-{
- CHECK(Util::same_program_name("foo", "foo"));
-#ifdef _WIN32
- CHECK(Util::same_program_name("FOO", "foo"));
- CHECK(Util::same_program_name("FOO.exe", "foo"));
-#else
- CHECK(!Util::same_program_name("FOO", "foo"));
- CHECK(!Util::same_program_name("FOO.exe", "foo"));
-#endif
-}
-
// Util::split_into_strings and Util::split_into_views are tested implicitly in
// test_util_Tokenizer.cpp.
-// Copyright (C) 2020-2021 Joel Rosdahl and other contributors
+// Copyright (C) 2020-2022 Joel Rosdahl and other contributors
//
// See doc/AUTHORS.adoc for a complete list of contributors.
//
# include <unistd.h>
#endif
-#ifdef MYNAME
-# define CCACHE_NAME MYNAME
-#else
-# define CCACHE_NAME "ccache"
-#endif
-
using TestUtil::TestContext;
TEST_SUITE_BEGIN("ccache");
// In case the first parameter is ccache, resolve the second parameter to
// the real compiler unless it's a relative or absolute path.
- CHECK(helper(CCACHE_NAME " gcc", "") == "resolved_gcc");
- CHECK(helper(CCACHE_NAME " rel/gcc", "") == "rel/gcc");
- CHECK(helper(CCACHE_NAME " /abs/gcc", "") == "/abs/gcc");
+ CHECK(helper("ccache gcc", "") == "resolved_gcc");
+ CHECK(helper("ccache rel/gcc", "") == "rel/gcc");
+ CHECK(helper("ccache /abs/gcc", "") == "/abs/gcc");
- CHECK(helper("rel/" CCACHE_NAME " gcc", "") == "resolved_gcc");
- CHECK(helper("rel/" CCACHE_NAME " rel/gcc", "") == "rel/gcc");
- CHECK(helper("rel/" CCACHE_NAME " /abs/gcc", "") == "/abs/gcc");
+ CHECK(helper("rel/ccache gcc", "") == "resolved_gcc");
+ CHECK(helper("rel/ccache rel/gcc", "") == "rel/gcc");
+ CHECK(helper("rel/ccache /abs/gcc", "") == "/abs/gcc");
- CHECK(helper("/abs/" CCACHE_NAME " gcc", "") == "resolved_gcc");
- CHECK(helper("/abs/" CCACHE_NAME " rel/gcc", "") == "rel/gcc");
- CHECK(helper("/abs/" CCACHE_NAME " /abs/gcc", "") == "/abs/gcc");
+ CHECK(helper("/abs/ccache gcc", "") == "resolved_gcc");
+ CHECK(helper("/abs/ccache rel/gcc", "") == "rel/gcc");
+ CHECK(helper("/abs/ccache /abs/gcc", "") == "/abs/gcc");
// If gcc points back to ccache throw, unless either ccache or gcc is a
// relative or absolute path.
- CHECK_THROWS(helper(CCACHE_NAME " gcc", "", CCACHE_NAME));
- CHECK(helper(CCACHE_NAME " rel/gcc", "", CCACHE_NAME) == "rel/gcc");
- CHECK(helper(CCACHE_NAME " /abs/gcc", "", CCACHE_NAME) == "/abs/gcc");
+ CHECK_THROWS(helper("ccache gcc", "", "ccache"));
+ CHECK(helper("ccache rel/gcc", "", "ccache") == "rel/gcc");
+ CHECK(helper("ccache /abs/gcc", "", "ccache") == "/abs/gcc");
- CHECK_THROWS(helper("rel/" CCACHE_NAME " gcc", "", CCACHE_NAME));
- CHECK(helper("rel/" CCACHE_NAME " rel/gcc", "", CCACHE_NAME) == "rel/gcc");
- CHECK(helper("rel/" CCACHE_NAME " /a/gcc", "", CCACHE_NAME) == "/a/gcc");
+ CHECK_THROWS(helper("rel/ccache gcc", "", "ccache"));
+ CHECK(helper("rel/ccache rel/gcc", "", "ccache") == "rel/gcc");
+ CHECK(helper("rel/ccache /a/gcc", "", "ccache") == "/a/gcc");
- CHECK_THROWS(helper("/abs/" CCACHE_NAME " gcc", "", CCACHE_NAME));
- CHECK(helper("/abs/" CCACHE_NAME " rel/gcc", "", CCACHE_NAME) == "rel/gcc");
- CHECK(helper("/abs/" CCACHE_NAME " /a/gcc", "", CCACHE_NAME) == "/a/gcc");
+ CHECK_THROWS(helper("/abs/ccache gcc", "", "ccache"));
+ CHECK(helper("/abs/ccache rel/gcc", "", "ccache") == "rel/gcc");
+ CHECK(helper("/abs/ccache /a/gcc", "", "ccache") == "/a/gcc");
// If compiler is not found then throw, unless the compiler has a relative
// or absolute path.
- CHECK_THROWS(helper(CCACHE_NAME " gcc", "", ""));
- CHECK(helper(CCACHE_NAME " rel/gcc", "", "") == "rel/gcc");
- CHECK(helper(CCACHE_NAME " /abs/gcc", "", "") == "/abs/gcc");
+ CHECK_THROWS(helper("ccache gcc", "", ""));
+ CHECK(helper("ccache rel/gcc", "", "") == "rel/gcc");
+ CHECK(helper("ccache /abs/gcc", "", "") == "/abs/gcc");
- CHECK_THROWS(helper("rel/" CCACHE_NAME " gcc", "", ""));
- CHECK(helper("rel/" CCACHE_NAME " rel/gcc", "", "") == "rel/gcc");
- CHECK(helper("rel/" CCACHE_NAME " /abs/gcc", "", "") == "/abs/gcc");
+ CHECK_THROWS(helper("rel/ccache gcc", "", ""));
+ CHECK(helper("rel/ccache rel/gcc", "", "") == "rel/gcc");
+ CHECK(helper("rel/ccache /abs/gcc", "", "") == "/abs/gcc");
- CHECK_THROWS(helper("/abs/" CCACHE_NAME " gcc", "", ""));
- CHECK(helper("/abs/" CCACHE_NAME " rel/gcc", "", "") == "rel/gcc");
- CHECK(helper("/abs/" CCACHE_NAME " /abs/gcc", "", "") == "/abs/gcc");
+ CHECK_THROWS(helper("/abs/ccache gcc", "", ""));
+ CHECK(helper("/abs/ccache rel/gcc", "", "") == "rel/gcc");
+ CHECK(helper("/abs/ccache /abs/gcc", "", "") == "/abs/gcc");
}
SUBCASE("double ccache")
{
// E.g. due to some suboptimal setup, scripts etc. Source:
// https://github.com/ccache/ccache/issues/686
- CHECK(helper(CCACHE_NAME " gcc", "") == "resolved_gcc");
- CHECK(helper(CCACHE_NAME " " CCACHE_NAME " gcc", "") == "resolved_gcc");
- CHECK(helper(CCACHE_NAME " " CCACHE_NAME " " CCACHE_NAME " gcc", "")
- == "resolved_gcc");
+ CHECK(helper("ccache gcc", "") == "resolved_gcc");
+ CHECK(helper("ccache ccache gcc", "") == "resolved_gcc");
+ CHECK(helper("ccache ccache-1.2.3 ccache gcc", "") == "resolved_gcc");
}
SUBCASE("config")
// In case the first parameter is ccache, use the configuration value. Don't
// resolve configuration value if it's a relative or absolute path.
- CHECK(helper(CCACHE_NAME " gcc", "config") == "resolved_config");
- CHECK(helper(CCACHE_NAME " gcc", "rel/config") == "rel/config");
- CHECK(helper(CCACHE_NAME " gcc", "/abs/config") == "/abs/config");
- CHECK(helper(CCACHE_NAME " rel/gcc", "config") == "resolved_config");
- CHECK(helper(CCACHE_NAME " /abs/gcc", "config") == "resolved_config");
+ CHECK(helper("ccache gcc", "config") == "resolved_config");
+ CHECK(helper("ccache gcc", "rel/config") == "rel/config");
+ CHECK(helper("ccache gcc", "/abs/config") == "/abs/config");
+ CHECK(helper("ccache rel/gcc", "config") == "resolved_config");
+ CHECK(helper("ccache /abs/gcc", "config") == "resolved_config");
// Same as above with relative path to ccache.
- CHECK(helper("r/" CCACHE_NAME " gcc", "conf") == "resolved_conf");
- CHECK(helper("r/" CCACHE_NAME " gcc", "rel/conf") == "rel/conf");
- CHECK(helper("r/" CCACHE_NAME " gcc", "/abs/conf") == "/abs/conf");
- CHECK(helper("r/" CCACHE_NAME " rel/gcc", "conf") == "resolved_conf");
- CHECK(helper("r/" CCACHE_NAME " /abs/gcc", "conf") == "resolved_conf");
+ CHECK(helper("r/ccache gcc", "conf") == "resolved_conf");
+ CHECK(helper("r/ccache gcc", "rel/conf") == "rel/conf");
+ CHECK(helper("r/ccache gcc", "/abs/conf") == "/abs/conf");
+ CHECK(helper("r/ccache rel/gcc", "conf") == "resolved_conf");
+ CHECK(helper("r/ccache /abs/gcc", "conf") == "resolved_conf");
// Same as above with absolute path to ccache.
- CHECK(helper("/a/" CCACHE_NAME " gcc", "conf") == "resolved_conf");
- CHECK(helper("/a/" CCACHE_NAME " gcc", "rel/conf") == "rel/conf");
- CHECK(helper("/a/" CCACHE_NAME " gcc", "/a/conf") == "/a/conf");
- CHECK(helper("/a/" CCACHE_NAME " rel/gcc", "conf") == "resolved_conf");
- CHECK(helper("/a/" CCACHE_NAME " /abs/gcc", "conf") == "resolved_conf");
+ CHECK(helper("/a/ccache gcc", "conf") == "resolved_conf");
+ CHECK(helper("/a/ccache gcc", "rel/conf") == "rel/conf");
+ CHECK(helper("/a/ccache gcc", "/a/conf") == "/a/conf");
+ CHECK(helper("/a/ccache rel/gcc", "conf") == "resolved_conf");
+ CHECK(helper("/a/ccache /abs/gcc", "conf") == "resolved_conf");
}
}