m_extra_args_to_hash.push_back(std::forward<T>(args));
}
+ template<typename T>
+ void
+ add_native_arg(T&& arg)
+ {
+ m_native_args.push_back(std::forward<T>(arg));
+ }
+
ProcessArgsResult
to_result()
{
m_preprocessor_args,
m_compiler_args,
m_extra_args_to_hash,
+ m_native_args,
hash_actual_cwd,
};
}
util::Args m_preprocessor_args;
util::Args m_compiler_args;
util::Args m_extra_args_to_hash;
+ util::Args m_native_args;
};
bool
"Found -frecord-gcc-switches, hashing original command line unmodified");
}
+ // -march=native, -mcpu=native and -mtune=native make the compiler optimize
+ // differently depending on platform.
+ if (arg == "-march=native" || arg == "-mcpu=native"
+ || arg == "-mtune=native") {
+ LOG("Detected system dependent argument: {}", args[i]);
+ state.add_native_arg(args[i]);
+ }
+
// MSVC -u is something else than GCC -u, handle it specially.
if (arg == "-u" && ctx.config.is_compiler_group_msvc()) {
state.add_common_arg(args[i]);
// Arguments not sent to the preprocessor but added to the input hash anyway.
util::Args extra_args_to_hash;
+ // -m*=native arguments to let the preprocessor expand.
+ util::Args native_args;
+
// Whether to include the actual CWD in the input hash.
bool hash_actual_cwd = false;
};
#include <ccache/util/direntry.hpp>
#include <ccache/util/duration.hpp>
#include <ccache/util/environment.hpp>
+#include <ccache/util/exec.hpp>
#include <ccache/util/expected.hpp>
#include <ccache/util/fd.hpp>
#include <ccache/util/file.hpp>
return {};
}
+static tl::expected<void, Failure>
+hash_native_args(Context& ctx, const util::Args& native_args, Hash& hash)
+{
+ if (native_args.empty()) {
+ return {};
+ }
+
+ LOG("Querying compiler about {}", native_args.to_string());
+
+ util::Args args{ctx.orig_args[0], "-###", "-E", "-"};
+ args.push_back(native_args);
+ auto output = util::exec_to_string(args);
+ if (!output) {
+ LOG("Failed to query compiler about {}: {}",
+ native_args.to_string(),
+ output.error());
+ return tl::unexpected(Statistic::internal_error);
+ }
+
+ std::string_view search_string =
+ ctx.config.is_compiler_group_clang()
+ ? "\"-cc1\"" // "/usr/lib/llvm-18/bin/clang" "-cc1" "-triple" ...
+ : "/cc1 -E"; // /usr/libexec/gcc/x86_64-linux-gnu/13/cc1 -E -quiet ...
+ std::optional<std::string_view> line_to_hash;
+ for (const auto line : util::Tokenizer(*output, "\n")) {
+ if (line.find(search_string) != std::string_view::npos) {
+ line_to_hash = line;
+ break;
+ }
+ }
+ if (!line_to_hash) {
+ LOG("Did not find line to hash for {}", native_args.to_string());
+ return tl::unexpected(Statistic::internal_error);
+ }
+
+ hash.hash_delimiter(native_args.to_string());
+
+ // We could potentially work out exactly which options -m*=native expand to
+ // and hash only those, but to keep things simple we include the full line
+ // where cc1 was found for now.
+ hash.hash(*line_to_hash);
+
+ return {};
+}
+
static std::tuple<std::optional<std::string_view>,
std::optional<std::string_view>>
get_option_and_value(std::string_view option, const util::Args& args, size_t& i)
TRY(
hash_common_info(ctx, process_args_result->preprocessor_args, common_hash));
+ TRY(hash_native_args(ctx, process_args_result->native_args, common_hash));
if (process_args_result->hash_actual_cwd) {
common_hash.hash_delimiter("actual_cwd");
--- /dev/null
+#!/bin/bash
+
+args=("$@")
+
+if [ "$1" = "-###" ]; then
+ cat <<EOF >&2
+...
+InstalledDir: /usr/bin
+ (in-process)
+ "/example/bin/clang" "-cc1" $CC1_ARGS
+EOF
+ echo "bin/cc1"
+elif [ "$1" = "-E" ]; then
+ echo preprocessed >"${args[$#-2]}"
+else
+ echo compiled >"${args[$#-2]}"
+fi
--- /dev/null
+#!/bin/bash
+
+args=("$@")
+
+if [ "$1" = "-###" ]; then
+ cat <<EOF >&2
+Using built-in specs.
+...
+COLLECT_GCC_OPTIONS='-E' ...
+ /example/cc1 -E -quiet $CC1_ARGS
+COMPILER_PATH=/example
+EOF
+ echo "bin/cc1"
+elif [ "$1" = "-E" ]; then
+ echo preprocessed >"${args[$#-2]}"
+else
+ echo compiled >"${args[$#-2]}"
+fi
# ---------------------------------------
-all_suites="$(sed -En 's/^addtest\((.*)\)$/\1/p' $(dirname $0)/CMakeLists.txt)"
+export TEST_BASE_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
+all_suites="$(sed -En 's/^addtest\((.*)\)$/\1/p' $(dirname $0)/CMakeLists.txt)"
for suite in $all_suites; do
- . $(dirname $0)/suites/$suite.bash
+ . "$TEST_BASE_DIR"/suites/$suite.bash
done
# ---------------------------------------
expect_stat cache_miss 1
fi
+ # -------------------------------------------------------------------------
+ TEST "-march=native, GCC"
+
+ CC1_ARGS=one $CCACHE "$TEST_BASE_DIR/fake-compilers/gcc-march-native.sh" -march=native -c test1.c
+ expect_stat preprocessed_cache_hit 0
+ expect_stat cache_miss 1
+
+ CC1_ARGS=one $CCACHE "$TEST_BASE_DIR/fake-compilers/gcc-march-native.sh" -march=native -c test1.c
+ expect_stat preprocessed_cache_hit 1
+ expect_stat cache_miss 1
+
+ CC1_ARGS=two $CCACHE "$TEST_BASE_DIR/fake-compilers/gcc-march-native.sh" -march=native -c test1.c
+ expect_stat preprocessed_cache_hit 1
+ expect_stat cache_miss 2
+
+ CC1_ARGS=two $CCACHE "$TEST_BASE_DIR/fake-compilers/gcc-march-native.sh" -march=native -c test1.c
+ expect_stat preprocessed_cache_hit 2
+ expect_stat cache_miss 2
+
+ # -------------------------------------------------------------------------
+ TEST "-march=native, Clang"
+
+ CC1_ARGS=one $CCACHE "$TEST_BASE_DIR/fake-compilers/clang-march-native.sh" -march=native -c test1.c
+ expect_stat preprocessed_cache_hit 0
+ expect_stat cache_miss 1
+
+ CC1_ARGS=one $CCACHE "$TEST_BASE_DIR/fake-compilers/clang-march-native.sh" -march=native -c test1.c
+ expect_stat preprocessed_cache_hit 1
+ expect_stat cache_miss 1
+
+ CC1_ARGS=two $CCACHE "$TEST_BASE_DIR/fake-compilers/clang-march-native.sh" -march=native -c test1.c
+ expect_stat preprocessed_cache_hit 1
+ expect_stat cache_miss 2
+
+ CC1_ARGS=two $CCACHE "$TEST_BASE_DIR/fake-compilers/clang-march-native.sh" -march=native -c test1.c
+ expect_stat preprocessed_cache_hit 2
+ expect_stat cache_miss 2
+
# -------------------------------------------------------------------------
TEST "Handling of compiler-only arguments"