}
}
+ // From the manual: "files that were used by the compiler are recorded, but
+ // header files that were *not* used, but would have been used if they
+ // existed, are not". To reduce the risk of getting a false positive hit when
+ // a directory early in the include path now exists, record whether include
+ // directories and similar input paths exist. Note that this is not 100%
+ // waterproof since it only detects newly appearing directories and not newly
+ // appearing header files.
+ if (direct_mode) {
+ std::optional<std::string_view> path;
+ if (compopt_takes_path(args[i]) && i + 1 < args.size()) {
+ path = args[i + 1];
+ } else {
+ auto p = compopt_prefix_takes_path(args[i]);
+ if (p) {
+ path = *p;
+ };
+ }
+ if (path) {
+ hash.hash_delimiter("path exists");
+ hash.hash(FMT("{} {}", *path, fs::exists(*path) ? "1" : "0"));
+ }
+ }
+
if (ctx.args_info.generating_dependencies) {
std::optional<std::string_view> option;
std::optional<std::string_view> value;
return co && (co->type & TAKES_CONCAT_ARG);
}
-// Determines if the prefix of the option matches any option and affects the
-// preprocessor.
bool
compopt_prefix_affects_cpp_output(std::string_view option)
{
return co && (co->type & TAKES_CONCAT_ARG) && (co->type & AFFECTS_CPP);
}
-// Determines if the prefix of the option matches any option and affects the
-// preprocessor.
bool
compopt_prefix_affects_compiler_output(std::string_view option)
{
const CompOpt* co = find_prefix(option);
return co && (co->type & TAKES_CONCAT_ARG) && (co->type & AFFECTS_COMP);
}
+
+std::optional<std::string_view>
+compopt_prefix_takes_path(std::string_view option)
+{
+ // Prefix options have to take concatenated args.
+ const CompOpt* co = find_prefix(option);
+ if (co && (co->type & TAKES_CONCAT_ARG) && (co->type & TAKES_PATH)) {
+ return option.substr(co->name.length());
+ } else {
+ return std::nullopt;
+ }
+}
#pragma once
+#include <optional>
#include <string_view>
bool compopt_short(bool (*fn)(std::string_view option),
bool compopt_takes_concat_arg(std::string_view option);
bool compopt_prefix_affects_cpp_output(std::string_view option);
bool compopt_prefix_affects_compiler_output(std::string_view option);
+std::optional<std::string_view>
+compopt_prefix_takes_path(std::string_view option);
expect_stat files_in_cache 2
expect_equal_content $manifest_file saved.manifest
+
+ # -------------------------------------------------------------------------
+ TEST "Detection of appearing include directories"
+
+ cat <<EOF >main.c
+#include <foo.h>
+EOF
+ backdate main.c
+ mkdir a
+ cat <<EOF >a/foo.h
+char x[] = "content_a";
+EOF
+ backdate a/foo.h
+
+ $CCACHE_COMPILE -c -Ib -Ia main.c
+ expect_contains main.o content_a
+ expect_stat direct_cache_hit 0
+ expect_stat cache_miss 1
+
+ $CCACHE_COMPILE -c -Ib -Ia main.c
+ expect_contains main.o content_a
+ expect_stat direct_cache_hit 1
+ expect_stat cache_miss 1
+
+ mkdir b
+ cat <<EOF >b/foo.h
+char x[] = "content_b";
+EOF
+
+ $CCACHE_COMPILE -c -Ib -Ia main.c
+ expect_contains main.o content_b
+ expect_stat direct_cache_hit 1
+ expect_stat cache_miss 2
+
+ $CCACHE_COMPILE -c -Ib -Ia main.c
+ expect_contains main.o content_b
+ expect_stat direct_cache_hit 2
+ expect_stat cache_miss 2
}
#include <doctest.h>
+#include <iostream> // for doctest stringification of std::string_view
+
bool compopt_verify_sortedness_and_flags();
TEST_SUITE_BEGIN("compopt");
CHECK(!compopt_prefix_affects_compiler_output("-Wa"));
}
+TEST_CASE("prefix_takes_path")
+{
+ CHECK(compopt_prefix_takes_path("-Dfoo") == std::nullopt);
+ CHECK(*compopt_prefix_takes_path("-Ifoo") == "foo");
+}
+
TEST_SUITE_END();