summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoel Rosdahl <joel@rosdahl.net>2022-10-19 22:13:21 +0200
committerJoel Rosdahl <joel@rosdahl.net>2022-10-19 22:27:34 +0200
commitb53afeb556d55576ed3683fef6566361464393d5 (patch)
treeb2fd2c70426ed52050b9fef1cac2d653c558ee9f
parent567a1f3c940c881b0718d4b06a04bc2f7f6b5246 (diff)
downloadccache-b53afeb556d55576ed3683fef6566361464393d5.tar.gz
fix: Handle -MD/-MMD when compiling assembler file
When compiling an assembler file, -MD and -MMD don't produce any dependency file, so don't expect one. Also, make sure to fall back to running the real compiler in case an expected output file is missing instead of exiting with an error. Fixes #1189.
-rw-r--r--doc/MANUAL.adoc8
-rw-r--r--src/argprocessing.cpp5
-rw-r--r--src/ccache.cpp73
-rw-r--r--src/core/Result.cpp9
-rw-r--r--src/core/Result.hpp2
-rw-r--r--src/core/Statistics.cpp6
-rw-r--r--test/suites/direct.bash33
7 files changed, 99 insertions, 37 deletions
diff --git a/doc/MANUAL.adoc b/doc/MANUAL.adoc
index 33165bea..e2453a70 100644
--- a/doc/MANUAL.adoc
+++ b/doc/MANUAL.adoc
@@ -1395,12 +1395,12 @@ The compilation failed. No result stored in the cache.
A compiler check program specified by
<<config_compiler_check,*compiler_check*>> (*CCACHE_COMPILERCHECK*) failed.
-| Compiler produced empty output |
-The compiler's output file (typically an object file) was empty after
+| Compiler output file missing |
+One of the files expected to be produced by the compiler was missing after
compilation.
-| Compiler produced no output |
-The compiler's output file (typically an object file) was missing after
+| Compiler produced empty output |
+The compiler's output file (typically an object file) was empty after
compilation.
| Could not find the compiler |
diff --git a/src/argprocessing.cpp b/src/argprocessing.cpp
index d71425fb..b095b7a7 100644
--- a/src/argprocessing.cpp
+++ b/src/argprocessing.cpp
@@ -1293,6 +1293,11 @@ process_args(Context& ctx)
return Statistic::unsupported_source_language;
}
+ if (args_info.actual_language == "assembler") {
+ // -MD/-MMD for assembler file does not produce a dependency file.
+ args_info.generating_dependencies = false;
+ }
+
if (!config.run_second_cpp()
&& (args_info.actual_language == "cu"
|| args_info.actual_language == "cuda")) {
diff --git a/src/ccache.cpp b/src/ccache.cpp
index 861bc5b1..e701e204 100644
--- a/src/ccache.cpp
+++ b/src/ccache.cpp
@@ -874,7 +874,7 @@ find_coverage_file(const Context& ctx)
return {true, found_file, found_file == mangled_form};
}
-static bool
+[[nodiscard]] static bool
write_result(Context& ctx,
const Digest& result_key,
const Stat& obj_stat,
@@ -891,41 +891,58 @@ write_result(Context& ctx,
if (!stdout_data.empty()) {
serializer.add_data(core::Result::FileType::stdout_output, stdout_data);
}
- if (obj_stat) {
- serializer.add_file(core::Result::FileType::object,
- ctx.args_info.output_obj);
+ if (obj_stat
+ && !serializer.add_file(core::Result::FileType::object,
+ ctx.args_info.output_obj)) {
+ LOG("Object file {} missing", ctx.args_info.output_obj);
+ return false;
}
- if (ctx.args_info.generating_dependencies) {
- serializer.add_file(core::Result::FileType::dependency,
- ctx.args_info.output_dep);
+ if (ctx.args_info.generating_dependencies
+ && !serializer.add_file(core::Result::FileType::dependency,
+ ctx.args_info.output_dep)) {
+ LOG("Dependency file {} missing", ctx.args_info.output_dep);
+ return false;
}
if (ctx.args_info.generating_coverage) {
const auto coverage_file = find_coverage_file(ctx);
if (!coverage_file.found) {
+ LOG_RAW("Coverage file not found");
+ return false;
+ }
+ if (!serializer.add_file(coverage_file.mangled
+ ? core::Result::FileType::coverage_mangled
+ : core::Result::FileType::coverage_unmangled,
+ coverage_file.path)) {
+ LOG("Coverage file {} missing", coverage_file.path);
return false;
}
- serializer.add_file(coverage_file.mangled
- ? core::Result::FileType::coverage_mangled
- : core::Result::FileType::coverage_unmangled,
- coverage_file.path);
}
- if (ctx.args_info.generating_stackusage) {
- serializer.add_file(core::Result::FileType::stackusage,
- ctx.args_info.output_su);
+ if (ctx.args_info.generating_stackusage
+ && !serializer.add_file(core::Result::FileType::stackusage,
+ ctx.args_info.output_su)) {
+ LOG("Stack usage file {} missing", ctx.args_info.output_su);
+ return false;
}
- if (ctx.args_info.generating_diagnostics) {
- serializer.add_file(core::Result::FileType::diagnostic,
- ctx.args_info.output_dia);
+ if (ctx.args_info.generating_diagnostics
+ && !serializer.add_file(core::Result::FileType::diagnostic,
+ ctx.args_info.output_dia)) {
+ LOG("Diagnostics file {} missing", ctx.args_info.output_dia);
+ return false;
}
- if (ctx.args_info.seen_split_dwarf && Stat::stat(ctx.args_info.output_dwo)) {
- // Only store .dwo file if it was created by the compiler (GCC and Clang
- // behave differently e.g. for "-gsplit-dwarf -g1").
- serializer.add_file(core::Result::FileType::dwarf_object,
- ctx.args_info.output_dwo);
+ if (ctx.args_info.seen_split_dwarf
+ // Only store .dwo file if it was created by the compiler (GCC and Clang
+ // behave differently e.g. for "-gsplit-dwarf -g1").
+ && Stat::stat(ctx.args_info.output_dwo)
+ && !serializer.add_file(core::Result::FileType::dwarf_object,
+ ctx.args_info.output_dwo)) {
+ LOG("Split dwarf file {} missing", ctx.args_info.output_dwo);
+ return false;
}
- if (!ctx.args_info.output_al.empty()) {
- serializer.add_file(core::Result::FileType::assembler_listing,
- ctx.args_info.output_al);
+ if (!ctx.args_info.output_al.empty()
+ && !serializer.add_file(core::Result::FileType::assembler_listing,
+ ctx.args_info.output_al)) {
+ LOG("Assembler listing file {} missing", ctx.args_info.output_al);
+ return false;
}
core::CacheEntry::Header header(ctx.config, core::CacheEntryType::result);
@@ -1130,8 +1147,10 @@ to_cache(Context& ctx,
}
MTR_BEGIN("result", "result_put");
- write_result(
- ctx, *result_key, obj_stat, result->stdout_data, result->stderr_data);
+ if (!write_result(
+ ctx, *result_key, obj_stat, result->stdout_data, result->stderr_data)) {
+ return nonstd::make_unexpected(Statistic::compiler_produced_no_output);
+ }
MTR_END("result", "result_put");
// Everything OK.
diff --git a/src/core/Result.cpp b/src/core/Result.cpp
index 079923eb..c1f84c64 100644
--- a/src/core/Result.cpp
+++ b/src/core/Result.cpp
@@ -242,14 +242,19 @@ Serializer::add_data(const FileType file_type, nonstd::span<const uint8_t> data)
m_file_entries.push_back(FileEntry{file_type, data});
}
-void
+bool
Serializer::add_file(const FileType file_type, const std::string& path)
{
m_serialized_size += 1 + 1 + 8; // marker + file_type + file_size
if (!should_store_raw_file(m_config, file_type)) {
- m_serialized_size += Stat::stat(path, Stat::OnError::throw_error).size();
+ auto st = Stat::stat(path);
+ if (!st) {
+ return false;
+ }
+ m_serialized_size += st.size();
}
m_file_entries.push_back(FileEntry{file_type, path});
+ return true;
}
uint32_t
diff --git a/src/core/Result.hpp b/src/core/Result.hpp
index 92301e16..3080f719 100644
--- a/src/core/Result.hpp
+++ b/src/core/Result.hpp
@@ -142,7 +142,7 @@ public:
void add_data(FileType file_type, nonstd::span<const uint8_t> data);
// Register a file path whose content should be included in the result.
- void add_file(FileType file_type, const std::string& path);
+ [[nodiscard]] bool add_file(FileType file_type, const std::string& path);
// core::Serializer
uint32_t serialized_size() const override;
diff --git a/src/core/Statistics.cpp b/src/core/Statistics.cpp
index 4952ce20..662b59ba 100644
--- a/src/core/Statistics.cpp
+++ b/src/core/Statistics.cpp
@@ -76,12 +76,12 @@ const StatisticsField k_statistics_fields[] = {
FIELD(cleanups_performed, nullptr),
FIELD(compile_failed, "Compilation failed", FLAG_UNCACHEABLE),
FIELD(compiler_check_failed, "Compiler check failed", FLAG_ERROR),
+ FIELD(compiler_produced_no_output,
+ "Compiler output file missing",
+ FLAG_UNCACHEABLE),
FIELD(compiler_produced_empty_output,
"Compiler produced empty output",
FLAG_UNCACHEABLE),
- FIELD(compiler_produced_no_output,
- "Compiler produced no output",
- FLAG_UNCACHEABLE),
FIELD(compiler_produced_stdout, "Compiler produced stdout", FLAG_UNCACHEABLE),
FIELD(could_not_find_compiler, "Could not find compiler", FLAG_ERROR),
FIELD(could_not_use_modules, "Could not use modules", FLAG_UNCACHEABLE),
diff --git a/test/suites/direct.bash b/test/suites/direct.bash
index 67334eef..0f4d0530 100644
--- a/test/suites/direct.bash
+++ b/test/suites/direct.bash
@@ -499,6 +499,39 @@ fi
expect_equal_object_files reference_test.o test.o
# -------------------------------------------------------------------------
+ TEST "-MD for assembler file with missing dependency file"
+
+ $COMPILER -S test.c
+
+ $CCACHE_COMPILE -c -MD test.s
+ expect_stat direct_cache_hit 0
+ expect_stat preprocessed_cache_hit 0
+ expect_stat cache_miss 1
+
+ $CCACHE_COMPILE -c -MD test.s
+ expect_stat direct_cache_hit 1
+ expect_stat preprocessed_cache_hit 0
+ expect_stat cache_miss 1
+
+ # -------------------------------------------------------------------------
+ TEST "-MD for assembler file with existing dependency file"
+
+ $COMPILER -S test.c
+ echo foo >test.d
+
+ $CCACHE_COMPILE -c -MD test.s
+ expect_stat direct_cache_hit 0
+ expect_stat preprocessed_cache_hit 0
+ expect_stat cache_miss 1
+ rm test.d
+
+ $CCACHE_COMPILE -c -MD test.s
+ expect_stat direct_cache_hit 1
+ expect_stat preprocessed_cache_hit 0
+ expect_stat cache_miss 1
+ expect_missing test.d
+
+ # -------------------------------------------------------------------------
TEST "-ftest-coverage"
cat <<EOF >code.c