summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoel Rosdahl <joel@rosdahl.net>2023-02-17 08:26:08 +0100
committerJoel Rosdahl <joel@rosdahl.net>2023-02-20 08:02:33 +0100
commite1a53fd0e67fb2d4ad7619e22550545fab27c620 (patch)
treea6faefad3976abd79fe939d80fd94423748ee362
parent86bfec0d10ac8967fd8a2703837f9f6e25d51bc3 (diff)
downloadccache-e1a53fd0e67fb2d4ad7619e22550545fab27c620.tar.gz
feat: Add support for setting per-compilation config on command line
Closes #1035.
-rw-r--r--doc/MANUAL.adoc24
-rw-r--r--src/Config.cpp44
-rw-r--r--src/Config.hpp10
-rw-r--r--src/Context.cpp9
-rw-r--r--src/Context.hpp5
-rw-r--r--src/ccache.cpp129
-rw-r--r--src/ccache.hpp18
-rw-r--r--src/core/mainoptions.cpp14
-rw-r--r--test/suites/config.bash12
-rw-r--r--unittest/test_ccache.cpp156
10 files changed, 260 insertions, 161 deletions
diff --git a/doc/MANUAL.adoc b/doc/MANUAL.adoc
index e22685ec..4645267b 100644
--- a/doc/MANUAL.adoc
+++ b/doc/MANUAL.adoc
@@ -9,9 +9,14 @@ ccache - a fast C/C++ compiler cache
== Synopsis
[verse]
-*ccache* [_options_]
-*ccache* _compiler_ [_compiler options_]
-_compiler_ [_compiler options_] (ccache masquerading as the compiler)
+*ccache* [_ccache options_]
+*ccache* [_KEY_=_VALUE_ ...] _compiler_ [_compiler options_]
+_compiler_ [_compiler options_]
+
+The first form takes options described in <<Command line options>> below. The
+second form invokes the compiler, optionally using <<Configuration,configuration
+options>> as _KEY_=_VALUE_ arguments. In the third form, ccache is masquerading
+as the compiler as described in <<Run modes>>.
== Description
@@ -310,11 +315,16 @@ system-level configuration file and secondly a cache-specific configuration
file. The priorities of configuration options are as follows (where 1 is
highest):
-1. Environment variables.
-2. The cache-specific configuration file (see below).
-3. The system (read-only) configuration file `<sysconfdir>/ccache.conf`
+1. Command line settings in _KEY_=_VALUE_ form. Example:
++
+-------------------------------------------------------------------------------
+ccache debug=true compiler_check="%compiler% --version" gcc -c example.c
+-------------------------------------------------------------------------------
+2. Environment variables.
+3. The cache-specific configuration file (see below).
+4. The system (read-only) configuration file `<sysconfdir>/ccache.conf`
(typically `/etc/ccache.conf` or `/usr/local/etc/ccache.conf`).
-4. Compile-time defaults.
+5. Compile-time defaults.
As a special case, if the environment variable `CCACHE_CONFIGPATH` is set it
specifies the configuration file, and the system configuration file won't be
diff --git a/src/Config.cpp b/src/Config.cpp
index a12180a8..a28d5647 100644
--- a/src/Config.cpp
+++ b/src/Config.cpp
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2022 Joel Rosdahl and other contributors
+// Copyright (C) 2019-2023 Joel Rosdahl and other contributors
//
// See doc/AUTHORS.adoc for a complete list of contributors.
//
@@ -439,6 +439,24 @@ parse_config_file(const std::string& path,
return true;
}
+std::unordered_map<std::string, std::string>
+create_cmdline_settings_map(const std::vector<std::string>& settings)
+{
+ std::unordered_map<std::string, std::string> result;
+ for (const auto& setting : settings) {
+ DEBUG_ASSERT(setting.find('=') != std::string::npos);
+ std::string key;
+ std::string value;
+ std::string error_message;
+ bool ok = parse_line(setting, &key, &value, &error_message);
+ ASSERT(ok);
+ if (!key.empty()) {
+ result.insert_or_assign(std::move(key), std::move(value));
+ }
+ }
+ return result;
+}
+
} // namespace
#ifndef _WIN32
@@ -489,8 +507,11 @@ compiler_type_to_string(CompilerType compiler_type)
}
void
-Config::read()
+Config::read(const std::vector<std::string>& cmdline_config_settings)
{
+ auto cmdline_settings_map =
+ create_cmdline_settings_map(cmdline_config_settings);
+
const std::string home_dir = Util::get_home_directory();
const std::string legacy_ccache_dir = Util::make_path(home_dir, ".ccache");
const bool legacy_ccache_dir_exists =
@@ -525,8 +546,12 @@ Config::read()
MTR_END("config", "conf_read_system");
const char* const env_ccache_dir = getenv("CCACHE_DIR");
+ auto cmdline_cache_dir = cmdline_settings_map.find("cache_dir");
+
std::string config_dir;
- if (env_ccache_dir && *env_ccache_dir) {
+ if (cmdline_cache_dir != cmdline_settings_map.end()) {
+ config_dir = cmdline_cache_dir->second;
+ } else if (env_ccache_dir && *env_ccache_dir) {
config_dir = env_ccache_dir;
} else if (!cache_dir().empty() && !env_ccache_dir) {
config_dir = cache_dir();
@@ -572,6 +597,8 @@ Config::read()
// (cache_dir is set above if CCACHE_DIR is set.)
MTR_END("config", "conf_update_from_environment");
+ update_from_map(cmdline_settings_map);
+
if (cache_dir().empty()) {
if (legacy_ccache_dir_exists) {
set_cache_dir(legacy_ccache_dir);
@@ -594,7 +621,8 @@ Config::read()
// else: cache_dir was set explicitly via environment or via system config.
// We have now determined config.cache_dir and populated the rest of config in
- // prio order (1. environment, 2. cache-specific config, 3. system config).
+ // prio order (1. command line, 2. environment, 3. cache-specific config, 4.
+ // system config).
}
const std::string&
@@ -633,6 +661,14 @@ Config::update_from_file(const std::string& path)
}
void
+Config::update_from_map(const std::unordered_map<std::string, std::string>& map)
+{
+ for (const auto& [key, value] : map) {
+ set_item(key, value, std::nullopt, false, "command line");
+ }
+}
+
+void
Config::update_from_environment()
{
for (char** env = environ; *env; ++env) {
diff --git a/src/Config.hpp b/src/Config.hpp
index b1d2e101..43c6a7fc 100644
--- a/src/Config.hpp
+++ b/src/Config.hpp
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2022 Joel Rosdahl and other contributors
+// Copyright (C) 2019-2023 Joel Rosdahl and other contributors
//
// See doc/AUTHORS.adoc for a complete list of contributors.
//
@@ -30,6 +30,7 @@
#include <optional>
#include <string>
#include <unordered_map>
+#include <vector>
enum class CompilerType {
auto_guess,
@@ -49,7 +50,7 @@ class Config : NonCopyable
public:
Config() = default;
- void read();
+ void read(const std::vector<std::string>& cmdline_config_settings = {});
bool absolute_paths_in_stderr() const;
const std::string& base_dir() const;
@@ -139,6 +140,11 @@ public:
// invalid configuration values.
bool update_from_file(const std::string& path);
+ // Set config values from a map with key-value pairs.
+ //
+ // Throws Error on invalid configuration values.
+ void update_from_map(const std::unordered_map<std::string, std::string>& map);
+
// Set config values from environment variables.
//
// Throws Error on invalid configuration values.
diff --git a/src/Context.cpp b/src/Context.cpp
index c46d3684..0a45d9e6 100644
--- a/src/Context.cpp
+++ b/src/Context.cpp
@@ -1,4 +1,4 @@
-// Copyright (C) 2020-2022 Joel Rosdahl and other contributors
+// Copyright (C) 2020-2023 Joel Rosdahl and other contributors
//
// See doc/AUTHORS.adoc for a complete list of contributors.
//
@@ -49,11 +49,12 @@ Context::Context()
}
void
-Context::initialize()
+Context::initialize(Args&& compiler_and_args,
+ const std::vector<std::string>& cmdline_config_settings)
{
- config.read();
+ orig_args = std::move(compiler_and_args);
+ config.read(cmdline_config_settings);
Logging::init(config);
-
ignore_header_paths =
util::split_path_list(config.ignore_headers_in_manifest());
set_ignore_options(Util::split_into_strings(config.ignore_options(), " "));
diff --git a/src/Context.hpp b/src/Context.hpp
index 883c02f4..3eee4e5e 100644
--- a/src/Context.hpp
+++ b/src/Context.hpp
@@ -1,4 +1,4 @@
-// Copyright (C) 2020-2022 Joel Rosdahl and other contributors
+// Copyright (C) 2020-2023 Joel Rosdahl and other contributors
//
// See doc/AUTHORS.adoc for a complete list of contributors.
//
@@ -51,7 +51,8 @@ public:
// Read configuration, initialize logging, etc. Typically not called from unit
// tests.
- void initialize();
+ void initialize(Args&& compiler_and_args,
+ const std::vector<std::string>& cmdline_config_settings);
ArgsInfo args_info;
Config config;
diff --git a/src/ccache.cpp b/src/ccache.cpp
index ff5315c1..d867dd1e 100644
--- a/src/ccache.cpp
+++ b/src/ccache.cpp
@@ -72,6 +72,7 @@
#include <algorithm>
#include <cmath>
+#include <cstring>
#include <limits>
#include <memory>
#include <unordered_map>
@@ -2109,25 +2110,18 @@ from_cache(Context& ctx, FromCacheCallMode mode, const Digest& result_key)
// PATH to find an executable of the same name that isn't ourselves.
void
find_compiler(Context& ctx,
- const FindExecutableFunction& find_executable_function)
+ const FindExecutableFunction& find_executable_function,
+ bool masquerading_as_compiler)
{
- // gcc --> 0
- // ccache gcc --> 1
- // ccache ccache gcc --> 2
- size_t compiler_pos = 0;
- while (compiler_pos < ctx.orig_args.size()
- && Util::is_ccache_executable(ctx.orig_args[compiler_pos])) {
- ++compiler_pos;
- }
-
// Support user override of the compiler.
const std::string compiler =
!ctx.config.compiler().empty()
? ctx.config.compiler()
// In case ccache is masquerading as the compiler, use only base_name so
// the real compiler can be determined.
- : (compiler_pos == 0 ? std::string(Util::base_name(ctx.orig_args[0]))
- : ctx.orig_args[compiler_pos]);
+ : (masquerading_as_compiler
+ ? std::string(Util::base_name(ctx.orig_args[0]))
+ : ctx.orig_args[0]);
const std::string resolved_compiler =
util::is_full_path(compiler)
@@ -2142,17 +2136,12 @@ find_compiler(Context& ctx,
throw core::Fatal("Recursive invocation of ccache");
}
- ctx.orig_args.pop_front(compiler_pos);
ctx.orig_args[0] = resolved_compiler;
}
-// Initialize ccache. Must be called once before anything else is run.
static void
-initialize(Context& ctx, int argc, const char* const* argv)
+initialize(Context& ctx, const char* const* argv, bool masquerading_as_compiler)
{
- ctx.orig_args = Args::from_argv(argc, argv);
- ctx.storage.initialize();
-
LOG("=== CCACHE {} STARTED =========================================",
CCACHE_VERSION);
@@ -2166,6 +2155,42 @@ initialize(Context& ctx, int argc, const char* const* argv)
LOG_RAW("Error: tracing is not enabled!");
#endif
}
+
+ if (!ctx.config.log_file().empty() || ctx.config.debug()) {
+ ctx.config.visit_items([&ctx](const std::string& key,
+ const std::string& value,
+ const std::string& origin) {
+ const auto& log_value =
+ key == "remote_storage"
+ ? ctx.storage.get_remote_storage_config_for_logging()
+ : value;
+ BULK_LOG("Config: ({}) {} = {}", origin, key, log_value);
+ });
+ }
+
+ LOG("Command line: {}", Util::format_argv_for_logging(argv));
+ LOG("Hostname: {}", Util::get_hostname());
+ LOG("Working directory: {}", ctx.actual_cwd);
+ if (ctx.apparent_cwd != ctx.actual_cwd) {
+ LOG("Apparent working directory: {}", ctx.apparent_cwd);
+ }
+
+ ctx.storage.initialize();
+
+ MTR_BEGIN("main", "find_compiler");
+ find_compiler(ctx, &find_executable, masquerading_as_compiler);
+ MTR_END("main", "find_compiler");
+
+ // Guess compiler after logging the config value in order to be able to
+ // display "compiler_type = auto" before overwriting the value with the
+ // guess.
+ if (ctx.config.compiler_type() == CompilerType::auto_guess) {
+ ctx.config.set_compiler_type(guess_compiler(ctx.orig_args[0]));
+ }
+ DEBUG_ASSERT(ctx.config.compiler_type() != CompilerType::auto_guess);
+
+ LOG("Compiler: {}", ctx.orig_args[0]);
+ LOG("Compiler type: {}", compiler_type_to_string(ctx.config.compiler_type()));
}
// Make a copy of stderr that will not be cached, so things like distcc can
@@ -2187,7 +2212,7 @@ set_up_uncached_err()
static int cache_compilation(int argc, const char* const* argv);
static nonstd::expected<core::StatisticsCounters, Failure>
-do_cache_compilation(Context& ctx, const char* const* argv);
+do_cache_compilation(Context& ctx);
static void
log_result_to_debug_log(Context& ctx)
@@ -2247,6 +2272,23 @@ finalize_at_exit(Context& ctx)
}
}
+ArgvParts
+split_argv(int argc, const char* const* argv)
+{
+ ArgvParts argv_parts;
+ int i = 0;
+ while (i < argc && Util::is_ccache_executable(argv[i])) {
+ argv_parts.masquerading_as_compiler = false;
+ ++i;
+ }
+ while (i < argc && std::strchr(argv[i], '=')) {
+ argv_parts.config_settings.emplace_back(argv[i]);
+ ++i;
+ }
+ argv_parts.compiler_and_args = Args::from_argv(argc - i, argv + i);
+ return argv_parts;
+}
+
// The entry point when invoked to cache a compilation.
static int
cache_compilation(int argc, const char* const* argv)
@@ -2258,15 +2300,21 @@ cache_compilation(int argc, const char* const* argv)
std::optional<uint32_t> original_umask;
std::string saved_temp_dir;
+ auto argv_parts = split_argv(argc, argv);
+ if (argv_parts.compiler_and_args.empty()) {
+ throw core::Fatal("no compiler given, see \"ccache --help\"");
+ }
+
{
Context ctx;
- ctx.initialize();
+ ctx.initialize(std::move(argv_parts.compiler_and_args),
+ argv_parts.config_settings);
SignalHandler signal_handler(ctx);
Finalizer finalizer([&ctx] { finalize_at_exit(ctx); });
- initialize(ctx, argc, argv);
+ initialize(ctx, argv, argv_parts.masquerading_as_compiler);
- const auto result = do_cache_compilation(ctx, argv);
+ const auto result = do_cache_compilation(ctx);
ctx.storage.local.increment_statistics(result ? *result
: result.error().counters());
const auto& counters = ctx.storage.local.get_statistics_updates();
@@ -2324,43 +2372,8 @@ cache_compilation(int argc, const char* const* argv)
}
static nonstd::expected<core::StatisticsCounters, Failure>
-do_cache_compilation(Context& ctx, const char* const* argv)
+do_cache_compilation(Context& ctx)
{
- if (!ctx.config.log_file().empty() || ctx.config.debug()) {
- ctx.config.visit_items([&ctx](const std::string& key,
- const std::string& value,
- const std::string& origin) {
- const auto& log_value =
- key == "remote_storage"
- ? ctx.storage.get_remote_storage_config_for_logging()
- : value;
- BULK_LOG("Config: ({}) {} = {}", origin, key, log_value);
- });
- }
-
- LOG("Command line: {}", Util::format_argv_for_logging(argv));
- LOG("Hostname: {}", Util::get_hostname());
- LOG("Working directory: {}", ctx.actual_cwd);
- if (ctx.apparent_cwd != ctx.actual_cwd) {
- LOG("Apparent working directory: {}", ctx.apparent_cwd);
- }
-
- // Note: do_cache_compilation must not return or use ctx.orig_args before
- // find_compiler is executed.
- MTR_BEGIN("main", "find_compiler");
- find_compiler(ctx, &find_executable);
- MTR_END("main", "find_compiler");
-
- // Guess compiler after logging the config value in order to be able to
- // display "compiler_type = auto" before overwriting the value with the
- // guess.
- if (ctx.config.compiler_type() == CompilerType::auto_guess) {
- ctx.config.set_compiler_type(guess_compiler(ctx.orig_args[0]));
- }
- DEBUG_ASSERT(ctx.config.compiler_type() != CompilerType::auto_guess);
-
- LOG("Compiler type: {}", compiler_type_to_string(ctx.config.compiler_type()));
-
if (ctx.config.disable()) {
LOG_RAW("ccache is disabled");
return nonstd::make_unexpected(Statistic::none);
diff --git a/src/ccache.hpp b/src/ccache.hpp
index 510563a4..a3d0be77 100644
--- a/src/ccache.hpp
+++ b/src/ccache.hpp
@@ -1,5 +1,5 @@
// Copyright (C) 2002-2007 Andrew Tridgell
-// Copyright (C) 2009-2022 Joel Rosdahl and other contributors
+// Copyright (C) 2009-2023 Joel Rosdahl and other contributors
//
// See doc/AUTHORS.adoc for a complete list of contributors.
//
@@ -19,11 +19,13 @@
#pragma once
-#include "Config.hpp"
+#include <Args.hpp>
+#include <Config.hpp>
#include <functional>
#include <string>
#include <string_view>
+#include <vector>
class Context;
@@ -37,6 +39,16 @@ using FindExecutableFunction =
int ccache_main(int argc, const char* const* argv);
// Tested by unit tests.
+struct ArgvParts
+{
+ bool masquerading_as_compiler = true;
+ std::vector<std::string> config_settings;
+ Args compiler_and_args;
+};
+
+ArgvParts split_argv(int argc, const char* const* argv);
+
void find_compiler(Context& ctx,
- const FindExecutableFunction& find_executable_function);
+ const FindExecutableFunction& find_executable_function,
+ bool masquerading_as_compiler);
CompilerType guess_compiler(std::string_view path);
diff --git a/src/core/mainoptions.cpp b/src/core/mainoptions.cpp
index 32a89b4e..e8b46437 100644
--- a/src/core/mainoptions.cpp
+++ b/src/core/mainoptions.cpp
@@ -1,4 +1,4 @@
-// Copyright (C) 2021-2022 Joel Rosdahl and other contributors
+// Copyright (C) 2021-2023 Joel Rosdahl and other contributors
//
// See doc/AUTHORS.adoc for a complete list of contributors.
//
@@ -88,9 +88,13 @@ version.
constexpr const char USAGE_TEXT[] =
R"(Usage:
- {0} [options]
- {0} compiler [compiler options]
- compiler [compiler options] (ccache masquerading as the compiler)
+ {0} [ccache options]
+ {0} [KEY=VALUE ...] compiler [compiler options]
+ compiler [compiler options]
+
+ The first form takes options described below. The second form invokes the
+ compiler, optionally using configuration options from KEY=VALUE arguments.
+ In the third form, ccache is masquerading as the compiler.
Common options:
-c, --cleanup delete old files and recalculate size counters
@@ -115,7 +119,7 @@ Common options:
--recompress-threads THREADS
use up to THREADS threads when recompressing the
cache; default: number of CPUs
- -o, --set-config KEY=VAL set configuration option KEY to value VAL
+ -o, --set-config KEY=VALUE set configuration option KEY to value VALUE
-x, --show-compression show compression statistics
-p, --show-config show current configuration options in
human-readable format
diff --git a/test/suites/config.bash b/test/suites/config.bash
index 97da52c7..7a21f4bb 100644
--- a/test/suites/config.bash
+++ b/test/suites/config.bash
@@ -8,4 +8,16 @@ SUITE_config() {
$CCACHE --show-config >config.txt
expect_contains config.txt "(environment) max_size = 40"
+
+ # -------------------------------------------------------------------------
+ TEST "Command line origin"
+
+ export CCACHE_DEBUG="1"
+ export CCACHE_MAXSIZE="40"
+
+ touch test.c
+ $CCACHE debug=true "max_size = 40" $COMPILER -c test.c
+
+ expect_contains test.o.*.ccache-log "(command line) debug = true"
+ expect_contains test.o.*.ccache-log "(command line) max_size = 40"
}
diff --git a/unittest/test_ccache.cpp b/unittest/test_ccache.cpp
index 30f3bdd7..61671f84 100644
--- a/unittest/test_ccache.cpp
+++ b/unittest/test_ccache.cpp
@@ -1,4 +1,4 @@
-// Copyright (C) 2020-2022 Joel Rosdahl and other contributors
+// Copyright (C) 2020-2023 Joel Rosdahl and other contributors
//
// See doc/AUTHORS.adoc for a complete list of contributors.
//
@@ -38,7 +38,8 @@ TEST_SUITE_BEGIN("ccache");
// Wraps find_compiler in a test friendly interface.
static std::string
-helper(const char* args,
+helper(bool masquerading_as_compiler,
+ const char* args,
const char* config_compiler,
const char* find_executable_return_string = nullptr)
{
@@ -51,10 +52,60 @@ helper(const char* args,
Context ctx;
ctx.config.set_compiler(config_compiler);
ctx.orig_args = Args::from_string(args);
- find_compiler(ctx, find_executable_stub);
+ find_compiler(ctx, find_executable_stub, masquerading_as_compiler);
return ctx.orig_args.to_string();
}
+TEST_CASE("split_argv")
+{
+ ArgvParts argv_parts;
+
+ SUBCASE("empty")
+ {
+ argv_parts = split_argv(0, nullptr);
+ CHECK(argv_parts.masquerading_as_compiler);
+ CHECK(argv_parts.config_settings.empty());
+ CHECK(argv_parts.compiler_and_args.empty());
+ }
+
+ SUBCASE("ccache")
+ {
+ const char* const argv[] = {"ccache"};
+ argv_parts = split_argv(std::size(argv), argv);
+ CHECK(!argv_parts.masquerading_as_compiler);
+ CHECK(argv_parts.config_settings.empty());
+ CHECK(argv_parts.compiler_and_args.empty());
+ }
+
+ SUBCASE("normal compilation")
+ {
+ const char* const argv[] = {"ccache", "gcc", "-c", "test.c"};
+ argv_parts = split_argv(std::size(argv), argv);
+ CHECK(!argv_parts.masquerading_as_compiler);
+ CHECK(argv_parts.config_settings.empty());
+ CHECK(argv_parts.compiler_and_args == Args::from_string("gcc -c test.c"));
+ }
+
+ SUBCASE("only config options")
+ {
+ const char* const argv[] = {"ccache", "foo=bar"};
+ argv_parts = split_argv(std::size(argv), argv);
+ CHECK(!argv_parts.masquerading_as_compiler);
+ CHECK(argv_parts.config_settings == std::vector<std::string>{"foo=bar"});
+ CHECK(argv_parts.compiler_and_args.empty());
+ }
+
+ SUBCASE("compilation with config options")
+ {
+ const char* const argv[] = {"ccache", "a=b", "c = d", "/usr/bin/gcc"};
+ argv_parts = split_argv(std::size(argv), argv);
+ CHECK(!argv_parts.masquerading_as_compiler);
+ CHECK(argv_parts.config_settings
+ == std::vector<std::string>{"a=b", "c = d"});
+ CHECK(argv_parts.compiler_and_args == Args::from_string("/usr/bin/gcc"));
+ }
+}
+
TEST_CASE("find_compiler")
{
SUBCASE("no config")
@@ -62,60 +113,27 @@ TEST_CASE("find_compiler")
// In case the first parameter is gcc it must be a link to ccache, so
// find_compiler should call find_executable to locate the next best "gcc"
// and return that value.
- CHECK(helper("gcc", "") == "resolved_gcc");
- CHECK(helper("relative/gcc", "") == "resolved_gcc");
- CHECK(helper("/absolute/gcc", "") == "resolved_gcc");
+ CHECK(helper(true, "gcc", "") == "resolved_gcc");
+ CHECK(helper(true, "relative/gcc", "") == "resolved_gcc");
+ CHECK(helper(true, "/absolute/gcc", "") == "resolved_gcc");
// 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 gcc", "") == "resolved_gcc");
- CHECK(helper("ccache rel/gcc", "") == "rel/gcc");
- CHECK(helper("ccache /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 gcc", "") == "resolved_gcc");
- CHECK(helper("/abs/ccache rel/gcc", "") == "rel/gcc");
- CHECK(helper("/abs/ccache /abs/gcc", "") == "/abs/gcc");
+ CHECK(helper(false, "gcc", "") == "resolved_gcc");
+ CHECK(helper(false, "rel/gcc", "") == "rel/gcc");
+ CHECK(helper(false, "/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 gcc", "", "ccache"));
- CHECK(helper("ccache rel/gcc", "", "ccache") == "rel/gcc");
- CHECK(helper("ccache /abs/gcc", "", "ccache") == "/abs/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 gcc", "", "ccache"));
- CHECK(helper("/abs/ccache rel/gcc", "", "ccache") == "rel/gcc");
- CHECK(helper("/abs/ccache /a/gcc", "", "ccache") == "/a/gcc");
+ CHECK_THROWS(helper(false, "gcc", "", "ccache"));
+ CHECK(helper(false, "rel/gcc", "", "ccache") == "rel/gcc");
+ CHECK(helper(false, "/abs/gcc", "", "ccache") == "/abs/gcc");
// If compiler is not found then throw, unless the compiler has a relative
// or absolute path.
- CHECK_THROWS(helper("ccache gcc", "", ""));
- CHECK(helper("ccache rel/gcc", "", "") == "rel/gcc");
- CHECK(helper("ccache /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 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 gcc", "") == "resolved_gcc");
- CHECK(helper("ccache ccache gcc", "") == "resolved_gcc");
- CHECK(helper("ccache ccache-1.2.3 ccache gcc", "") == "resolved_gcc");
+ CHECK_THROWS(helper(false, "gcc", "", ""));
+ CHECK(helper(false, "rel/gcc", "", "") == "rel/gcc");
+ CHECK(helper(false, "/abs/gcc", "", "") == "/abs/gcc");
}
SUBCASE("config")
@@ -123,37 +141,23 @@ TEST_CASE("find_compiler")
// In case the first parameter is gcc it must be a link to ccache so use
// config value instead. Don't resolve config if it's a relative or absolute
// path.
- CHECK(helper("gcc", "config") == "resolved_config");
- CHECK(helper("gcc", "rel/config") == "rel/config");
- CHECK(helper("gcc", "/abs/config") == "/abs/config");
- CHECK(helper("rel/gcc", "config") == "resolved_config");
- CHECK(helper("rel/gcc", "rel/config") == "rel/config");
- CHECK(helper("rel/gcc", "/abs/config") == "/abs/config");
- CHECK(helper("/abs/gcc", "config") == "resolved_config");
- CHECK(helper("/abs/gcc", "rel/config") == "rel/config");
- CHECK(helper("/abs/gcc", "/abs/config") == "/abs/config");
+ CHECK(helper(true, "gcc", "config") == "resolved_config");
+ CHECK(helper(true, "gcc", "rel/config") == "rel/config");
+ CHECK(helper(true, "gcc", "/abs/config") == "/abs/config");
+ CHECK(helper(true, "rel/gcc", "config") == "resolved_config");
+ CHECK(helper(true, "rel/gcc", "rel/config") == "rel/config");
+ CHECK(helper(true, "rel/gcc", "/abs/config") == "/abs/config");
+ CHECK(helper(true, "/abs/gcc", "config") == "resolved_config");
+ CHECK(helper(true, "/abs/gcc", "rel/config") == "rel/config");
+ CHECK(helper(true, "/abs/gcc", "/abs/config") == "/abs/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 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 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 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");
+ CHECK(helper(false, "gcc", "config") == "resolved_config");
+ CHECK(helper(false, "gcc", "rel/config") == "rel/config");
+ CHECK(helper(false, "gcc", "/abs/config") == "/abs/config");
+ CHECK(helper(false, "rel/gcc", "config") == "resolved_config");
+ CHECK(helper(false, "/abs/gcc", "config") == "resolved_config");
}
}