return Statistic::none;
}
+ if (util::starts_with(arg, "-fcoverage-prefix-map=")) {
+ std::string map = arg.substr(arg.find('=') + 1);
+ args_info.coverage_prefix_maps.push_back(map);
+ state.add_common_arg(args[i]);
+ return Statistic::none;
+ }
+
if (util::starts_with(arg, "-fdebug-compilation-dir")
|| util::starts_with(arg, "-ffile-compilation-dir")) {
std::string compilation_dir;
return Statistic::none;
}
+ if (std::string_view prefix{"-fcoverage-compilation-dir="};
+ util::starts_with(arg, prefix)) {
+ args_info.coverage_compilation_dir = arg.substr(prefix.length());
+ state.add_common_arg(args[i]);
+ return Statistic::none;
+ }
+
// Debugging is handled specially, so that we know if we can strip line
// number info.
if (util::starts_with(arg, "-g")) {
}
}
+ std::reverse(args_info.debug_prefix_maps.begin(),
+ args_info.debug_prefix_maps.end());
+ std::reverse(args_info.coverage_prefix_maps.begin(),
+ args_info.coverage_prefix_maps.end());
+
const bool is_link =
!(state.found_c_opt || state.found_dc_opt || state.found_S_opt
|| state.found_syntax_only || state.found_analyze_opt);
// Relocating debuginfo in the format old=new.
std::vector<std::string> debug_prefix_maps;
+ // Relocating coverage info in the format old=new.
+ std::vector<std::string> coverage_prefix_maps;
+
// Compilation directory as passed in -ffile-compilation-dir or
// -fdebug-compilation-dir.
std::string compilation_dir;
+ // Coverage compilation directory as passed in -fcoverage-compilation-dir.
+ std::string coverage_compilation_dir;
+
// Build session file as passed in -fbuild-session-file.
std::filesystem::path build_session_file;
};
return {};
}
+static void
+apply_prefix_remapping(const std::vector<std::string>& maps, fs::path& path)
+{
+ for (const auto& map : maps) {
+ const size_t sep_pos{map.find('=')};
+ if (sep_pos == std::string::npos) {
+ continue;
+ }
+
+ const std::string old_prefix{map.substr(0, sep_pos)};
+ const std::string new_prefix{map.substr(sep_pos + 1)};
+ if (!util::starts_with(util::pstr(path).str(), old_prefix)) {
+ continue;
+ }
+
+ LOG("Relocating from '{}' to '{}' (original path: '{}')",
+ old_prefix,
+ new_prefix,
+ path);
+ fs::path suffix{util::pstr(path).str().substr(old_prefix.size())};
+ path = new_prefix / suffix;
+
+ return;
+ }
+}
+
// update a hash with information common for the direct and preprocessor modes.
static tl::expected<void, Failure>
hash_common_info(const Context& ctx, const util::Args& args, Hash& hash)
// Possibly hash the current working directory.
if (ctx.args_info.generating_debuginfo && ctx.config.hash_dir()) {
- std::string dir_to_hash = util::pstr(ctx.apparent_cwd);
+ fs::path dir_to_hash{ctx.apparent_cwd};
if (!ctx.args_info.compilation_dir.empty()) {
dir_to_hash = ctx.args_info.compilation_dir;
} else {
- for (const auto& map : ctx.args_info.debug_prefix_maps) {
- size_t sep_pos = map.find('=');
- if (sep_pos != std::string::npos) {
- std::string old_path = map.substr(0, sep_pos);
- std::string new_path = map.substr(sep_pos + 1);
- LOG("Relocating debuginfo from {} to {} (CWD: {})",
- old_path,
- new_path,
- ctx.apparent_cwd);
- if (util::starts_with(util::pstr(ctx.apparent_cwd).str(), old_path)) {
- dir_to_hash =
- new_path
- + util::pstr(ctx.apparent_cwd).str().substr(old_path.size());
- }
- }
- }
+ LOG("Applying debug prefix maps to CWD path '{}'", dir_to_hash);
+ apply_prefix_remapping(ctx.args_info.debug_prefix_maps, dir_to_hash);
}
LOG("Hashing CWD {}", dir_to_hash);
hash.hash_delimiter("cwd");
hash.hash("-fprofile-prefix-path=");
return {};
}
+ if (util::starts_with(args[i], "-fcoverage-prefix-map=")) {
+ hash.hash_delimiter("arg");
+ hash.hash("-fcoverage-prefix-map=");
+ return {};
+ }
if (util::starts_with(args[i], "-frandom-seed=")
&& ctx.config.sloppiness().contains(core::Sloppy::random_seed)) {
// For a relative profile directory D the compiler stores $PWD/D as part of
// the profile filename so we need to include the same information in the
// hash.
- const fs::path profile_path =
- ctx.args_info.profile_path.is_absolute()
- ? ctx.args_info.profile_path
- : ctx.apparent_cwd / ctx.args_info.profile_path;
- LOG("Adding profile directory {} to our hash", profile_path);
+ fs::path profile_path = ctx.args_info.profile_path.is_absolute()
+ ? ctx.args_info.profile_path
+ : ctx.apparent_cwd / ctx.args_info.profile_path;
+
+ if (!ctx.args_info.coverage_compilation_dir.empty()) {
+ profile_path = ctx.args_info.coverage_compilation_dir;
+ } else if (!ctx.args_info.coverage_prefix_maps.empty()) {
+ LOG("Applying coverage prefix maps to profile path '{}'", profile_path);
+ apply_prefix_remapping(ctx.args_info.coverage_prefix_maps, profile_path);
+ }
+ LOG("Adding profile directory '{}' to our hash", profile_path);
hash.hash_delimiter("-fprofile-dir");
hash.hash(profile_path);
}
addtest(cleanup)
addtest(color_diagnostics)
addtest(config)
+addtest(coverage_compilation_dir)
+addtest(coverage_prefix_map)
addtest(debug_compilation_dir)
addtest(debug_prefix_map)
addtest(depend)
--- /dev/null
+SUITE_coverage_compilation_dir_PROBE() {
+ touch test.c
+ if ! $COMPILER -c -fcoverage-compilation-dir=dir test.c 2>/dev/null; then
+ echo "-fcoverage-compilation-dir not supported by compiler"
+ fi
+
+ if ! $RUN_WIN_XFAIL; then
+ echo "coverage-compilation-dir tests are broken on Windows."
+ return
+ fi
+}
+
+SUITE_coverage_compilation_dir_SETUP() {
+ unset CCACHE_NODIRECT
+
+ mkdir -p dir1/src dir1/include
+ cat <<EOF >dir1/src/test.c
+#include <stdarg.h>
+#include <test.h>
+EOF
+ cat <<EOF >dir1/include/test.h
+int test;
+EOF
+ cp -r dir1 dir2
+ backdate dir1/include/test.h dir2/include/test.h
+}
+
+SUITE_coverage_compilation_dir() {
+ # -------------------------------------------------------------------------
+ TEST "Cache misses without a configured coverage compilation directory"
+
+ cd dir1
+ CCACHE_BASEDIR=$(pwd) $CCACHE_COMPILE \
+ -I$(pwd)/include \
+ -g \
+ -fprofile-instr-generate \
+ -fdebug-compilation-dir=some_name_not_likely_to_exist_in_path \
+ -c $(pwd)/src/test.c \
+ -o $(pwd)/test.o
+ expect_stat direct_cache_hit 0
+ expect_stat preprocessed_cache_hit 0
+ expect_stat cache_miss 1
+ expect_stat files_in_cache 2
+
+ cd ../dir2
+ CCACHE_BASEDIR=$(pwd) $CCACHE_COMPILE \
+ -I$(pwd)/include \
+ -g \
+ -fprofile-instr-generate \
+ -fdebug-compilation-dir=some_name_not_likely_to_exist_in_path \
+ -c $(pwd)/src/test.c \
+ -o $(pwd)/test.o
+ expect_stat direct_cache_hit 0
+ expect_stat preprocessed_cache_hit 0
+ expect_stat cache_miss 2
+ expect_stat files_in_cache 4
+
+ # -------------------------------------------------------------------------
+ TEST "Cache hits with a configured coverage compilation directory"
+
+ cd dir1
+ CCACHE_BASEDIR=$(pwd) $CCACHE_COMPILE \
+ -I$(pwd)/include \
+ -g \
+ -fprofile-instr-generate \
+ -fdebug-compilation-dir=some_name_not_likely_to_exist_in_path \
+ -fcoverage-compilation-dir=some_other_name_not_likely_to_exist_in_path \
+ -c $(pwd)/src/test.c \
+ -o $(pwd)/test.o
+ expect_stat direct_cache_hit 0
+ expect_stat preprocessed_cache_hit 0
+ expect_stat cache_miss 1
+ expect_stat files_in_cache 2
+
+ cd ../dir2
+ CCACHE_BASEDIR=$(pwd) $CCACHE_COMPILE \
+ -I$(pwd)/include \
+ -g \
+ -fprofile-instr-generate \
+ -fdebug-compilation-dir=some_name_not_likely_to_exist_in_path \
+ -fcoverage-compilation-dir=some_other_name_not_likely_to_exist_in_path \
+ -c $(pwd)/src/test.c \
+ -o $(pwd)/test.o
+ expect_stat direct_cache_hit 1
+ expect_stat preprocessed_cache_hit 0
+ expect_stat cache_miss 1
+ expect_stat files_in_cache 2
+}
--- /dev/null
+SUITE_coverage_prefix_map_PROBE() {
+ touch test.c
+ if ! $COMPILER -c -fcoverage-prefix-map=old=new test.c 2>/dev/null; then
+ echo "-fcoverage-prefix-map not supported by compiler"
+ fi
+
+ if ! $RUN_WIN_XFAIL; then
+ echo "coverage_prefix_map tests are broken on Windows."
+ return
+ fi
+}
+
+SUITE_coverage_prefix_map_SETUP() {
+ unset CCACHE_NODIRECT
+
+ mkdir -p dir1/src dir1/include
+ cat <<EOF >dir1/src/test.c
+#include <stdarg.h>
+#include <test.h>
+EOF
+ cat <<EOF >dir1/include/test.h
+int test;
+EOF
+ cp -r dir1 dir2
+ backdate dir1/include/test.h dir2/include/test.h
+}
+
+SUITE_coverage_prefix_map() {
+ # -------------------------------------------------------------------------
+ TEST "Cache misses without a configured coverage prefix map"
+
+ cd dir1
+ CCACHE_BASEDIR=$(pwd) $CCACHE_COMPILE \
+ -I$(pwd)/include \
+ -g \
+ -fprofile-instr-generate \
+ -fdebug-compilation-dir=some_name_not_likely_to_exist_in_path \
+ -c $(pwd)/src/test.c \
+ -o $(pwd)/test.o
+ expect_stat direct_cache_hit 0
+ expect_stat preprocessed_cache_hit 0
+ expect_stat cache_miss 1
+ expect_stat files_in_cache 2
+
+ cd ../dir2
+ CCACHE_BASEDIR=$(pwd) $CCACHE_COMPILE \
+ -I$(pwd)/include \
+ -g \
+ -fprofile-instr-generate \
+ -fdebug-compilation-dir=some_name_not_likely_to_exist_in_path \
+ -c $(pwd)/src/test.c \
+ -o $(pwd)/test.o
+ expect_stat direct_cache_hit 0
+ expect_stat preprocessed_cache_hit 0
+ expect_stat cache_miss 2
+ expect_stat files_in_cache 4
+
+ # -------------------------------------------------------------------------
+ TEST "Cache hits with a configured coverage prefix map"
+
+ cd dir1
+ CCACHE_BASEDIR=$(pwd) $CCACHE_COMPILE \
+ -I$(pwd)/include \
+ -g \
+ -fprofile-instr-generate \
+ -fdebug-compilation-dir=some_name_not_likely_to_exist_in_path \
+ -fcoverage-prefix-map=$(pwd)=some_other_name_not_likely_to_exist_in_path \
+ -c $(pwd)/src/test.c \
+ -o $(pwd)/test.o
+ expect_stat direct_cache_hit 0
+ expect_stat preprocessed_cache_hit 0
+ expect_stat cache_miss 1
+ expect_stat files_in_cache 2
+
+ cd ../dir2
+ CCACHE_BASEDIR=$(pwd) $CCACHE_COMPILE \
+ -I$(pwd)/include \
+ -g \
+ -fprofile-instr-generate \
+ -fdebug-compilation-dir=some_name_not_likely_to_exist_in_path \
+ -fcoverage-prefix-map=$(pwd)=some_other_name_not_likely_to_exist_in_path \
+ -c $(pwd)/src/test.c \
+ -o $(pwd)/test.o
+ expect_stat direct_cache_hit 1
+ expect_stat preprocessed_cache_hit 0
+ expect_stat cache_miss 1
+ expect_stat files_in_cache 2
+
+ # -------------------------------------------------------------------------
+ TEST "Cache hits with multiple configured coverage prefix maps"
+
+ cd dir1
+ CCACHE_BASEDIR=$(pwd) $CCACHE_COMPILE \
+ -I$(pwd)/include \
+ -g \
+ -fprofile-instr-generate \
+ -fdebug-compilation-dir=some_name_not_likely_to_exist_in_path \
+ -fcoverage-prefix-map=$(pwd)=some_other_name_not_likely_to_exist_in_path \
+ -fcoverage-prefix-map=foo=bar \
+ -c $(pwd)/src/test.c \
+ -o $(pwd)/test.o
+ expect_stat direct_cache_hit 0
+ expect_stat preprocessed_cache_hit 0
+ expect_stat cache_miss 1
+ expect_stat files_in_cache 2
+
+ cd ../dir2
+ CCACHE_BASEDIR=$(pwd) $CCACHE_COMPILE \
+ -I$(pwd)/include \
+ -g \
+ -fprofile-instr-generate \
+ -fdebug-compilation-dir=some_name_not_likely_to_exist_in_path \
+ -fcoverage-prefix-map=$(pwd)=some_other_name_not_likely_to_exist_in_path \
+ -fcoverage-prefix-map=foo=bar \
+ -c $(pwd)/src/test.c \
+ -o $(pwd)/test.o
+ expect_stat direct_cache_hit 1
+ expect_stat preprocessed_cache_hit 0
+ expect_stat cache_miss 1
+ expect_stat files_in_cache 2
+
+ # -------------------------------------------------------------------------
+ TEST "Cache hits with multiple configured coverage prefix maps (different order)"
+
+ cd dir1
+ CCACHE_BASEDIR=$(pwd) $CCACHE_COMPILE \
+ -I$(pwd)/include \
+ -g \
+ -fprofile-instr-generate \
+ -fdebug-compilation-dir=some_name_not_likely_to_exist_in_path \
+ -fcoverage-prefix-map=foo=bar \
+ -fcoverage-prefix-map=$(pwd)=some_other_name_not_likely_to_exist_in_path \
+ -c $(pwd)/src/test.c \
+ -o $(pwd)/test.o
+ expect_stat direct_cache_hit 0
+ expect_stat preprocessed_cache_hit 0
+ expect_stat cache_miss 1
+ expect_stat files_in_cache 2
+
+ cd ../dir2
+ CCACHE_BASEDIR=$(pwd) $CCACHE_COMPILE \
+ -I$(pwd)/include \
+ -g \
+ -fprofile-instr-generate \
+ -fdebug-compilation-dir=some_name_not_likely_to_exist_in_path \
+ -fcoverage-prefix-map=$(pwd)=some_other_name_not_likely_to_exist_in_path \
+ -fcoverage-prefix-map=foo=bar \
+ -c $(pwd)/src/test.c \
+ -o $(pwd)/test.o
+ expect_stat direct_cache_hit 1
+ expect_stat preprocessed_cache_hit 0
+ expect_stat cache_miss 1
+ expect_stat files_in_cache 2
+}