]> git.ipfire.org Git - thirdparty/ccache.git/blame - src/ccache.cpp
fix: Allow nonexistent include files in preprocessor mode
[thirdparty/ccache.git] / src / ccache.cpp
CommitLineData
147ea804 1// Copyright (C) 2009-2023 Joel Rosdahl and other contributors
3c98cd28 2// Copyright (C) 2002-2007 Andrew Tridgell
5a719cab
JR
3//
4// See doc/AUTHORS.adoc for a complete list of contributors.
48e33b2e
JR
5//
6// This program is free software; you can redistribute it and/or modify it
7// under the terms of the GNU General Public License as published by the Free
8// Software Foundation; either version 3 of the License, or (at your option)
9// any later version.
10//
11// This program is distributed in the hope that it will be useful, but WITHOUT
12// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14// more details.
15//
16// You should have received a copy of the GNU General Public License along with
17// this program; if not, write to the Free Software Foundation, Inc., 51
18// Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
f42859a1 19
68e42bd7 20#include "ccache.hpp"
f5795cdb 21
ad52c600 22#include "Args.hpp"
bd9897fb 23#include "ArgsInfo.hpp"
f3652404 24#include "Context.hpp"
c964ad4a 25#include "Depfile.hpp"
a5021452 26#include "Hash.hpp"
1a15286a 27#include "MiniTrace.hpp"
91aa7075 28#include "SignalHandler.hpp"
1a88b504 29#include "Util.hpp"
756e03d1 30#include "argprocessing.hpp"
68e42bd7 31#include "compopt.hpp"
42939f09 32#include "execute.hpp"
68e42bd7
JR
33#include "hashutil.hpp"
34#include "language.hpp"
e53af1a6 35
a03f14b7 36#include <core/CacheEntry.hpp>
9882ac2d 37#include <core/Manifest.hpp>
552d736e 38#include <core/MsvcShowIncludesOutput.hpp>
99c881d1
JR
39#include <core/Result.hpp>
40#include <core/ResultRetriever.hpp>
a28af38b
JR
41#include <core/Statistics.hpp>
42#include <core/StatsLog.hpp>
8630a888 43#include <core/common.hpp>
eb266c99 44#include <core/exceptions.hpp>
32c037e7 45#include <core/mainoptions.hpp>
c7c0837a 46#include <core/types.hpp>
01e72eaa 47#include <storage/Storage.hpp>
54cbb06a 48#include <util/Fd.hpp>
ea9a264e 49#include <util/FileStream.hpp>
f88e6084 50#include <util/Finalizer.hpp>
1da50f6f 51#include <util/TemporaryFile.hpp>
3c98cd28 52#include <util/UmaskScope.hpp>
09c32fb9 53#include <util/environment.hpp>
85f5f8af 54#include <util/expected.hpp>
3c55dbff 55#include <util/file.hpp>
709701ac 56#include <util/filesystem.hpp>
ef96a84a 57#include <util/fmtmacros.hpp>
13cb56cd 58#include <util/logging.hpp>
303c82fe 59#include <util/path.hpp>
3c98cd28 60#include <util/process.hpp>
303c82fe 61#include <util/string.hpp>
f657af6a 62#include <util/time.hpp>
7f034685 63#include <util/wincompat.hpp>
c7c0837a 64
ca9ec9cf
JR
65#include <fcntl.h>
66
eea89d4a 67#include <optional>
60005c83 68#include <string_view>
eea89d4a 69
ca9ec9cf
JR
70#ifdef HAVE_UNISTD_H
71# include <unistd.h>
a4456585
JR
72#endif
73
231fef47 74#include <algorithm>
dd8f65aa 75#include <cmath>
e1a53fd0 76#include <cstring>
3578d20a 77#include <limits>
3c0f600d 78#include <memory>
147ea804 79#include <unordered_map>
89e0e093 80
709701ac 81namespace fs = util::filesystem;
fe3aa934 82
c24446f5 83using core::Statistic;
c86a4628 84using util::DirEntry;
30c10e87 85
48e33b2e
JR
86// This is a string that identifies the current "version" of the hash sum
87// computed by ccache. If, for any reason, we want to force the hash sum to be
88// different for the same input in a new ccache version, we can just change
89// this string. A typical example would be if the format of one of the files
90// stored in the cache changes in a backwards-incompatible way.
e83ac28d 91const char HASH_PREFIX[] = "4";
5ea294ef 92
b3c3e799
JR
93// Search for k_ccache_disable_token within the first
94// k_ccache_disable_search_limit bytes of the input file.
95const size_t k_ccache_disable_search_limit = 4096;
96
97// String to look for when checking whether to disable ccache for the input
98// file.
20438ee6
JR
99const char k_ccache_disable_token[] = {
100 'c', 'c', 'a', 'c', 'h', 'e', ':', 'd', 'i', 's', 'a', 'b', 'l', 'e', '\0'};
b3c3e799 101
e3bba660
AL
102namespace {
103
39606070 104// Return tl::unexpected<Failure> if ccache did not succeed in getting
85f5f8af
JR
105// or putting a result in the cache. If `exit_code` is set, ccache will just
106// exit with that code directly, otherwise execute the real compiler and exit
107// with its exit code. Statistics counters will also be incremented.
108class Failure
e3bba660
AL
109{
110public:
85f5f8af
JR
111 Failure(Statistic statistic);
112 Failure(std::initializer_list<Statistic> statistics);
e3bba660 113
85f5f8af 114 const core::StatisticsCounters& counters() const;
eea89d4a 115 std::optional<int> exit_code() const;
85f5f8af 116 void set_exit_code(int exit_code);
e3bba660
AL
117
118private:
85f5f8af 119 core::StatisticsCounters m_counters;
eea89d4a 120 std::optional<int> m_exit_code;
e3bba660
AL
121};
122
85f5f8af 123inline Failure::Failure(const Statistic statistic) : m_counters({statistic})
e3bba660
AL
124{
125}
126
85f5f8af
JR
127inline Failure::Failure(const std::initializer_list<Statistic> statistics)
128 : m_counters(statistics)
129{
130}
131
132inline const core::StatisticsCounters&
133Failure::counters() const
134{
135 return m_counters;
136}
137
eea89d4a 138inline std::optional<int>
e3bba660
AL
139Failure::exit_code() const
140{
141 return m_exit_code;
142}
143
85f5f8af
JR
144inline void
145Failure::set_exit_code(const int exit_code)
e3bba660 146{
85f5f8af 147 m_exit_code = exit_code;
e3bba660
AL
148}
149
150} // namespace
151
b3c3e799
JR
152static bool
153should_disable_ccache_for_input_file(const std::string& path)
154{
155 auto content =
156 util::read_file_part<std::string>(path, 0, k_ccache_disable_search_limit);
157 return content && content->find(k_ccache_disable_token) != std::string::npos;
158}
159
b453d43a 160static void
f65e8766 161add_prefix(const Context& ctx, Args& args, const std::string& prefix_command)
b453d43a 162{
f65e8766 163 if (prefix_command.empty()) {
f5795cdb
JR
164 return;
165 }
166
ad52c600 167 Args prefix;
32970d78 168 for (const auto& word : util::split_into_strings(prefix_command, " ")) {
451d92c8 169 std::string path = find_executable(ctx, word, ctx.orig_args[0]);
119a7ed0 170 if (path.empty()) {
a4ab84f9 171 throw core::Fatal(FMT("{}: {}", word, strerror(errno)));
f5795cdb
JR
172 }
173
04984326 174 prefix.push_back(path);
f5795cdb 175 }
f5795cdb 176
60904e7b 177 LOG("Using command-line prefix {}", prefix_command);
ad52c600 178 for (size_t i = prefix.size(); i != 0; i--) {
ca403520 179 args.push_front(prefix[i - 1]);
f5795cdb 180 }
b453d43a
MS
181}
182
a181d44d 183static std::string
d96b24a9
JR
184prepare_debug_path(const fs::path& cwd,
185 const fs::path& debug_dir,
653dde81 186 const util::TimePoint& time_of_invocation,
d96b24a9 187 const fs::path& output_obj,
60005c83 188 std::string_view suffix)
a181d44d 189{
d96b24a9
JR
190 auto prefix =
191 debug_dir.empty()
192 ? output_obj
193 : (debug_dir
194 / (output_obj.is_absolute()
195 ? output_obj
196 : fs::weakly_canonical(cwd / output_obj).value_or(output_obj))
197 .relative_path());
fb7ce2f8 198
1adaf8ef
JR
199 // Ignore any error from fs::create_directories since we can't handle an error
200 // in another way in this context. The caller takes care of logging when
201 // trying to open the path for writing.
d96b24a9 202 fs::create_directories(prefix.parent_path());
7c980edc
JR
203
204 char timestamp[100];
f657af6a 205 const auto tm = util::localtime(time_of_invocation);
7c980edc
JR
206 if (tm) {
207 strftime(timestamp, sizeof(timestamp), "%Y%m%d_%H%M%S", &*tm);
208 } else {
209 snprintf(timestamp,
210 sizeof(timestamp),
211 "%llu",
653dde81 212 static_cast<long long unsigned int>(time_of_invocation.sec()));
7c980edc
JR
213 }
214 return FMT("{}.{}_{:06}.ccache-{}",
d96b24a9 215 prefix.string(),
7c980edc 216 timestamp,
653dde81 217 time_of_invocation.nsec_decimal_part() / 1000,
7c980edc 218 suffix);
a181d44d
JR
219}
220
f60a1d9a 221static void
91aa7075 222init_hash_debug(Context& ctx,
a5021452 223 Hash& hash,
f5795cdb 224 char type,
60005c83 225 std::string_view section_name,
f5795cdb 226 FILE* debug_text_file)
4c1a92a0 227{
f8faf9b4 228 if (!ctx.config.debug() || ctx.config.debug_level() < 2) {
f5795cdb
JR
229 return;
230 }
231
d96b24a9
JR
232 const auto path = prepare_debug_path(ctx.apparent_cwd,
233 ctx.config.debug_dir(),
7c980edc
JR
234 ctx.time_of_invocation,
235 ctx.args_info.output_obj,
236 FMT("input-{}", type));
ea9a264e 237 util::FileStream debug_binary_file(path, "wb");
f5795cdb 238 if (debug_binary_file) {
a5021452 239 hash.enable_debug(section_name, debug_binary_file.get(), debug_text_file);
91aa7075 240 ctx.hash_debug_files.push_back(std::move(debug_binary_file));
f5795cdb 241 } else {
60904e7b 242 LOG("Failed to open {}: {}", path, strerror(errno));
f5795cdb 243 }
4c1a92a0
JR
244}
245
4b0be71f 246#ifndef _WIN32
46e9192c
JR
247std::string
248follow_symlinks(const fs::path& path)
249{
4b0be71f 250 // Follow symlinks to the real compiler to learn its name. We're not using
3cacab8d 251 // util::real_path in order to save some unnecessary stat calls.
46e9192c 252 fs::path p = path;
4b0be71f 253 while (true) {
46e9192c 254 auto symlink_target = fs::read_symlink(p);
709701ac 255 if (!symlink_target) {
fe3aa934 256 // Not a symlink.
4b0be71f
JR
257 break;
258 }
709701ac 259 if (symlink_target->is_absolute()) {
46e9192c 260 p = *symlink_target;
4b0be71f 261 } else {
46e9192c 262 p = p.parent_path() / *symlink_target;
4b0be71f
JR
263 }
264 }
46e9192c
JR
265 return p;
266}
4b0be71f
JR
267#endif
268
46e9192c
JR
269static CompilerType
270do_guess_compiler(const fs::path& path)
271{
e2e9eea7 272 const auto name =
46e9192c
JR
273 util::to_lowercase(path.filename().replace_extension("").string());
274 if (name.find("clang-cl") != std::string_view::npos) {
caa5bcbb 275 return CompilerType::clang_cl;
60005c83 276 } else if (name.find("clang") != std::string_view::npos) {
5f3de1d8 277 return CompilerType::clang;
60005c83
JR
278 } else if (name.find("gcc") != std::string_view::npos
279 || name.find("g++") != std::string_view::npos) {
5f3de1d8 280 return CompilerType::gcc;
60005c83 281 } else if (name.find("nvcc") != std::string_view::npos) {
5f3de1d8 282 return CompilerType::nvcc;
6c2f9ee7
DR
283 } else if (name == "icl") {
284 return CompilerType::icl;
e2e9eea7 285 } else if (name == "cl") {
ceecf43d 286 return CompilerType::msvc;
4b0be71f 287 } else {
e2ab1352 288 return CompilerType::other;
f5795cdb 289 }
5f6b6ffd
JR
290}
291
46e9192c
JR
292CompilerType
293guess_compiler(const fs::path& path)
294{
295 CompilerType type = do_guess_compiler(path);
296#ifdef _WIN32
297 return type;
298#else
299 if (type == CompilerType::other) {
300 return do_guess_compiler(follow_symlinks(path));
301 } else {
302 return type;
303 }
304#endif
305}
306
d75dbe26
JR
307// This function hashes an include file and stores the path and hash in
308// ctx.included_files. If the include file is a PCH, cpp_hash is also updated.
309[[nodiscard]] tl::expected<void, Failure>
310remember_include_file(Context& ctx,
311 std::string path,
312 Hash& cpp_hash,
313 bool system,
314 Hash* depend_mode_hash)
e53af1a6 315{
8a58daf2 316 if (path.length() >= 2 && path[0] == '<' && path[path.length() - 1] == '>') {
f5795cdb 317 // Typically <built-in> or <command-line>.
d75dbe26 318 return {};
f5795cdb
JR
319 }
320
236a297a 321 if (path == ctx.args_info.normalized_input_file) {
f5795cdb 322 // Don't remember the input file.
d75dbe26 323 return {};
f5795cdb
JR
324 }
325
c1735710 326 if (system
d75dbe26 327 && ctx.config.sloppiness().contains(core::Sloppy::system_headers)) {
f5795cdb 328 // Don't remember this system header.
d75dbe26 329 return {};
f5795cdb
JR
330 }
331
380beacf 332 // Canonicalize path for comparison; Clang uses ./header.h.
ec94a399 333 if (util::starts_with(path, "./")) {
380beacf
JR
334 path.erase(0, 2);
335 }
336
971f1183
BL
337 if (ctx.included_files.find(path) != ctx.included_files.end()) {
338 // Already known include file.
d75dbe26 339 return {};
971f1183
BL
340 }
341
37e27eb1 342#ifdef _WIN32
f5795cdb
JR
343 {
344 // stat fails on directories on win32.
8a58daf2 345 DWORD attributes = GetFileAttributes(path.c_str());
f5795cdb
JR
346 if (attributes != INVALID_FILE_ATTRIBUTES
347 && attributes & FILE_ATTRIBUTE_DIRECTORY) {
d75dbe26 348 return {};
f5795cdb
JR
349 }
350 }
37e27eb1
RP
351#endif
352
c86a4628
JR
353 DirEntry dir_entry(path, DirEntry::LogOnError::yes);
354 if (!dir_entry.exists()) {
33d390bb
JR
355 if (ctx.config.direct_mode()) {
356 LOG("Include file {} does not exist, disabling direct mode",
357 dir_entry.path());
358 ctx.config.set_direct_mode(false);
359 }
360 return {};
f5795cdb 361 }
c86a4628 362 if (dir_entry.is_directory()) {
f5795cdb 363 // Ignore directory, typically $PWD.
d75dbe26 364 return {};
f5795cdb 365 }
c86a4628 366 if (!dir_entry.is_regular_file()) {
f5795cdb 367 // Device, pipe, socket or other strange creature.
60904e7b 368 LOG("Non-regular include file {}", path);
d75dbe26 369 return tl::unexpected(Statistic::bad_input_file);
f5795cdb
JR
370 }
371
380beacf 372 for (const auto& ignore_header_path : ctx.ignore_header_paths) {
587b0244 373 if (file_path_matches_dir_prefix_or_file(ignore_header_path, path)) {
d75dbe26 374 return {};
f5795cdb
JR
375 }
376 }
377
f5795cdb 378 // Let's hash the include file content.
0e4e4b63 379 Hash::Digest file_digest;
f5795cdb 380
d75dbe26 381 const bool is_pch = is_precompiled_header(path);
f5795cdb 382 if (is_pch) {
e1260404 383 if (ctx.args_info.included_pch_file.empty()) {
60904e7b 384 LOG("Detected use of precompiled header: {}", path);
f5795cdb
JR
385 }
386 bool using_pch_sum = false;
8b0f2eb6 387 if (ctx.config.pch_external_checksum()) {
f5795cdb
JR
388 // hash pch.sum instead of pch when it exists
389 // to prevent hashing a very large .pch file every time
83b50b30 390 std::string pch_sum_path = FMT("{}.sum", path);
c86a4628 391 if (DirEntry(pch_sum_path, DirEntry::LogOnError::yes).is_regular_file()) {
8a58daf2 392 path = std::move(pch_sum_path);
f5795cdb 393 using_pch_sum = true;
60904e7b 394 LOG("Using pch.sum file {}", path);
f5795cdb 395 }
f5795cdb
JR
396 }
397
561be208 398 if (!hash_binary_file(ctx, file_digest, path)) {
d75dbe26 399 return tl::unexpected(Statistic::bad_input_file);
f5795cdb 400 }
a5021452 401 cpp_hash.hash_delimiter(using_pch_sum ? "pch_sum_hash" : "pch_hash");
0e4e4b63 402 cpp_hash.hash(util::format_digest(file_digest));
f5795cdb
JR
403 }
404
8b0f2eb6 405 if (ctx.config.direct_mode()) {
f5795cdb 406 if (!is_pch) { // else: the file has already been hashed.
38ab9d38 407 auto ret = hash_source_code_file(ctx, file_digest, path);
d75dbe26
JR
408 if (ret.contains(HashSourceCode::error)) {
409 return tl::unexpected(Statistic::bad_input_file);
410 }
411 if (ret.contains(HashSourceCode::found_time)) {
412 LOG_RAW("Disabling direct mode");
413 ctx.config.set_direct_mode(false);
f5795cdb
JR
414 }
415 }
416
f5795cdb 417 if (depend_mode_hash) {
a5021452 418 depend_mode_hash->hash_delimiter("include");
0e4e4b63 419 depend_mode_hash->hash(util::format_digest(file_digest));
f5795cdb
JR
420 }
421 }
422
d75dbe26 423 ctx.included_files.emplace(path, file_digest);
5796e9b5 424
d75dbe26 425 return {};
20187332
AT
426}
427
34d666d0 428static void
81115751 429print_included_files(const Context& ctx, FILE* fp)
34d666d0 430{
4812396d
JR
431 for (const auto& [path, digest] : ctx.included_files) {
432 PRINT(fp, "{}\n", path);
5d76845a 433 }
34d666d0
AB
434}
435
48e33b2e
JR
436// This function reads and hashes a file. While doing this, it also does these
437// things:
438//
439// - Makes include file paths for which the base directory is a prefix relative
440// when computing the hash sum.
0246f450 441// - Stores the paths and hashes of included files in ctx.included_files.
39606070 442static tl::expected<void, Failure>
2044fea8 443process_preprocessed_file(Context& ctx, Hash& hash, const std::string& path)
e53af1a6 444{
3c55dbff
JR
445 auto data = util::read_file<std::string>(path);
446 if (!data) {
c5e1f88e 447 LOG("Failed to read {}: {}", path, data.error());
39606070 448 return tl::unexpected(Statistic::internal_error);
f5795cdb
JR
449 }
450
147ea804
JR
451 std::unordered_map<std::string, std::string> relative_inc_path_cache;
452
f5795cdb 453 // Bytes between p and q are pending to be hashed.
3c55dbff
JR
454 char* q = &(*data)[0];
455 const char* p = q;
456 const char* end = p + data->length();
f5795cdb
JR
457
458 // There must be at least 7 characters (# 1 "x") left to potentially find an
459 // include file path.
460 while (q < end - 7) {
60005c83 461 static const std::string_view pragma_gcc_pch_preprocess =
68fa4011 462 "pragma GCC pch_preprocess ";
60005c83 463 static const std::string_view hash_31_command_line_newline =
68fa4011 464 "# 31 \"<command-line>\"\n";
60005c83 465 static const std::string_view hash_32_command_line_2_newline =
68fa4011 466 "# 32 \"<command-line>\" 2\n";
bc97d547
JR
467 // Note: Intentionally not using the string form to avoid false positive
468 // match by ccache itself.
7ee6030b 469 static const char incbin_directive[] = {'.', 'i', 'n', 'c', 'b', 'i', 'n'};
68fa4011 470
f5795cdb
JR
471 // Check if we look at a line containing the file name of an included file.
472 // At least the following formats exist (where N is a positive integer):
473 //
474 // GCC:
475 //
476 // # N "file"
477 // # N "file" N
478 // #pragma GCC pch_preprocess "file"
479 //
480 // HP's compiler:
481 //
482 // #line N "file"
483 //
484 // AIX's compiler:
485 //
486 // #line N "file"
487 // #line N
488 //
489 // Note that there may be other lines starting with '#' left after
490 // preprocessing as well, for instance "# pragma".
491 if (q[0] == '#'
492 // GCC:
493 && ((q[1] == ' ' && q[2] >= '0' && q[2] <= '9')
494 // GCC precompiled header:
ec94a399 495 || util::starts_with(&q[1], pragma_gcc_pch_preprocess)
f5795cdb
JR
496 // HP/AIX:
497 || (q[1] == 'l' && q[2] == 'i' && q[3] == 'n' && q[4] == 'e'
498 && q[5] == ' '))
3c55dbff 499 && (q == data->data() || q[-1] == '\n')) {
f5795cdb
JR
500 // Workarounds for preprocessor linemarker bugs in GCC version 6.
501 if (q[2] == '3') {
ec94a399 502 if (util::starts_with(q, hash_31_command_line_newline)) {
f5795cdb
JR
503 // Bogus extra line with #31, after the regular #1: Ignore the whole
504 // line, and continue parsing.
a5021452 505 hash.hash(p, q - p);
f5795cdb
JR
506 while (q < end && *q != '\n') {
507 q++;
508 }
509 q++;
510 p = q;
511 continue;
ec94a399 512 } else if (util::starts_with(q, hash_32_command_line_2_newline)) {
f5795cdb
JR
513 // Bogus wrong line with #32, instead of regular #1: Replace the line
514 // number with the usual one.
a5021452 515 hash.hash(p, q - p);
f5795cdb
JR
516 q += 1;
517 q[0] = '#';
518 q[1] = ' ';
519 q[2] = '1';
520 p = q;
521 }
522 }
523
524 while (q < end && *q != '"' && *q != '\n') {
525 q++;
526 }
527 if (q < end && *q == '\n') {
528 // A newline before the quotation mark -> no match.
529 continue;
530 }
531 q++;
532 if (q >= end) {
60904e7b 533 LOG_RAW("Failed to parse included file path");
39606070 534 return tl::unexpected(Statistic::internal_error);
f5795cdb
JR
535 }
536 // q points to the beginning of an include file path
a5021452 537 hash.hash(p, q - p);
f5795cdb
JR
538 p = q;
539 while (q < end && *q != '"') {
540 q++;
541 }
eb57a6be
OS
542 if (p == q) {
543 // Skip empty file name.
544 continue;
545 }
f5795cdb
JR
546 // Look for preprocessor flags, after the "filename".
547 bool system = false;
e9915d53 548 const char* r = q + 1;
f5795cdb
JR
549 while (r < end && *r != '\n') {
550 if (*r == '3') { // System header.
551 system = true;
552 }
553 r++;
554 }
147ea804 555
f5795cdb 556 // p and q span the include file path.
35dab842 557 std::string inc_path(p, q - p);
147ea804
JR
558 auto it = relative_inc_path_cache.find(inc_path);
559 if (it == relative_inc_path_cache.end()) {
560 auto rel_inc_path = Util::make_relative_path(
561 ctx, Util::normalize_concrete_absolute_path(inc_path));
562 relative_inc_path_cache.emplace(inc_path, rel_inc_path);
563 inc_path = std::move(rel_inc_path);
564 } else {
565 inc_path = it->second;
566 }
f5795cdb 567
236a297a 568 if ((inc_path != ctx.apparent_cwd) || ctx.config.hash_dir()) {
a5021452 569 hash.hash(inc_path);
f5795cdb
JR
570 }
571
d75dbe26 572 TRY(remember_include_file(ctx, inc_path, hash, system, nullptr));
f5795cdb 573 p = q; // Everything of interest between p and q has been hashed now.
7ee6030b
JR
574 } else if (strncmp(q, incbin_directive, sizeof(incbin_directive)) == 0
575 && ((q[7] == ' '
576 && (q[8] == '"' || (q[8] == '\\' && q[9] == '"')))
577 || q[7] == '"')) {
f5795cdb
JR
578 // An assembler .inc bin (without the space) statement, which could be
579 // part of inline assembly, refers to an external file. If the file
580 // changes, the hash should change as well, but finding out what file to
581 // hash is too hard for ccache, so just bail out.
60904e7b 582 LOG_RAW(
7ee6030b 583 "Found potential unsupported .inc"
f5795cdb 584 "bin directive in source code");
39606070 585 return tl::unexpected(Failure(Statistic::unsupported_code_directive));
a9b30fd3 586 } else if (strncmp(q, "___________", 10) == 0
3c55dbff 587 && (q == data->data() || q[-1] == '\n')) {
f5795cdb
JR
588 // Unfortunately the distcc-pump wrapper outputs standard output lines:
589 // __________Using distcc-pump from /usr/bin
590 // __________Using # distcc servers in pump mode
591 // __________Shutting down distcc-pump include server
5a55014f 592 hash.hash(p, q - p);
f5795cdb
JR
593 while (q < end && *q != '\n') {
594 q++;
595 }
596 if (*q == '\n') {
597 q++;
598 }
599 p = q;
600 continue;
601 } else {
602 q++;
603 }
604 }
605
a5021452 606 hash.hash(p, (end - p));
f5795cdb
JR
607
608 // Explicitly check the .gch/.pch/.pth file as Clang does not include any
609 // mention of it in the preprocessed output.
e1260404
JR
610 if (!ctx.args_info.included_pch_file.empty()) {
611 std::string pch_path =
612 Util::make_relative_path(ctx, ctx.args_info.included_pch_file);
a5021452 613 hash.hash(pch_path);
d75dbe26 614 TRY(remember_include_file(ctx, pch_path, hash, false, nullptr));
f5795cdb
JR
615 }
616
617 bool debug_included = getenv("CCACHE_DEBUG_INCLUDED");
618 if (debug_included) {
35bcc8dc 619 print_included_files(ctx, stdout);
f5795cdb
JR
620 }
621
85f5f8af 622 return {};
e53af1a6 623}
20187332 624
d39fe87b
JR
625// Extract the used includes from the dependency file. Note that we cannot
626// distinguish system headers from other includes here.
d75dbe26 627static tl::expected<Hash::Digest, Failure>
c7c0837a 628result_key_from_depfile(Context& ctx, Hash& hash)
d39fe87b 629{
63e2517d
JR
630 // Make sure that result hash will always be different from the manifest hash
631 // since there otherwise may a storage key collision (in case the dependency
632 // file is empty).
633 hash.hash_delimiter("result");
634
3c55dbff
JR
635 const auto file_content =
636 util::read_file<std::string>(ctx.args_info.output_dep);
637 if (!file_content) {
c5e1f88e 638 LOG("Failed to read dependency file {}: {}",
3c55dbff
JR
639 ctx.args_info.output_dep,
640 file_content.error());
d75dbe26 641 return tl::unexpected(Statistic::bad_input_file);
f5795cdb
JR
642 }
643
3c55dbff 644 for (std::string_view token : Depfile::tokenize(*file_content)) {
60005c83 645 if (util::ends_with(token, ":")) {
aaadd43d
TO
646 continue;
647 }
70dcd287 648 std::string path = Util::make_relative_path(ctx, token);
d75dbe26 649 TRY(remember_include_file(ctx, path, hash, false, &hash));
f5795cdb
JR
650 }
651
f5795cdb
JR
652 // Explicitly check the .gch/.pch/.pth file as it may not be mentioned in the
653 // dependencies output.
e1260404
JR
654 if (!ctx.args_info.included_pch_file.empty()) {
655 std::string pch_path =
656 Util::make_relative_path(ctx, ctx.args_info.included_pch_file);
a5021452 657 hash.hash(pch_path);
d75dbe26 658 TRY(remember_include_file(ctx, pch_path, hash, false, nullptr));
f5795cdb
JR
659 }
660
661 bool debug_included = getenv("CCACHE_DEBUG_INCLUDED");
662 if (debug_included) {
35bcc8dc 663 print_included_files(ctx, stdout);
f5795cdb
JR
664 }
665
a5021452 666 return hash.digest();
cf48b7df 667}
64fc42ca
JR
668
669struct GetTmpFdResult
670{
54cbb06a 671 util::Fd fd;
230ae9ca 672 fs::path path;
64fc42ca
JR
673};
674
675static GetTmpFdResult
676get_tmp_fd(Context& ctx,
677 const std::string_view description,
678 const bool capture_output)
679{
680 if (capture_output) {
1da50f6f
JR
681 auto tmp_stdout =
682 util::value_or_throw<core::Fatal>(util::TemporaryFile::create(
683 FMT("{}/{}", ctx.config.temporary_dir(), description)));
230ae9ca 684 ctx.register_pending_tmp_file(tmp_stdout.path.string());
64fc42ca
JR
685 return {std::move(tmp_stdout.fd), std::move(tmp_stdout.path)};
686 } else {
687 const auto dev_null_path = util::get_dev_null_path();
54cbb06a 688 return {util::Fd(open(dev_null_path, O_WRONLY | O_BINARY)), dev_null_path};
64fc42ca
JR
689 }
690}
691
692struct DoExecuteResult
693{
694 int exit_status;
e9ddf680
JR
695 util::Bytes stdout_data;
696 util::Bytes stderr_data;
64fc42ca
JR
697};
698
7d679310 699// Extract the used includes from /showIncludes output in stdout. Note that we
b1348e5f 700// cannot distinguish system headers from other includes here.
d75dbe26 701static tl::expected<Hash::Digest, Failure>
b1348e5f
OS
702result_key_from_includes(Context& ctx, Hash& hash, std::string_view stdout_data)
703{
a68cae90 704 for (std::string_view include : core::MsvcShowIncludesOutput::get_includes(
b1348e5f 705 stdout_data, ctx.config.msvc_dep_prefix())) {
a68cae90
JR
706 const std::string path = Util::make_relative_path(
707 ctx, Util::normalize_abstract_absolute_path(include));
d75dbe26 708 TRY(remember_include_file(ctx, path, hash, false, &hash));
b1348e5f
OS
709 }
710
711 // Explicitly check the .pch file as it is not mentioned in the
712 // includes output.
713 if (!ctx.args_info.included_pch_file.empty()) {
714 std::string pch_path =
715 Util::make_relative_path(ctx, ctx.args_info.included_pch_file);
716 hash.hash(pch_path);
d75dbe26 717 TRY(remember_include_file(ctx, pch_path, hash, false, nullptr));
b1348e5f
OS
718 }
719
720 const bool debug_included = getenv("CCACHE_DEBUG_INCLUDED");
721 if (debug_included) {
722 print_included_files(ctx, stdout);
723 }
724
725 return hash.digest();
726}
727
1c6ccf18
MW
728// Execute the compiler/preprocessor, with logic to retry without requesting
729// colored diagnostics messages if that fails.
39606070 730static tl::expected<DoExecuteResult, Failure>
64fc42ca 731do_execute(Context& ctx, Args& args, const bool capture_stdout = true)
1c6ccf18 732{
3c98cd28 733 util::UmaskScope umask_scope(ctx.original_umask);
106a1d22 734
755359d9
JR
735 if (ctx.diagnostics_color_failed) {
736 DEBUG_ASSERT(ctx.config.compiler_type() == CompilerType::gcc);
50e8d229 737 args.erase_last("-fdiagnostics-color");
1c6ccf18 738 }
64fc42ca
JR
739
740 auto tmp_stdout = get_tmp_fd(ctx, "stdout", capture_stdout);
741 auto tmp_stderr = get_tmp_fd(ctx, "stderr", true);
742
ea433578
AS
743 int status = execute(ctx,
744 args.to_argv().data(),
53b35a42 745 std::move(tmp_stdout.fd),
ea433578 746 std::move(tmp_stderr.fd));
1c6ccf18 747 if (status != 0 && !ctx.diagnostics_color_failed
e2ab1352 748 && ctx.config.compiler_type() == CompilerType::gcc) {
3c55dbff
JR
749 const auto errors = util::read_file<std::string>(tmp_stderr.path);
750 if (errors && errors->find("fdiagnostics-color") != std::string::npos) {
755359d9
JR
751 // GCC versions older than 4.9 don't understand -fdiagnostics-color, and
752 // non-GCC compilers misclassified as CompilerType::gcc might not do it
753 // either. We assume that if the error message contains
754 // "fdiagnostics-color" then the compilation failed due to
755 // -fdiagnostics-color being unsupported and we then retry without the
756 // flag. (Note that there intentionally is no leading dash in
757 // "fdiagnostics-color" since some compilers don't include the dash in the
758 // error message.)
60904e7b 759 LOG_RAW("-fdiagnostics-color is unsupported; trying again without it");
53b35a42 760
1c6ccf18 761 ctx.diagnostics_color_failed = true;
64fc42ca 762 return do_execute(ctx, args, capture_stdout);
1c6ccf18
MW
763 }
764 }
64fc42ca 765
e9ddf680 766 util::Bytes stdout_data;
3c55dbff 767 if (capture_stdout) {
f8b81c2b 768 auto stdout_data_result = util::read_file<util::Bytes>(tmp_stdout.path);
3c55dbff 769 if (!stdout_data_result) {
c5e1f88e
JR
770 LOG("Failed to read {} (cleanup in progress?): {}",
771 tmp_stdout.path,
772 stdout_data_result.error());
39606070 773 return tl::unexpected(Statistic::missing_cache_file);
3c55dbff 774 }
e9ddf680 775 stdout_data = *stdout_data_result;
3c55dbff
JR
776 }
777
f8b81c2b 778 auto stderr_data_result = util::read_file<util::Bytes>(tmp_stderr.path);
3c55dbff 779 if (!stderr_data_result) {
c5e1f88e
JR
780 LOG("Failed to read {} (cleanup in progress?): {}",
781 tmp_stderr.path,
782 stderr_data_result.error());
39606070 783 return tl::unexpected(Statistic::missing_cache_file);
64fc42ca 784 }
3c55dbff 785
e9ddf680 786 return DoExecuteResult{status, stdout_data, *stderr_data_result};
1c6ccf18
MW
787}
788
d663cb51
JR
789static void
790read_manifest(Context& ctx, nonstd::span<const uint8_t> cache_entry_data)
9882ac2d 791{
a03f14b7 792 try {
a03f14b7
JR
793 core::CacheEntry cache_entry(cache_entry_data);
794 cache_entry.verify_checksum();
d663cb51 795 ctx.manifest.read(cache_entry.payload());
a03f14b7 796 } catch (const core::Error& e) {
d663cb51 797 LOG("Error reading manifest: {}", e.what());
9882ac2d 798 }
9882ac2d
JR
799}
800
801static void
d663cb51 802update_manifest(Context& ctx,
0e4e4b63
JR
803 const Hash::Digest& manifest_key,
804 const Hash::Digest& result_key)
38301c0d 805{
c7c0837a 806 if (ctx.config.read_only() || ctx.config.read_only_direct()) {
f5795cdb
JR
807 return;
808 }
809
792b27b8
JR
810 ASSERT(ctx.config.direct_mode());
811
1897fd5e 812 MTR_SCOPE("manifest", "manifest_put");
fd8474e3 813
3ec65766 814 // ctime() may be 0, so we have to check time_of_invocation against
3fcfd751
JR
815 // MAX(mtime, ctime).
816 //
817 // ccache only reads mtime/ctime if file_stat_matches sloppiness is enabled,
818 // so mtimes/ctimes are stored as a dummy value (-1) if not enabled. This
819 // reduces the number of file_info entries for the common case.
fd8474e3 820 const bool save_timestamp =
03023ee7 821 (ctx.config.sloppiness().contains(core::Sloppy::file_stat_matches))
fd8474e3 822 || ctx.args_info.output_is_precompiled_header;
947030fd 823
d663cb51 824 const bool added = ctx.manifest.add_result(
3fcfd751 825 result_key, ctx.included_files, [&](const std::string& path) {
c86a4628 826 DirEntry de(path, DirEntry::LogOnError::yes);
3fcfd751
JR
827 bool cache_time =
828 save_timestamp
3ec65766 829 && ctx.time_of_invocation > std::max(de.mtime(), de.ctime());
3fcfd751 830 return core::Manifest::FileStats{
c86a4628
JR
831 de.size(),
832 de.is_regular_file() && cache_time ? de.mtime() : util::TimePoint(),
833 de.is_regular_file() && cache_time ? de.ctime() : util::TimePoint(),
3fcfd751
JR
834 };
835 });
d663cb51 836 if (added) {
0e4e4b63 837 LOG("Added result key to manifest {}", util::format_digest(manifest_key));
d663cb51
JR
838 core::CacheEntry::Header header(ctx.config, core::CacheEntryType::manifest);
839 ctx.storage.put(manifest_key,
840 core::CacheEntryType::manifest,
841 core::CacheEntry::serialize(header, ctx.manifest));
d663cb51 842 } else {
0e4e4b63
JR
843 LOG("Did not add result key to manifest {}",
844 util::format_digest(manifest_key));
d663cb51 845 }
89e0e093
JR
846}
847
1da6d7ed
JR
848struct FindCoverageFileResult
849{
850 bool found;
851 std::string path;
852 bool mangled;
853};
854
855static FindCoverageFileResult
856find_coverage_file(const Context& ctx)
857{
858 // GCC 9+ writes coverage data for /dir/to/example.o to #dir#to#example.gcno
859 // (in CWD) if -fprofile-dir=DIR is present (regardless of DIR) instead of the
860 // traditional /dir/to/example.gcno.
861
99c881d1
JR
862 std::string mangled_form = core::Result::gcno_file_in_mangled_form(ctx);
863 std::string unmangled_form = core::Result::gcno_file_in_unmangled_form(ctx);
1da6d7ed 864 std::string found_file;
c86a4628 865 if (DirEntry(mangled_form).is_regular_file()) {
60904e7b 866 LOG("Found coverage file {}", mangled_form);
1da6d7ed
JR
867 found_file = mangled_form;
868 }
c86a4628 869 if (DirEntry(unmangled_form).is_regular_file()) {
60904e7b 870 LOG("Found coverage file {}", unmangled_form);
1da6d7ed 871 if (!found_file.empty()) {
60904e7b 872 LOG_RAW("Found two coverage files, cannot continue");
1da6d7ed
JR
873 return {};
874 }
875 found_file = unmangled_form;
876 }
877 if (found_file.empty()) {
60904e7b 878 LOG("No coverage file found (tried {} and {}), cannot continue",
1da6d7ed
JR
879 unmangled_form,
880 mangled_form);
881 return {};
882 }
883 return {true, found_file, found_file == mangled_form};
884}
885
b53afeb5 886[[nodiscard]] static bool
c7c0837a 887write_result(Context& ctx,
0e4e4b63 888 const Hash::Digest& result_key,
e9ddf680
JR
889 const util::Bytes& stdout_data,
890 const util::Bytes& stderr_data)
c7c0837a 891{
99c881d1 892 core::Result::Serializer serializer(ctx.config);
c7c0837a 893
ef19b0f0 894 if (!stderr_data.empty()) {
99c881d1 895 serializer.add_data(core::Result::FileType::stderr_output, stderr_data);
c7c0837a 896 }
d981aee3
LL
897 // Write stdout only after stderr (better with MSVC), as ResultRetriever
898 // will later print process them in the order they are read.
ef19b0f0 899 if (!stdout_data.empty()) {
99c881d1 900 serializer.add_data(core::Result::FileType::stdout_output, stdout_data);
d981aee3 901 }
c86a4628 902 if (ctx.args_info.expect_output_obj
b53afeb5
JR
903 && !serializer.add_file(core::Result::FileType::object,
904 ctx.args_info.output_obj)) {
905 LOG("Object file {} missing", ctx.args_info.output_obj);
906 return false;
c7c0837a 907 }
b53afeb5
JR
908 if (ctx.args_info.generating_dependencies
909 && !serializer.add_file(core::Result::FileType::dependency,
910 ctx.args_info.output_dep)) {
911 LOG("Dependency file {} missing", ctx.args_info.output_dep);
912 return false;
c7c0837a
JR
913 }
914 if (ctx.args_info.generating_coverage) {
915 const auto coverage_file = find_coverage_file(ctx);
916 if (!coverage_file.found) {
b53afeb5
JR
917 LOG_RAW("Coverage file not found");
918 return false;
919 }
920 if (!serializer.add_file(coverage_file.mangled
921 ? core::Result::FileType::coverage_mangled
922 : core::Result::FileType::coverage_unmangled,
923 coverage_file.path)) {
924 LOG("Coverage file {} missing", coverage_file.path);
85f5f8af 925 return false;
c7c0837a 926 }
c7c0837a 927 }
b53afeb5
JR
928 if (ctx.args_info.generating_stackusage
929 && !serializer.add_file(core::Result::FileType::stackusage,
930 ctx.args_info.output_su)) {
931 LOG("Stack usage file {} missing", ctx.args_info.output_su);
932 return false;
c7c0837a 933 }
b53afeb5
JR
934 if (ctx.args_info.generating_diagnostics
935 && !serializer.add_file(core::Result::FileType::diagnostic,
936 ctx.args_info.output_dia)) {
937 LOG("Diagnostics file {} missing", ctx.args_info.output_dia);
938 return false;
c7c0837a 939 }
b53afeb5
JR
940 if (ctx.args_info.seen_split_dwarf
941 // Only store .dwo file if it was created by the compiler (GCC and Clang
942 // behave differently e.g. for "-gsplit-dwarf -g1").
c86a4628 943 && DirEntry(ctx.args_info.output_dwo).is_regular_file()
b53afeb5
JR
944 && !serializer.add_file(core::Result::FileType::dwarf_object,
945 ctx.args_info.output_dwo)) {
946 LOG("Split dwarf file {} missing", ctx.args_info.output_dwo);
947 return false;
c7c0837a 948 }
b53afeb5
JR
949 if (!ctx.args_info.output_al.empty()
950 && !serializer.add_file(core::Result::FileType::assembler_listing,
951 ctx.args_info.output_al)) {
952 LOG("Assembler listing file {} missing", ctx.args_info.output_al);
953 return false;
b4dfd7b5 954 }
c7c0837a 955
a03f14b7
JR
956 core::CacheEntry::Header header(ctx.config, core::CacheEntryType::result);
957 const auto cache_entry_data = core::CacheEntry::serialize(header, serializer);
d5782080
JR
958
959 if (!ctx.config.remote_only()) {
960 const auto& raw_files = serializer.get_raw_files();
961 if (!raw_files.empty()) {
962 ctx.storage.local.put_raw_files(result_key, raw_files);
963 }
a03f14b7 964 }
d5782080 965
d663cb51 966 ctx.storage.put(result_key, core::CacheEntryType::result, cache_entry_data);
99c881d1 967
85f5f8af 968 return true;
c7c0837a
JR
969}
970
e9ddf680
JR
971static util::Bytes
972rewrite_stdout_from_compiler(const Context& ctx, util::Bytes&& stdout_data)
ef19b0f0 973{
ff10b348
OS
974 using util::Tokenizer;
975 using Mode = Tokenizer::Mode;
976 using IncludeDelimiter = Tokenizer::IncludeDelimiter;
2044fea8 977 if (!stdout_data.empty()) {
3ec0d4ec 978 util::Bytes new_stdout_data;
e9ddf680
JR
979 for (const auto line : Tokenizer(util::to_string_view(stdout_data),
980 "\n",
981 Mode::include_empty,
982 IncludeDelimiter::yes)) {
ef19b0f0 983 if (util::starts_with(line, "__________")) {
8630a888 984 core::send_to_console(ctx, line, STDOUT_FILENO);
236a297a
VV
985 }
986 // Ninja uses the lines with 'Note: including file: ' to determine the
987 // used headers. Headers within basedir need to be changed into relative
988 // paths because otherwise Ninja will use the abs path to original header
989 // to check if a file needs to be recompiled.
990 else if (ctx.config.compiler_type() == CompilerType::msvc
991 && !ctx.config.base_dir().empty()
b1348e5f 992 && util::starts_with(line, ctx.config.msvc_dep_prefix())) {
236a297a
VV
993 std::string orig_line(line.data(), line.length());
994 std::string abs_inc_path =
b1348e5f 995 util::replace_first(orig_line, ctx.config.msvc_dep_prefix(), "");
236a297a
VV
996 abs_inc_path = util::strip_whitespace(abs_inc_path);
997 std::string rel_inc_path = Util::make_relative_path(
998 ctx, Util::normalize_concrete_absolute_path(abs_inc_path));
999 std::string line_with_rel_inc =
1000 util::replace_first(orig_line, abs_inc_path, rel_inc_path);
a71cb96c 1001 new_stdout_data.insert(new_stdout_data.end(),
3ec0d4ec
JR
1002 line_with_rel_inc.data(),
1003 line_with_rel_inc.size());
ef19b0f0 1004 } else {
3ec0d4ec 1005 new_stdout_data.insert(new_stdout_data.end(), line.data(), line.size());
ef19b0f0
JR
1006 }
1007 }
3ec0d4ec 1008 return new_stdout_data;
ef19b0f0
JR
1009 } else {
1010 return std::move(stdout_data);
1011 }
1012}
1013
d75dbe26
JR
1014static std::string
1015format_epoch_time(const util::TimePoint& tp)
1016{
1017 return FMT("{}.{:09}", tp.sec(), tp.nsec_decimal_part());
1018}
1019
1020static bool
1021source_file_is_too_new(const Context& ctx, const fs::path& path)
1022{
1023 const bool sloppy_ctime =
1024 ctx.config.sloppiness().contains(core::Sloppy::include_file_ctime);
1025 const bool sloppy_mtime =
1026 ctx.config.sloppiness().contains(core::Sloppy::include_file_mtime);
1027
1028 if ((sloppy_mtime && sloppy_ctime) || util::is_dev_null_path(path)) {
1029 return false;
1030 }
1031
1032 // It's not enough to check if mtime/ctime >= ctx.time_of_invocation since
1033 // filesystem timestamps are granular. See the comment for
1034 // InodeCache::InodeCache for details.
1035 //
1036 // A relatively small safety margin is used in this case to make things safe
1037 // on common filesystems while also not bailing out when creating a source
1038 // file reasonably close in time before the compilation.
1039 const util::Duration min_age(0, 100'000'000); // 0.1 s
1040 util::TimePoint deadline = ctx.time_of_invocation + min_age;
1041
1042 DirEntry dir_entry(path);
1043
1044 if (!sloppy_mtime && dir_entry.mtime() >= deadline) {
1045 LOG(
1046 "{} was modified near or after invocation (mtime {}, invocation time {})",
1047 dir_entry.path(),
1048 format_epoch_time(dir_entry.mtime()),
1049 format_epoch_time(ctx.time_of_invocation));
1050 return true;
1051 }
1052
1053 // The same logic as above applies to the change time of the file.
1054 if (!sloppy_ctime && dir_entry.ctime() >= deadline) {
1055 LOG(
1056 "{} had status change near or after invocation (ctime {}, invocation"
1057 " time {})",
1058 dir_entry.path(),
1059 format_epoch_time(dir_entry.ctime()),
1060 format_epoch_time(ctx.time_of_invocation));
1061 return true;
1062 }
1063
1064 return false;
1065}
1066
c7c0837a 1067// Run the real compiler and put the result in cache. Returns the result key.
39606070 1068static tl::expected<Hash::Digest, Failure>
272fb0ed 1069to_cache(Context& ctx,
ad52c600 1070 Args& args,
0e4e4b63 1071 std::optional<Hash::Digest> result_key,
656b50a9 1072 const Args& depend_extra_args,
a5021452 1073 Hash* depend_mode_hash)
f42859a1 1074{
caa5bcbb 1075 if (ctx.config.is_compiler_group_msvc()) {
56c18b0d
CA
1076 args.push_back(fmt::format("-Fo{}", ctx.args_info.output_obj));
1077 } else {
1078 args.push_back("-o");
1079 args.push_back(ctx.args_info.output_obj);
1080 }
f5795cdb 1081
c86a4628
JR
1082 if (ctx.config.hard_link()
1083 && !util::is_dev_null_path(ctx.args_info.output_obj)) {
f5795cdb
JR
1084 // Workaround for Clang bug where it overwrites an existing object file
1085 // when it's compiling an assembler file, see
1086 // <https://bugs.llvm.org/show_bug.cgi?id=39782>.
19f67009 1087 util::remove_nfs_safe(ctx.args_info.output_obj);
f5795cdb
JR
1088 }
1089
fdddb0b6 1090 if (ctx.args_info.generating_diagnostics) {
a0208732 1091 args.push_back("--serialize-diagnostics");
04984326 1092 args.push_back(ctx.args_info.output_dia);
f5795cdb
JR
1093 }
1094
dfc7a901
JR
1095 if (ctx.args_info.seen_double_dash) {
1096 args.push_back("--");
1097 }
1098
8b0f2eb6 1099 if (ctx.config.run_second_cpp()) {
04984326 1100 args.push_back(ctx.args_info.input_file);
f5795cdb 1101 } else {
04984326 1102 args.push_back(ctx.i_tmpfile);
f5795cdb
JR
1103 }
1104
690766ef 1105 if (ctx.args_info.seen_split_dwarf) {
f5795cdb
JR
1106 // Remove any pre-existing .dwo file since we want to check if the compiler
1107 // produced one, intentionally not using x_unlink or tmp_unlink since we're
1108 // not interested in logging successful deletions or failures due to
ef5fde60 1109 // nonexistent .dwo files.
26fd7eab
JR
1110 if (unlink(ctx.args_info.output_dwo.c_str()) != 0 && errno != ENOENT
1111 && errno != ESTALE) {
60904e7b 1112 LOG("Failed to unlink {}: {}", ctx.args_info.output_dwo, strerror(errno));
39606070 1113 return tl::unexpected(Statistic::bad_output_file);
f5795cdb
JR
1114 }
1115 }
1116
60904e7b 1117 LOG_RAW("Running real compiler");
f5795cdb 1118 MTR_BEGIN("execute", "compiler");
62e5c432 1119
39606070 1120 tl::expected<DoExecuteResult, Failure> result;
8b0f2eb6 1121 if (!ctx.config.depend_mode()) {
64fc42ca 1122 result = do_execute(ctx, args);
a1bc04de 1123 args.pop_back(3);
f5795cdb 1124 } else {
f5795cdb
JR
1125 // Use the original arguments (including dependency options) in depend
1126 // mode.
ad52c600 1127 Args depend_mode_args = ctx.orig_args;
c1fad9ca 1128 depend_mode_args.erase_with_prefix("--ccache-");
e58da986
JR
1129 // Add depend_mode_args directly after the compiler. We can't add them last
1130 // since options then may be placed after a "--" option.
1131 depend_mode_args.insert(1, depend_extra_args);
f65e8766 1132 add_prefix(ctx, depend_mode_args, ctx.config.prefix_command());
f5795cdb 1133
64fc42ca 1134 result = do_execute(ctx, depend_mode_args);
f5795cdb
JR
1135 }
1136 MTR_END("execute", "compiler");
1137
64fc42ca 1138 if (!result) {
39606070 1139 return tl::unexpected(result.error());
85f5f8af
JR
1140 }
1141
64fc42ca
JR
1142 // Merge stderr from the preprocessor (if any) and stderr from the real
1143 // compiler.
1144 if (!ctx.cpp_stderr_data.empty()) {
e9ddf680
JR
1145 result->stderr_data.insert(result->stderr_data.begin(),
1146 ctx.cpp_stderr_data.begin(),
1147 ctx.cpp_stderr_data.end());
f5795cdb
JR
1148 }
1149
64fc42ca
JR
1150 result->stdout_data =
1151 rewrite_stdout_from_compiler(ctx, std::move(result->stdout_data));
ef19b0f0 1152
64fc42ca
JR
1153 if (result->exit_status != 0) {
1154 LOG("Compiler gave exit status {}", result->exit_status);
f5795cdb 1155
1c6ccf18 1156 // We can output stderr immediately instead of rerunning the compiler.
8630a888 1157 core::send_to_console(
e9ddf680 1158 ctx, util::to_string_view(result->stderr_data), STDERR_FILENO);
8630a888 1159 core::send_to_console(
bda468cf 1160 ctx,
552d736e 1161 util::to_string_view(core::MsvcShowIncludesOutput::strip_includes(
bda468cf
OS
1162 ctx, std::move(result->stdout_data))),
1163 STDOUT_FILENO);
f5795cdb 1164
85f5f8af 1165 auto failure = Failure(Statistic::compile_failed);
64fc42ca 1166 failure.set_exit_code(result->exit_status);
39606070 1167 return tl::unexpected(failure);
f5795cdb
JR
1168 }
1169
8b0f2eb6 1170 if (ctx.config.depend_mode()) {
706f7443 1171 ASSERT(depend_mode_hash);
b1348e5f 1172 if (ctx.args_info.generating_dependencies) {
d75dbe26
JR
1173 auto key = result_key_from_depfile(ctx, *depend_mode_hash);
1174 if (!key) {
1175 return tl::unexpected(key.error());
1176 }
1177 result_key = *key;
b1348e5f 1178 } else if (ctx.args_info.generating_includes) {
d75dbe26 1179 auto key = result_key_from_includes(
b1348e5f 1180 ctx, *depend_mode_hash, util::to_string_view(result->stdout_data));
d75dbe26
JR
1181 if (!key) {
1182 return tl::unexpected(key.error());
1183 }
1184 result_key = *key;
b1348e5f
OS
1185 } else {
1186 ASSERT(false);
1187 }
58a2dfc7 1188 LOG_RAW("Got result key from dependency file");
0e4e4b63 1189 LOG("Result key: {}", util::format_digest(*result_key));
f5795cdb
JR
1190 }
1191
c7c0837a
JR
1192 ASSERT(result_key);
1193
d75dbe26
JR
1194 if (source_file_is_too_new(ctx, ctx.args_info.input_file)) {
1195 return tl::unexpected(Statistic::modified_input_file);
1196 }
1197 for (const auto& [path, digest] : ctx.included_files) {
1198 if (source_file_is_too_new(ctx, path)) {
1199 return tl::unexpected(Statistic::modified_input_file);
1200 }
1201 }
1202
c86a4628 1203 if (ctx.args_info.generating_dependencies) {
c964ad4a 1204 Depfile::make_paths_relative_in_output_dep(ctx);
f5795cdb
JR
1205 }
1206
d4fcdcf2
JR
1207 if (!ctx.args_info.expect_output_obj) {
1208 // Don't probe for object file when we don't expect one since we otherwise
1209 // will be fooled by an already existing object file.
1210 LOG_RAW("Compiler not expected to produce an object file");
1211 } else {
c86a4628
JR
1212 DirEntry dir_entry(ctx.args_info.output_obj);
1213 if (!dir_entry.is_regular_file()) {
d4fcdcf2 1214 LOG_RAW("Compiler didn't produce an object file");
39606070 1215 return tl::unexpected(Statistic::compiler_produced_no_output);
c86a4628 1216 } else if (dir_entry.size() == 0) {
d4fcdcf2 1217 LOG_RAW("Compiler produced an empty object file");
39606070 1218 return tl::unexpected(Statistic::compiler_produced_empty_output);
f258b70e 1219 }
f5795cdb
JR
1220 }
1221
c7c0837a 1222 MTR_BEGIN("result", "result_put");
b53afeb5 1223 if (!write_result(
c86a4628 1224 ctx, *result_key, result->stdout_data, result->stderr_data)) {
39606070 1225 return tl::unexpected(Statistic::compiler_produced_no_output);
b53afeb5 1226 }
705b14b9 1227 MTR_END("result", "result_put");
f5795cdb
JR
1228
1229 // Everything OK.
8630a888 1230 core::send_to_console(
e9ddf680 1231 ctx, util::to_string_view(result->stderr_data), STDERR_FILENO);
d981aee3 1232 // Send stdout after stderr, it makes the output clearer with MSVC.
8630a888 1233 core::send_to_console(
bda468cf 1234 ctx,
552d736e 1235 util::to_string_view(core::MsvcShowIncludesOutput::strip_includes(
bda468cf
OS
1236 ctx, std::move(result->stdout_data))),
1237 STDOUT_FILENO);
c7c0837a
JR
1238
1239 return *result_key;
f42859a1
AT
1240}
1241
c7c0837a 1242// Find the result key by running the compiler in preprocessor mode and
0887dcaa 1243// hashing the result.
39606070 1244static tl::expected<Hash::Digest, Failure>
c7c0837a 1245get_result_key_from_cpp(Context& ctx, Args& args, Hash& hash)
f42859a1 1246{
64fc42ca 1247 std::string preprocessed_path;
e9ddf680 1248 util::Bytes cpp_stderr_data;
64fc42ca 1249
49111755 1250 if (ctx.args_info.direct_i_file) {
f5795cdb
JR
1251 // We are compiling a .i or .ii file - that means we can skip the cpp stage
1252 // and directly form the correct i_tmpfile.
64fc42ca 1253 preprocessed_path = ctx.args_info.input_file;
f5795cdb
JR
1254 } else {
1255 // Run cpp on the input file to obtain the .i.
1256
64fc42ca
JR
1257 // preprocessed_path needs the proper cpp_extension for the compiler to do
1258 // its thing correctly.
1da50f6f
JR
1259 auto tmp_stdout =
1260 util::value_or_throw<core::Fatal>(util::TemporaryFile::create(
1261 FMT("{}/cpp_stdout", ctx.config.temporary_dir()),
1262 FMT(".{}", ctx.config.cpp_extension())));
230ae9ca 1263 preprocessed_path = tmp_stdout.path.string();
64fc42ca
JR
1264 tmp_stdout.fd.close(); // We're only using the path.
1265 ctx.register_pending_tmp_file(preprocessed_path);
b3297337 1266
64fc42ca 1267 const size_t orig_args_size = args.size();
80a228c3 1268
8b0f2eb6 1269 if (ctx.config.keep_comments_cpp()) {
a0208732 1270 args.push_back("-C");
f5795cdb 1271 }
64fc42ca 1272
80a228c3
JR
1273 // Send preprocessor output to a file instead of stdout to work around
1274 // compilers that don't exit with a proper status on write error to stdout.
1275 // See also <https://github.com/llvm/llvm-project/issues/56499>.
1276 if (ctx.config.is_compiler_group_msvc()) {
1277 args.push_back("-P");
1278 args.push_back(FMT("-Fi{}", preprocessed_path));
1279 } else {
1280 args.push_back("-E");
1281 args.push_back("-o");
1282 args.push_back(preprocessed_path);
1283 }
64fc42ca 1284
04984326 1285 args.push_back(ctx.args_info.input_file);
64fc42ca 1286
f65e8766 1287 add_prefix(ctx, args, ctx.config.prefix_command_cpp());
60904e7b 1288 LOG_RAW("Running preprocessor");
f5795cdb 1289 MTR_BEGIN("execute", "preprocessor");
64fc42ca 1290 const auto result = do_execute(ctx, args, false);
f5795cdb 1291 MTR_END("execute", "preprocessor");
64fc42ca 1292 args.pop_back(args.size() - orig_args_size);
f5795cdb 1293
64fc42ca 1294 if (!result) {
39606070 1295 return tl::unexpected(result.error());
64fc42ca
JR
1296 } else if (result->exit_status != 0) {
1297 LOG("Preprocessor gave exit status {}", result->exit_status);
39606070 1298 return tl::unexpected(Statistic::preprocessor_error);
85f5f8af 1299 }
f5795cdb 1300
64fc42ca
JR
1301 cpp_stderr_data = result->stderr_data;
1302 }
f5795cdb 1303
64fc42ca
JR
1304 hash.hash_delimiter("cpp");
1305 TRY(process_preprocessed_file(ctx, hash, preprocessed_path));
1306
11f3d650 1307 hash.hash_delimiter("cppstderr");
e9ddf680 1308 hash.hash(util::to_string_view(cpp_stderr_data));
11f3d650 1309
64fc42ca 1310 ctx.i_tmpfile = preprocessed_path;
f5795cdb 1311
b3297337 1312 if (!ctx.config.run_second_cpp()) {
f5795cdb
JR
1313 // If we are using the CPP trick, we need to remember this stderr data and
1314 // output it just before the main stderr from the compiler pass.
64fc42ca 1315 ctx.cpp_stderr_data = std::move(cpp_stderr_data);
a5021452
JR
1316 hash.hash_delimiter("runsecondcpp");
1317 hash.hash("false");
f5795cdb
JR
1318 }
1319
a5021452 1320 return hash.digest();
e53af1a6
JR
1321}
1322
48e33b2e
JR
1323// Hash mtime or content of a file, or the output of a command, according to
1324// the CCACHE_COMPILERCHECK setting.
39606070 1325static tl::expected<void, Failure>
81115751 1326hash_compiler(const Context& ctx,
a5021452 1327 Hash& hash,
c86a4628 1328 const DirEntry& dir_entry,
aff39ed2 1329 const std::string& path,
222ce68f
JR
1330 bool allow_command)
1331{
8b0f2eb6 1332 if (ctx.config.compiler_check() == "none") {
f5795cdb 1333 // Do nothing.
8b0f2eb6 1334 } else if (ctx.config.compiler_check() == "mtime") {
a5021452 1335 hash.hash_delimiter("cc_mtime");
c86a4628
JR
1336 hash.hash(dir_entry.size());
1337 hash.hash(dir_entry.mtime().nsec());
ec94a399 1338 } else if (util::starts_with(ctx.config.compiler_check(), "string:")) {
a5021452 1339 hash.hash_delimiter("cc_hash");
aff39ed2 1340 hash.hash(&ctx.config.compiler_check()[7]);
8b0f2eb6 1341 } else if (ctx.config.compiler_check() == "content" || !allow_command) {
a5021452 1342 hash.hash_delimiter("cc_content");
213d9883 1343 hash_binary_file(ctx, hash, path);
f5795cdb 1344 } else { // command string
d536ae7e
JR
1345 if (!hash_multicommand_output(
1346 hash, ctx.config.compiler_check(), ctx.orig_args[0])) {
60904e7b 1347 LOG("Failure running compiler check command: {}",
b8a69ab8 1348 ctx.config.compiler_check());
39606070 1349 return tl::unexpected(Statistic::compiler_check_failed);
f5795cdb
JR
1350 }
1351 }
85f5f8af 1352 return {};
222ce68f
JR
1353}
1354
9c051cc6
JR
1355// Hash the host compiler(s) invoked by nvcc.
1356//
aff39ed2
JR
1357// If `ccbin_st` and `ccbin` are set, they refer to a directory or compiler set
1358// with -ccbin/--compiler-bindir. If `ccbin_st` is nullptr or `ccbin` is the
1359// empty string, the compilers are looked up in PATH instead.
39606070 1360static tl::expected<void, Failure>
81115751 1361hash_nvcc_host_compiler(const Context& ctx,
a5021452 1362 Hash& hash,
c86a4628 1363 const DirEntry* ccbin_st = nullptr,
aff39ed2 1364 const std::string& ccbin = {})
9c051cc6 1365{
f5795cdb
JR
1366 // From <http://docs.nvidia.com/cuda/cuda-compiler-driver-nvcc/index.html>:
1367 //
1368 // "[...] Specify the directory in which the compiler executable resides.
1369 // The host compiler executable name can be also specified to ensure that
1370 // the correct host compiler is selected."
1371 //
1372 // and
1373 //
1374 // "On all platforms, the default host compiler executable (gcc and g++ on
1375 // Linux, clang and clang++ on Mac OS X, and cl.exe on Windows) found in
1376 // the current execution search path will be used".
1377
aff39ed2 1378 if (ccbin.empty() || !ccbin_st || ccbin_st->is_directory()) {
9c051cc6 1379#if defined(__APPLE__)
f5795cdb 1380 const char* compilers[] = {"clang", "clang++"};
9c051cc6 1381#elif defined(_WIN32)
f5795cdb 1382 const char* compilers[] = {"cl.exe"};
9c051cc6 1383#else
f5795cdb 1384 const char* compilers[] = {"gcc", "g++"};
9c051cc6 1385#endif
9b11996d 1386 for (const char* compiler : compilers) {
aff39ed2 1387 if (!ccbin.empty()) {
83b50b30 1388 std::string path = FMT("{}/{}", ccbin, compiler);
c86a4628
JR
1389 DirEntry de(path);
1390 if (de.is_regular_file()) {
1391 TRY(hash_compiler(ctx, hash, de, path, false));
f5795cdb 1392 }
f5795cdb 1393 } else {
451d92c8 1394 std::string path = find_executable(ctx, compiler, ctx.orig_args[0]);
119a7ed0 1395 if (!path.empty()) {
c86a4628
JR
1396 DirEntry de(path, DirEntry::LogOnError::yes);
1397 TRY(hash_compiler(ctx, hash, de, ccbin, false));
f5795cdb
JR
1398 }
1399 }
1400 }
1401 } else {
85f5f8af 1402 TRY(hash_compiler(ctx, hash, *ccbin_st, ccbin, false));
f5795cdb 1403 }
85f5f8af
JR
1404
1405 return {};
9c051cc6
JR
1406}
1407
c9c54f6e 1408// update a hash with information common for the direct and preprocessor modes.
39606070 1409static tl::expected<void, Failure>
81115751 1410hash_common_info(const Context& ctx,
ad52c600 1411 const Args& args,
a5021452 1412 Hash& hash,
bd9897fb 1413 const ArgsInfo& args_info)
a60d2af7 1414{
a5021452 1415 hash.hash(HASH_PREFIX);
a60d2af7 1416
9217417c
JR
1417 if (!ctx.config.namespace_().empty()) {
1418 hash.hash_delimiter("namespace");
1419 hash.hash(ctx.config.namespace_());
1420 }
1421
f5795cdb
JR
1422 // We have to hash the extension, as a .i file isn't treated the same by the
1423 // compiler as a .ii file.
a5021452 1424 hash.hash_delimiter("ext");
18dd14a1 1425 hash.hash(ctx.config.cpp_extension());
37739bc9 1426
971a78da 1427#ifdef _WIN32
29e90bef 1428 const std::string compiler_path = util::add_exe_suffix(args[0]);
8ef5d30a 1429#else
a4456585 1430 const std::string compiler_path = args[0];
1f18f0f4 1431#endif
50ede96f 1432
c86a4628
JR
1433 DirEntry dir_entry(compiler_path, DirEntry::LogOnError::yes);
1434 if (!dir_entry.is_regular_file()) {
39606070 1435 return tl::unexpected(Statistic::could_not_find_compiler);
f5795cdb
JR
1436 }
1437
1438 // Hash information about the compiler.
c86a4628 1439 TRY(hash_compiler(ctx, hash, dir_entry, compiler_path, true));
f5795cdb
JR
1440
1441 // Also hash the compiler name as some compilers use hard links and behave
1442 // differently depending on the real name.
a5021452
JR
1443 hash.hash_delimiter("cc_name");
1444 hash.hash(Util::base_name(args[0]));
f5795cdb 1445
3b6762e1 1446 // Hash variables that may affect the compilation.
cad24162 1447 const char* always_hash_env_vars[] = {
a862e32a
JR
1448 // From <https://gcc.gnu.org/onlinedocs/gcc/Environment-Variables.html>
1449 // (note: SOURCE_DATE_EPOCH is handled in hash_source_code_string()):
cad24162
JR
1450 "COMPILER_PATH",
1451 "GCC_COMPARE_DEBUG",
1452 "GCC_EXEC_PREFIX",
d9df8ed1
JR
1453 // Variables that affect which underlying compiler ICC uses. Reference:
1454 // <https://www.intel.com/content/www/us/en/develop/documentation/
1455 // mpi-developer-reference-windows/top/environment-variable-reference/
1456 // compilation-environment-variables.html>
1457 "I_MPI_CC",
1458 "I_MPI_CXX",
a862e32a
JR
1459#ifdef __APPLE__
1460 // On macOS, /usr/bin/clang is a compiler wrapper that switches compiler
1461 // based on at least these variables:
1462 "DEVELOPER_DIR",
1463 "MACOSX_DEPLOYMENT_TARGET",
1464#endif
3b6762e1 1465 };
cad24162
JR
1466 for (const char* name : always_hash_env_vars) {
1467 const char* value = getenv(name);
3b6762e1 1468 if (value) {
cad24162 1469 hash.hash_delimiter(name);
3b6762e1
JR
1470 hash.hash(value);
1471 }
1472 }
1473
03023ee7 1474 if (!(ctx.config.sloppiness().contains(core::Sloppy::locale))) {
f5795cdb
JR
1475 // Hash environment variables that may affect localization of compiler
1476 // warning messages.
9b11996d
AL
1477 const char* envvars[] = {
1478 "LANG", "LC_ALL", "LC_CTYPE", "LC_MESSAGES", nullptr};
f5795cdb 1479 for (const char** p = envvars; *p; ++p) {
aff39ed2 1480 const char* v = getenv(*p);
f5795cdb 1481 if (v) {
a5021452
JR
1482 hash.hash_delimiter(*p);
1483 hash.hash(v);
f5795cdb
JR
1484 }
1485 }
1486 }
1487
1488 // Possibly hash the current working directory.
8b0f2eb6 1489 if (args_info.generating_debuginfo && ctx.config.hash_dir()) {
20696244 1490 std::string dir_to_hash = ctx.apparent_cwd;
df499792
JR
1491 for (const auto& map : args_info.debug_prefix_maps) {
1492 size_t sep_pos = map.find('=');
1493 if (sep_pos != std::string::npos) {
1494 std::string old_path = map.substr(0, sep_pos);
1495 std::string new_path = map.substr(sep_pos + 1);
60904e7b 1496 LOG("Relocating debuginfo from {} to {} (CWD: {})",
b8a69ab8
JR
1497 old_path,
1498 new_path,
1499 ctx.apparent_cwd);
ec94a399 1500 if (util::starts_with(ctx.apparent_cwd, old_path)) {
df499792 1501 dir_to_hash = new_path + ctx.apparent_cwd.substr(old_path.size());
f5795cdb 1502 }
f5795cdb
JR
1503 }
1504 }
60904e7b 1505 LOG("Hashing CWD {}", dir_to_hash);
a5021452
JR
1506 hash.hash_delimiter("cwd");
1507 hash.hash(dir_to_hash);
f5795cdb
JR
1508 }
1509
35e181c9 1510 // The object file produced by MSVC includes the full path to the source file
6cde83fb
JR
1511 // even without debug flags. Hashing the directory should be enough since the
1512 // filename is included in the hash anyway.
1513 if (ctx.config.is_compiler_group_msvc() && ctx.config.hash_dir()) {
1514 const std::string output_obj_dir =
887de1a0 1515 fs::path(args_info.output_obj).is_absolute()
6cde83fb
JR
1516 ? std::string(Util::dir_name(args_info.output_obj))
1517 : ctx.actual_cwd;
1518 LOG("Hashing object file directory {}", output_obj_dir);
1519 hash.hash_delimiter("source path");
1520 hash.hash(output_obj_dir);
1521 }
1522
fec40553 1523 if (ctx.args_info.seen_split_dwarf || ctx.args_info.profile_arcs) {
ea644051
JR
1524 // When using -gsplit-dwarf: Object files include a link to the
1525 // corresponding .dwo file based on the target object filename, so hashing
1526 // the object file path will do it, although just hashing the object file
1527 // base name would be enough.
2fd39b06 1528 //
f15da09b 1529 // When using -fprofile-arcs (including implicitly via --coverage): the
2fd39b06 1530 // object file contains a .gcda path based on the object file path.
a5021452
JR
1531 hash.hash_delimiter("object file");
1532 hash.hash(ctx.args_info.output_obj);
f5795cdb
JR
1533 }
1534
492f3e4a 1535 if (ctx.args_info.generating_coverage
03023ee7 1536 && !(ctx.config.sloppiness().contains(core::Sloppy::gcno_cwd))) {
492f3e4a
JR
1537 // GCC 9+ includes $PWD in the .gcno file. Since we don't have knowledge
1538 // about compiler version we always (unless sloppiness is wanted) include
1539 // the directory in the hash for now.
1540 LOG_RAW("Hashing apparent CWD due to generating a .gcno file");
1541 hash.hash_delimiter("CWD in .gcno");
1542 hash.hash(ctx.apparent_cwd);
1543 }
1544
f5795cdb 1545 // Possibly hash the coverage data file path.
88f89af4 1546 if (ctx.args_info.generating_coverage && ctx.args_info.profile_arcs) {
6c1dffd9 1547 std::string dir;
d0eb89de
JR
1548 if (!ctx.args_info.profile_path.empty()) {
1549 dir = ctx.args_info.profile_path;
f5795cdb 1550 } else {
3cacab8d 1551 dir = util::real_path(Util::dir_name(ctx.args_info.output_obj));
f5795cdb 1552 }
60005c83 1553 std::string_view stem =
6c1dffd9 1554 Util::remove_extension(Util::base_name(ctx.args_info.output_obj));
83b50b30 1555 std::string gcda_path = FMT("{}/{}.gcda", dir, stem);
60904e7b 1556 LOG("Hashing coverage path {}", gcda_path);
a5021452
JR
1557 hash.hash_delimiter("gcda");
1558 hash.hash(gcda_path);
f5795cdb
JR
1559 }
1560
1561 // Possibly hash the sanitize blacklist file path.
f859341d 1562 for (const auto& sanitize_blacklist : args_info.sanitize_blacklists) {
60904e7b 1563 LOG("Hashing sanitize blacklist {}", sanitize_blacklist);
df2602bb 1564 hash.hash_delimiter("sanitizeblacklist");
d536ae7e 1565 if (!hash_binary_file(ctx, hash, sanitize_blacklist)) {
39606070 1566 return tl::unexpected(Statistic::error_hashing_extra_file);
f5795cdb
JR
1567 }
1568 }
1569
8b0f2eb6 1570 if (!ctx.config.extra_files_to_hash().empty()) {
587b0244 1571 for (const auto& path :
49548d72 1572 util::split_path_list(ctx.config.extra_files_to_hash())) {
60904e7b 1573 LOG("Hashing extra file {}", path);
a5021452 1574 hash.hash_delimiter("extrafile");
587b0244 1575 if (!hash_binary_file(ctx, hash, path.string())) {
39606070 1576 return tl::unexpected(Statistic::error_hashing_extra_file);
f5795cdb 1577 }
f5795cdb 1578 }
f5795cdb
JR
1579 }
1580
1581 // Possibly hash GCC_COLORS (for color diagnostics).
e2ab1352 1582 if (ctx.config.compiler_type() == CompilerType::gcc) {
f5795cdb
JR
1583 const char* gcc_colors = getenv("GCC_COLORS");
1584 if (gcc_colors) {
a5021452
JR
1585 hash.hash_delimiter("gcccolors");
1586 hash.hash(gcc_colors);
f5795cdb
JR
1587 }
1588 }
85f5f8af
JR
1589
1590 return {};
a60d2af7
JR
1591}
1592
fec40553
JR
1593static std::tuple<std::optional<std::string_view>,
1594 std::optional<std::string_view>>
1595get_option_and_value(std::string_view option, const Args& args, size_t& i)
1596{
1597 if (args[i] == option) {
1598 if (i + 1 < args.size()) {
1599 ++i;
1600 return {option, args[i]};
1601 } else {
1602 return {std::nullopt, std::nullopt};
1603 }
1604 } else if (util::starts_with(args[i], option)) {
1605 return {option, std::string_view(args[i]).substr(option.length())};
1606 } else {
1607 return {std::nullopt, std::nullopt};
1608 }
1609}
1610
39606070 1611static tl::expected<void, Failure>
98f5fcef
JR
1612hash_argument(const Context& ctx,
1613 const Args& args,
1614 size_t& i,
1615 Hash& hash,
1616 const bool is_clang,
1617 const bool direct_mode,
1618 bool& found_ccbin)
a60d2af7 1619{
98f5fcef
JR
1620 // Trust the user if they've said we should not hash a given option.
1621 if (option_should_be_ignored(args[i], ctx.ignore_options())) {
1622 LOG("Not hashing ignored option: {}", args[i]);
1623 if (i + 1 < args.size() && compopt_takes_arg(args[i])) {
1624 i++;
1625 LOG("Not hashing argument of ignored option: {}", args[i]);
1626 }
1627 return {};
1628 }
f5795cdb 1629
98f5fcef
JR
1630 // -L doesn't affect compilation (except for clang).
1631 if (i < args.size() - 1 && args[i] == "-L" && !is_clang) {
1632 i++;
1633 return {};
1634 }
1635 if (util::starts_with(args[i], "-L") && !is_clang) {
1636 return {};
1637 }
f5795cdb 1638
98f5fcef
JR
1639 // -Wl,... doesn't affect compilation (except for clang).
1640 if (util::starts_with(args[i], "-Wl,") && !is_clang) {
1641 return {};
f5795cdb
JR
1642 }
1643
98f5fcef
JR
1644 if (util::starts_with(args[i], "-Wa,")) {
1645 // We have to distinguish between three cases:
1646 //
1647 // Case 1: -Wa,-a (write to stdout)
1648 // Case 2: -Wa,-a= (write to stdout and stderr)
1649 // Case 3: -Wa,-a=file (write to file)
1650 //
1651 // No need to include the file part in case 3 in the hash since the filename
1652 // is not part of the output.
f5795cdb 1653
98f5fcef
JR
1654 hash.hash_delimiter("arg");
1655 bool first = true;
1656 for (const auto part :
1657 util::Tokenizer(args[i], ",", util::Tokenizer::Mode::include_empty)) {
1658 if (first) {
1659 first = false;
1660 } else {
1661 hash.hash(",");
231fef47 1662 }
98f5fcef
JR
1663 if (util::starts_with(part, "-a")) {
1664 const auto eq_pos = part.find('=');
1665 if (eq_pos < part.size() - 1) {
1666 // Case 3:
1667 hash.hash(part.substr(0, eq_pos + 1));
1668 hash.hash("file");
1669 continue;
b4dfd7b5 1670 }
b4dfd7b5 1671 }
98f5fcef
JR
1672 // Case 1 and 2:
1673 hash.hash(part);
b4dfd7b5 1674 }
98f5fcef
JR
1675 return {};
1676 }
b4dfd7b5 1677
98f5fcef
JR
1678 // The -fdebug-prefix-map option may be used in combination with
1679 // CCACHE_BASEDIR to reuse results across different directories. Skip using
1680 // the value of the option from hashing but still hash the existence of the
1681 // option.
1682 if (util::starts_with(args[i], "-fdebug-prefix-map=")) {
1683 hash.hash_delimiter("arg");
1684 hash.hash("-fdebug-prefix-map=");
1685 return {};
1686 }
1687 if (util::starts_with(args[i], "-ffile-prefix-map=")) {
1688 hash.hash_delimiter("arg");
1689 hash.hash("-ffile-prefix-map=");
1690 return {};
1691 }
1692 if (util::starts_with(args[i], "-fmacro-prefix-map=")) {
1693 hash.hash_delimiter("arg");
1694 hash.hash("-fmacro-prefix-map=");
1695 return {};
1696 }
f5795cdb 1697
923e0b95 1698 if (util::starts_with(args[i], "-frandom-seed=")
03023ee7 1699 && ctx.config.sloppiness().contains(core::Sloppy::random_seed)) {
d097f32f 1700 LOG("Ignoring {} since random_seed sloppiness is requested", args[i]);
923e0b95
RS
1701 return {};
1702 }
1703
98f5fcef
JR
1704 // When using the preprocessor, some arguments don't contribute to the hash.
1705 // The theory is that these arguments will change the output of -E if they are
1706 // going to have any effect at all. For precompiled headers this might not be
1707 // the case.
1708 if (!direct_mode && !ctx.args_info.output_is_precompiled_header
1709 && !ctx.args_info.using_precompiled_header) {
1710 if (compopt_affects_cpp_output(args[i])) {
1711 if (compopt_takes_arg(args[i])) {
1712 i++;
f5795cdb 1713 }
98f5fcef 1714 return {};
f5795cdb 1715 }
98f5fcef
JR
1716 if (compopt_affects_cpp_output(args[i].substr(0, 2))) {
1717 return {};
1718 }
1719 }
f5795cdb 1720
98f5fcef
JR
1721 if (ctx.args_info.generating_dependencies) {
1722 std::optional<std::string_view> option;
1723 std::optional<std::string_view> value;
1724
1725 if (util::starts_with(args[i], "-Wp,")) {
1726 // Skip the dependency filename since it doesn't impact the output.
1727 if (util::starts_with(args[i], "-Wp,-MD,")
1728 && args[i].find(',', 8) == std::string::npos) {
1729 hash.hash(args[i].data(), 8);
1730 return {};
1731 } else if (util::starts_with(args[i], "-Wp,-MMD,")
1732 && args[i].find(',', 9) == std::string::npos) {
1733 hash.hash(args[i].data(), 9);
1734 return {};
f5795cdb 1735 }
98f5fcef
JR
1736 } else if (std::tie(option, value) = get_option_and_value("-MF", args, i);
1737 option) {
1738 // Skip the dependency filename since it doesn't impact the output.
1739 hash.hash(*option);
1740 return {};
1741 } else if (std::tie(option, value) = get_option_and_value("-MQ", args, i);
1742 option) {
1743 hash.hash(*option);
1744 // No need to hash the dependency target since we always calculate it on
1745 // a cache hit.
1746 return {};
1747 } else if (std::tie(option, value) = get_option_and_value("-MT", args, i);
1748 option) {
1749 hash.hash(*option);
1750 // No need to hash the dependency target since we always calculate it on
1751 // a cache hit.
1752 return {};
f5795cdb 1753 }
98f5fcef 1754 }
f5795cdb 1755
98f5fcef
JR
1756 if (util::starts_with(args[i], "-specs=")
1757 || util::starts_with(args[i], "--specs=")
1758 || (args[i] == "-specs" || args[i] == "--specs")
1759 || args[i] == "--config") {
1760 std::string path;
1761 size_t eq_pos = args[i].find('=');
1762 if (eq_pos == std::string::npos) {
1763 if (i + 1 >= args.size()) {
1764 LOG("missing argument for \"{}\"", args[i]);
39606070 1765 return tl::unexpected(Statistic::bad_compiler_arguments);
8bf69a1d 1766 }
98f5fcef
JR
1767 path = args[i + 1];
1768 i++;
1769 } else {
1770 path = args[i].substr(eq_pos + 1);
f5795cdb 1771 }
27043359
JR
1772
1773 if (args[i] == "--config" && path.find('/') == std::string::npos) {
1774 // --config FILE without / in FILE: the file is searched for in Clang's
1775 // user/system/executable directories.
1776 LOG("Argument to compiler option {} is too hard", args[i]);
1777 return tl::unexpected(Statistic::unsupported_compiler_option);
1778 }
1779
c86a4628
JR
1780 DirEntry dir_entry(path, DirEntry::LogOnError::yes);
1781 if (dir_entry.is_regular_file()) {
98f5fcef
JR
1782 // If given an explicit specs file, then hash that file, but don't
1783 // include the path to it in the hash.
1784 hash.hash_delimiter("specs");
c86a4628 1785 TRY(hash_compiler(ctx, hash, dir_entry, path, false));
98f5fcef 1786 return {};
27043359
JR
1787 } else {
1788 LOG("While processing {}: {} is missing", args[i], path);
1789 return tl::unexpected(Statistic::bad_compiler_arguments);
98f5fcef
JR
1790 }
1791 }
f5795cdb 1792
98f5fcef 1793 if (util::starts_with(args[i], "-fplugin=")) {
c86a4628
JR
1794 DirEntry dir_entry(&args[i][9], DirEntry::LogOnError::yes);
1795 if (dir_entry.is_regular_file()) {
98f5fcef 1796 hash.hash_delimiter("plugin");
c86a4628 1797 TRY(hash_compiler(ctx, hash, dir_entry, &args[i][9], false));
98f5fcef 1798 return {};
f5795cdb 1799 }
98f5fcef 1800 }
f5795cdb 1801
98f5fcef
JR
1802 if (args[i] == "-Xclang" && i + 3 < args.size() && args[i + 1] == "-load"
1803 && args[i + 2] == "-Xclang") {
c86a4628
JR
1804 DirEntry dir_entry(args[i + 3], DirEntry::LogOnError::yes);
1805 if (dir_entry.is_regular_file()) {
98f5fcef 1806 hash.hash_delimiter("plugin");
c86a4628 1807 TRY(hash_compiler(ctx, hash, dir_entry, args[i + 3], false));
98f5fcef
JR
1808 i += 3;
1809 return {};
f5795cdb 1810 }
98f5fcef 1811 }
f5795cdb 1812
98f5fcef
JR
1813 if ((args[i] == "-ccbin" || args[i] == "--compiler-bindir")
1814 && i + 1 < args.size()) {
c86a4628
JR
1815 DirEntry dir_entry(args[i + 1]);
1816 if (dir_entry.exists()) {
98f5fcef
JR
1817 found_ccbin = true;
1818 hash.hash_delimiter("ccbin");
c86a4628 1819 TRY(hash_nvcc_host_compiler(ctx, hash, &dir_entry, args[i + 1]));
98f5fcef
JR
1820 i++;
1821 return {};
f5795cdb 1822 }
98f5fcef 1823 }
f5795cdb 1824
98f5fcef
JR
1825 // All other arguments are included in the hash.
1826 hash.hash_delimiter("arg");
1827 hash.hash(args[i]);
1828 if (i + 1 < args.size() && compopt_takes_arg(args[i])) {
1829 i++;
a5021452
JR
1830 hash.hash_delimiter("arg");
1831 hash.hash(args[i]);
98f5fcef
JR
1832 }
1833
1834 return {};
1835}
1836
39606070 1837static tl::expected<std::optional<Hash::Digest>, Failure>
58a2dfc7 1838get_manifest_key(Context& ctx, Hash& hash)
98f5fcef
JR
1839{
1840 // Hash environment variables that affect the preprocessor output.
27043359
JR
1841 const char* envvars[] = {
1842 "CPATH",
1843 "C_INCLUDE_PATH",
1844 "CPLUS_INCLUDE_PATH",
1845 "OBJC_INCLUDE_PATH",
1846 "OBJCPLUS_INCLUDE_PATH", // Clang
1847 "CLANG_CONFIG_FILE_SYSTEM_DIR", // Clang
1848 "CLANG_CONFIG_FILE_USER_DIR", // Clang
1849 nullptr,
1850 };
98f5fcef
JR
1851 for (const char** p = envvars; *p; ++p) {
1852 const char* v = getenv(*p);
1853 if (v) {
1854 hash.hash_delimiter(*p);
1855 hash.hash(v);
f5795cdb
JR
1856 }
1857 }
1858
98f5fcef
JR
1859 // Make sure that the direct mode hash is unique for the input file path. If
1860 // this would not be the case:
1861 //
1862 // * A false cache hit may be produced. Scenario:
1863 // - a/r.h exists.
1864 // - a/x.c has #include "r.h".
1865 // - b/x.c is identical to a/x.c.
1866 // - Compiling a/x.c records a/r.h in the manifest.
1867 // - Compiling b/x.c results in a false cache hit since a/x.c and b/x.c
1868 // share manifests and a/r.h exists.
1869 // * The expansion of __FILE__ may be incorrect.
1870 hash.hash_delimiter("inputfile");
1871 hash.hash(ctx.args_info.input_file);
1872
1873 hash.hash_delimiter("sourcecode hash");
0e4e4b63 1874 Hash::Digest input_file_digest;
38ab9d38 1875 auto ret =
98f5fcef 1876 hash_source_code_file(ctx, input_file_digest, ctx.args_info.input_file);
38ab9d38 1877 if (ret.contains(HashSourceCode::error)) {
39606070 1878 return tl::unexpected(Statistic::internal_error);
98f5fcef 1879 }
38ab9d38 1880 if (ret.contains(HashSourceCode::found_time)) {
98f5fcef
JR
1881 LOG_RAW("Disabling direct mode");
1882 ctx.config.set_direct_mode(false);
1883 return {};
f5795cdb 1884 }
0e4e4b63 1885 hash.hash(util::format_digest(input_file_digest));
58a2dfc7 1886 return hash.digest();
98f5fcef
JR
1887}
1888
1889static bool
1890hash_profile_data_file(const Context& ctx, Hash& hash)
1891{
1892 const std::string& profile_path = ctx.args_info.profile_path;
1893 std::string_view base_name = Util::remove_extension(ctx.args_info.output_obj);
1894 std::string hashified_cwd = ctx.apparent_cwd;
1895 std::replace(hashified_cwd.begin(), hashified_cwd.end(), '/', '#');
1896
1897 std::vector<std::string> paths_to_try{
1898 // -fprofile-use[=dir]/-fbranch-probabilities (GCC <9)
1899 FMT("{}/{}.gcda", profile_path, base_name),
1900 // -fprofile-use[=dir]/-fbranch-probabilities (GCC >=9)
1901 FMT("{}/{}#{}.gcda", profile_path, hashified_cwd, base_name),
1902 // -fprofile(-instr|-sample)-use=file (Clang), -fauto-profile=file (GCC >=5)
1903 profile_path,
1904 // -fprofile(-instr|-sample)-use=dir (Clang)
1905 FMT("{}/default.profdata", profile_path),
1906 // -fauto-profile (GCC >=5)
1907 "fbdata.afdo", // -fprofile-dir is not used
1908 };
1909
1910 bool found = false;
1911 for (const std::string& p : paths_to_try) {
1912 LOG("Checking for profile data file {}", p);
c86a4628 1913 if (DirEntry(p).is_regular_file()) {
98f5fcef
JR
1914 LOG("Adding profile data {} to the hash", p);
1915 hash.hash_delimiter("-fprofile-use");
1916 if (hash_binary_file(ctx, hash, p)) {
1917 found = true;
1918 }
1919 }
f5795cdb
JR
1920 }
1921
98f5fcef
JR
1922 return found;
1923}
1924
39606070 1925static tl::expected<void, Failure>
98f5fcef
JR
1926hash_profiling_related_data(const Context& ctx, Hash& hash)
1927{
d0eb89de
JR
1928 // For profile generation (-fprofile(-instr)-generate[=path])
1929 // - hash profile path
f5795cdb 1930 //
4b1b7d4b 1931 // For profile usage (-fprofile(-instr|-sample)-use, -fbranch-probabilities):
f5795cdb
JR
1932 // - hash profile data
1933 //
1934 // -fbranch-probabilities and -fvpt usage is covered by
1935 // -fprofile-generate/-fprofile-use.
1936 //
1937 // The profile directory can be specified as an argument to
4b1b7d4b
OL
1938 // -fprofile(-instr)-generate=, -fprofile(-instr|-sample)-use= or
1939 // -fprofile-dir=.
d0eb89de 1940
0902d812 1941 if (ctx.args_info.profile_generate) {
706f7443 1942 ASSERT(!ctx.args_info.profile_path.empty());
2c286f1f
JR
1943
1944 // For a relative profile directory D the compiler stores $PWD/D as part of
1945 // the profile filename so we need to include the same information in the
1946 // hash.
1947 const std::string profile_path =
887de1a0 1948 fs::path(ctx.args_info.profile_path).is_absolute()
2c286f1f
JR
1949 ? ctx.args_info.profile_path
1950 : FMT("{}/{}", ctx.apparent_cwd, ctx.args_info.profile_path);
1951 LOG("Adding profile directory {} to our hash", profile_path);
a5021452 1952 hash.hash_delimiter("-fprofile-dir");
2c286f1f 1953 hash.hash(profile_path);
f5795cdb
JR
1954 }
1955
d0eb89de 1956 if (ctx.args_info.profile_use && !hash_profile_data_file(ctx, hash)) {
60904e7b 1957 LOG_RAW("No profile data file found");
39606070 1958 return tl::unexpected(Statistic::no_input_file);
f5795cdb
JR
1959 }
1960
98f5fcef
JR
1961 return {};
1962}
1963
0e4e4b63
JR
1964static std::optional<Hash::Digest>
1965get_result_key_from_manifest(Context& ctx, const Hash::Digest& manifest_key)
58a2dfc7
JR
1966{
1967 MTR_BEGIN("manifest", "manifest_get");
0e4e4b63 1968 std::optional<Hash::Digest> result_key;
58a2dfc7
JR
1969 size_t read_manifests = 0;
1970 ctx.storage.get(
1971 manifest_key, core::CacheEntryType::manifest, [&](util::Bytes&& value) {
1972 try {
1973 read_manifest(ctx, value);
1974 ++read_manifests;
1975 result_key = ctx.manifest.look_up_result_digest(ctx);
1976 } catch (const core::Error& e) {
1977 LOG("Failed to look up result key in manifest: {}", e.what());
1978 }
1979 if (result_key) {
1980 LOG_RAW("Got result key from manifest");
1981 return true;
1982 } else {
1983 LOG_RAW("Did not find result key in manifest");
1984 return false;
1985 }
1986 });
1987 MTR_END("manifest", "manifest_get");
1988 if (read_manifests > 1 && !ctx.config.remote_only()) {
1989 MTR_SCOPE("manifest", "merge");
0e4e4b63
JR
1990 LOG("Storing merged manifest {} locally",
1991 util::format_digest(manifest_key));
58a2dfc7
JR
1992 core::CacheEntry::Header header(ctx.config, core::CacheEntryType::manifest);
1993 ctx.storage.local.put(manifest_key,
1994 core::CacheEntryType::manifest,
1995 core::CacheEntry::serialize(header, ctx.manifest));
1996 }
1997
1998 return result_key;
1999}
2000
98f5fcef
JR
2001// Update a hash sum with information specific to the direct and preprocessor
2002// modes and calculate the result key. Returns the result key on success, and
2003// if direct_mode is true also the manifest key.
39606070 2004static tl::expected<
0e4e4b63
JR
2005 std::pair<std::optional<Hash::Digest>, std::optional<Hash::Digest>>,
2006 Failure>
98f5fcef
JR
2007calculate_result_and_manifest_key(Context& ctx,
2008 const Args& args,
98f5fcef 2009 Hash& hash,
dda86ed9 2010 Args* preprocessor_args)
98f5fcef 2011{
dda86ed9 2012 bool direct_mode = !preprocessor_args;
98f5fcef
JR
2013 bool found_ccbin = false;
2014
a03f14b7 2015 hash.hash_delimiter("cache entry version");
653dde81 2016 hash.hash(core::CacheEntry::k_format_version);
a03f14b7 2017
98f5fcef 2018 hash.hash_delimiter("result version");
a03f14b7 2019 hash.hash(core::Result::k_format_version);
98f5fcef
JR
2020
2021 if (direct_mode) {
2022 hash.hash_delimiter("manifest version");
2023 hash.hash(core::Manifest::k_format_version);
2024 }
2025
2026 // clang will emit warnings for unused linker flags, so we shouldn't skip
2027 // those arguments.
2028 int is_clang = ctx.config.is_compiler_group_clang()
2029 || ctx.config.compiler_type() == CompilerType::other;
2030
2031 // First the arguments.
2032 for (size_t i = 1; i < args.size(); i++) {
2033 TRY(hash_argument(ctx, args, i, hash, is_clang, direct_mode, found_ccbin));
2034 }
2035
98f5fcef
JR
2036 if (!found_ccbin && ctx.args_info.actual_language == "cu") {
2037 TRY(hash_nvcc_host_compiler(ctx, hash));
2038 }
2039
2040 TRY(hash_profiling_related_data(ctx, hash));
2041
f5795cdb 2042 // Adding -arch to hash since cpp output is affected.
7ca8fd6c 2043 for (const auto& arch : ctx.args_info.arch_args) {
a5021452
JR
2044 hash.hash_delimiter("-arch");
2045 hash.hash(arch);
ab7dd6ff
TN
2046
2047 // Adding -Xarch_* to hash since cpp output is affected.
2048 auto it = ctx.args_info.xarch_args.find(arch);
2049 if (it != ctx.args_info.xarch_args.end()) {
2050 for (const auto& xarch : it->second) {
2051 hash.hash_delimiter("-Xarch_" + arch);
2052 hash.hash(xarch);
2053 }
2054 }
f5795cdb
JR
2055 }
2056
0e4e4b63
JR
2057 std::optional<Hash::Digest> result_key;
2058 std::optional<Hash::Digest> manifest_key;
c7c0837a 2059
f5795cdb 2060 if (direct_mode) {
58a2dfc7
JR
2061 const auto manifest_key_result = get_manifest_key(ctx, hash);
2062 if (!manifest_key_result) {
39606070 2063 return tl::unexpected(manifest_key_result.error());
58a2dfc7
JR
2064 }
2065 manifest_key = *manifest_key_result;
2066 if (manifest_key) {
0e4e4b63 2067 LOG("Manifest key: {}", util::format_digest(*manifest_key));
58a2dfc7
JR
2068 result_key = get_result_key_from_manifest(ctx, *manifest_key);
2069 }
85f5f8af 2070 } else if (ctx.args_info.arch_args.empty()) {
dda86ed9 2071 const auto digest = get_result_key_from_cpp(ctx, *preprocessor_args, hash);
85f5f8af 2072 if (!digest) {
39606070 2073 return tl::unexpected(digest.error());
85f5f8af
JR
2074 }
2075 result_key = *digest;
2076 LOG_RAW("Got result key from preprocessor");
f5795cdb 2077 } else {
dda86ed9 2078 preprocessor_args->push_back("-arch");
85f5f8af 2079 for (size_t i = 0; i < ctx.args_info.arch_args.size(); ++i) {
ab7dd6ff 2080 const auto& arch = ctx.args_info.arch_args[i];
36e914f8 2081 size_t xarch_count = 0;
ab7dd6ff
TN
2082 preprocessor_args->push_back(arch);
2083 auto it = ctx.args_info.xarch_args.find(arch);
2084 if (it != ctx.args_info.xarch_args.end()) {
2085 for (const auto& xarch : it->second) {
2086 preprocessor_args->push_back("-Xarch_" + arch);
2087 preprocessor_args->push_back(xarch);
2088 xarch_count += 2;
2089 }
2090 }
dda86ed9
JR
2091 const auto digest =
2092 get_result_key_from_cpp(ctx, *preprocessor_args, hash);
85f5f8af 2093 if (!digest) {
39606070 2094 return tl::unexpected(digest.error());
85f5f8af
JR
2095 }
2096 result_key = *digest;
ab7dd6ff 2097 LOG("Got result key from preprocessor with -arch {}", arch);
85f5f8af 2098 if (i != ctx.args_info.arch_args.size() - 1) {
eea89d4a 2099 result_key = std::nullopt;
f5795cdb 2100 }
36e914f8 2101 preprocessor_args->pop_back(1 + xarch_count);
f5795cdb 2102 }
dda86ed9 2103 preprocessor_args->pop_back();
f5795cdb
JR
2104 }
2105
58a2dfc7 2106 if (result_key) {
0e4e4b63 2107 LOG("Result key: {}", util::format_digest(*result_key));
58a2dfc7 2108 }
85f5f8af 2109 return std::make_pair(result_key, manifest_key);
e53af1a6 2110}
f42859a1 2111
d5390135
JR
2112enum class FromCacheCallMode { direct, cpp };
2113
b646eb0a 2114// Try to return the compile result from cache.
39606070 2115static tl::expected<bool, Failure>
0e4e4b63 2116from_cache(Context& ctx, FromCacheCallMode mode, const Hash::Digest& result_key)
f42859a1 2117{
f5795cdb 2118 // The user might be disabling cache hits.
8b0f2eb6 2119 if (ctx.config.recache()) {
a9567b9a 2120 return false;
f5795cdb
JR
2121 }
2122
2123 // If we're using Clang, we can't trust a precompiled header object based on
2124 // running the preprocessor since clang will produce a fatal error when the
2125 // precompiled header is used and one of the included files has an updated
2126 // timestamp:
2127 //
2128 // file 'foo.h' has been modified since the precompiled header 'foo.pch'
2129 // was built
32c70852 2130 if ((ctx.config.is_compiler_group_clang()
e2ab1352 2131 || ctx.config.compiler_type() == CompilerType::other)
f2cd5dec 2132 && ctx.args_info.output_is_precompiled_header
fd1e2683 2133 && mode == FromCacheCallMode::cpp) {
60904e7b 2134 LOG_RAW("Not considering cached precompiled header in preprocessor mode");
a9567b9a 2135 return false;
f5795cdb
JR
2136 }
2137
705b14b9 2138 MTR_SCOPE("cache", "from_cache");
f5795cdb 2139
f5795cdb 2140 // Get result from cache.
0db6d06d
JR
2141 util::Bytes cache_entry_data;
2142 ctx.storage.get(
2143 result_key, core::CacheEntryType::result, [&](util::Bytes&& value) {
2144 cache_entry_data = std::move(value);
2145 return true;
2146 });
2147 if (cache_entry_data.empty()) {
a9567b9a 2148 return false;
fd8474e3 2149 }
c7c0837a 2150
02dac1f1 2151 try {
0db6d06d 2152 core::CacheEntry cache_entry(cache_entry_data);
a03f14b7
JR
2153 cache_entry.verify_checksum();
2154 core::Result::Deserializer deserializer(cache_entry.payload());
d663cb51 2155 core::ResultRetriever result_retriever(ctx, result_key);
3c98cd28 2156 util::UmaskScope umask_scope(ctx.original_umask);
99c881d1 2157 deserializer.visit(result_retriever);
99c881d1 2158 } catch (core::ResultRetriever::WriteError& e) {
d663cb51 2159 LOG("Write error when retrieving result from {}: {}",
0e4e4b63 2160 util::format_digest(result_key),
d663cb51 2161 e.what());
39606070 2162 return tl::unexpected(Statistic::bad_output_file);
02dac1f1 2163 } catch (core::Error& e) {
0e4e4b63
JR
2164 LOG("Failed to get result from {}: {}",
2165 util::format_digest(result_key),
2166 e.what());
a9567b9a 2167 return false;
f5795cdb
JR
2168 }
2169
60904e7b 2170 LOG_RAW("Succeeded getting cached result");
a9567b9a 2171 return true;
f42859a1
AT
2172}
2173
41fa24ab 2174// Find the real compiler and put it into ctx.orig_args[0]. We just search the
451d92c8 2175// PATH to find an executable of the same name that isn't ourselves.
41fa24ab
AL
2176void
2177find_compiler(Context& ctx,
e1a53fd0
JR
2178 const FindExecutableFunction& find_executable_function,
2179 bool masquerading_as_compiler)
f42859a1 2180{
697390ed 2181 // Support user override of the compiler.
cb8aec82
JR
2182 const std::string compiler =
2183 !ctx.config.compiler().empty()
2184 ? ctx.config.compiler()
1e7f56fa
JR
2185 // In case ccache is masquerading as the compiler, use only base_name so
2186 // the real compiler can be determined.
e1a53fd0
JR
2187 : (masquerading_as_compiler
2188 ? std::string(Util::base_name(ctx.orig_args[0]))
2189 : ctx.orig_args[0]);
f5795cdb 2190
697390ed 2191 const std::string resolved_compiler =
e3e29c94 2192 util::is_full_path(compiler)
697390ed 2193 ? compiler
451d92c8 2194 : find_executable_function(ctx, compiler, ctx.orig_args[0]);
f5795cdb 2195
697390ed 2196 if (resolved_compiler.empty()) {
a4ab84f9 2197 throw core::Fatal(FMT("Could not find compiler \"{}\" in PATH", compiler));
f5795cdb 2198 }
697390ed 2199
73f6c52a 2200 if (is_ccache_executable(resolved_compiler)) {
451d92c8 2201 throw core::Fatal("Recursive invocation of ccache");
f5795cdb 2202 }
697390ed 2203
697390ed 2204 ctx.orig_args[0] = resolved_compiler;
f42859a1
AT
2205}
2206
91aa7075 2207static void
e1a53fd0 2208initialize(Context& ctx, const char* const* argv, bool masquerading_as_compiler)
107e2e36 2209{
60904e7b 2210 LOG("=== CCACHE {} STARTED =========================================",
b8a69ab8 2211 CCACHE_VERSION);
f5795cdb 2212
a2e7f910
JR
2213 LOG("Configuration file: {}", ctx.config.config_path());
2214 LOG("System configuration file: {}", ctx.config.system_config_path());
61c70a6f 2215
1a15286a 2216 if (getenv("CCACHE_INTERNAL_TRACE")) {
f08edbb7 2217#ifdef MTR_ENABLED
98495aa4 2218 ctx.mini_trace = std::make_unique<MiniTrace>(ctx.args_info);
f08edbb7 2219#else
60904e7b 2220 LOG_RAW("Error: tracing is not enabled!");
00c6b35b 2221#endif
f5795cdb 2222 }
e1a53fd0
JR
2223
2224 if (!ctx.config.log_file().empty() || ctx.config.debug()) {
2225 ctx.config.visit_items([&ctx](const std::string& key,
2226 const std::string& value,
2227 const std::string& origin) {
2228 const auto& log_value =
2229 key == "remote_storage"
2230 ? ctx.storage.get_remote_storage_config_for_logging()
2231 : value;
2232 BULK_LOG("Config: ({}) {} = {}", origin, key, log_value);
2233 });
2234 }
2235
7019a3d0 2236 LOG("Command line: {}", util::format_argv_for_logging(argv));
0d4f1ce2 2237 LOG("Hostname: {}", util::get_hostname());
e1a53fd0
JR
2238 LOG("Working directory: {}", ctx.actual_cwd);
2239 if (ctx.apparent_cwd != ctx.actual_cwd) {
2240 LOG("Apparent working directory: {}", ctx.apparent_cwd);
2241 }
2242
2243 ctx.storage.initialize();
2244
2245 MTR_BEGIN("main", "find_compiler");
2246 find_compiler(ctx, &find_executable, masquerading_as_compiler);
2247 MTR_END("main", "find_compiler");
2248
2249 // Guess compiler after logging the config value in order to be able to
2250 // display "compiler_type = auto" before overwriting the value with the
2251 // guess.
2252 if (ctx.config.compiler_type() == CompilerType::auto_guess) {
2253 ctx.config.set_compiler_type(guess_compiler(ctx.orig_args[0]));
2254 }
2255 DEBUG_ASSERT(ctx.config.compiler_type() != CompilerType::auto_guess);
2256
2257 LOG("Compiler: {}", ctx.orig_args[0]);
2258 LOG("Compiler type: {}", compiler_type_to_string(ctx.config.compiler_type()));
b55be7ec
JR
2259}
2260
48e33b2e
JR
2261// Make a copy of stderr that will not be cached, so things like distcc can
2262// send networking errors to it.
39606070 2263static tl::expected<void, Failure>
b646eb0a 2264set_up_uncached_err()
b55be7ec 2265{
47923581
JR
2266 int uncached_fd =
2267 dup(STDERR_FILENO); // The file descriptor is intentionally leaked.
f5795cdb 2268 if (uncached_fd == -1) {
60904e7b 2269 LOG("dup(2) failed: {}", strerror(errno));
39606070 2270 return tl::unexpected(Statistic::internal_error);
f5795cdb
JR
2271 }
2272
09c32fb9 2273 util::setenv("UNCACHED_ERR_FD", FMT("{}", uncached_fd));
85f5f8af 2274 return {};
b55be7ec
JR
2275}
2276
9131b059 2277static int cache_compilation(int argc, const char* const* argv);
85f5f8af 2278
39606070 2279static tl::expected<core::StatisticsCounters, Failure>
e1a53fd0 2280do_cache_compilation(Context& ctx);
3896b68f 2281
a28af38b
JR
2282static void
2283log_result_to_debug_log(Context& ctx)
2284{
2285 if (ctx.config.log_file().empty() && !ctx.config.debug()) {
2286 return;
2287 }
2288
0cd6f70b 2289 core::Statistics statistics(ctx.storage.local.get_statistics_updates());
190d2f2e 2290 for (const auto& message : statistics.get_statistics_ids()) {
9b1e89d2 2291 LOG("Result: {}", message);
a28af38b
JR
2292 }
2293}
2294
2295static void
2296log_result_to_stats_log(Context& ctx)
2297{
2298 if (ctx.config.stats_log().empty()) {
2299 return;
2300 }
2301
0cd6f70b 2302 core::Statistics statistics(ctx.storage.local.get_statistics_updates());
9b1e89d2
JR
2303 const auto ids = statistics.get_statistics_ids();
2304 if (ids.empty()) {
a28af38b
JR
2305 return;
2306 }
2307
2308 core::StatsLog(ctx.config.stats_log())
9b1e89d2 2309 .log_result(ctx.args_info.input_file, ids);
a28af38b
JR
2310}
2311
c7c0837a
JR
2312static void
2313finalize_at_exit(Context& ctx)
fd8474e3 2314{
c7c0837a
JR
2315 try {
2316 if (ctx.config.disable()) {
2317 // Just log result, don't update statistics.
2318 LOG_RAW("Result: disabled");
2319 return;
fd8474e3 2320 }
fb7c0327 2321
a28af38b
JR
2322 log_result_to_debug_log(ctx);
2323 log_result_to_stats_log(ctx);
fe22a1de 2324
c7c0837a 2325 ctx.storage.finalize();
eb266c99 2326 } catch (const core::ErrorBase& e) {
fd8474e3 2327 // finalize_at_exit must not throw since it's called by a destructor.
60904e7b 2328 LOG("Error while finalizing stats: {}", e.what());
fd8474e3 2329 }
dd8f65aa
JR
2330
2331 // Dump log buffer last to not lose any logs.
2332 if (ctx.config.debug() && !ctx.args_info.output_obj.empty()) {
d96b24a9
JR
2333 util::logging::dump_log(prepare_debug_path(ctx.apparent_cwd,
2334 ctx.config.debug_dir(),
13cb56cd
JR
2335 ctx.time_of_invocation,
2336 ctx.args_info.output_obj,
2337 "log"));
dd8f65aa
JR
2338 }
2339}
2340
e1a53fd0
JR
2341ArgvParts
2342split_argv(int argc, const char* const* argv)
2343{
2344 ArgvParts argv_parts;
2345 int i = 0;
73f6c52a 2346 while (i < argc && is_ccache_executable(argv[i])) {
e1a53fd0
JR
2347 argv_parts.masquerading_as_compiler = false;
2348 ++i;
2349 }
2350 while (i < argc && std::strchr(argv[i], '=')) {
2351 argv_parts.config_settings.emplace_back(argv[i]);
2352 ++i;
2353 }
2354 argv_parts.compiler_and_args = Args::from_argv(argc - i, argv + i);
2355 return argv_parts;
2356}
2357
2adbab62 2358// The entry point when invoked to cache a compilation.
cc2236b2 2359static int
9131b059 2360cache_compilation(int argc, const char* const* argv)
f42859a1 2361{
e521c750 2362 tzset(); // Needed for localtime_r.
f5795cdb 2363
dd8f65aa
JR
2364 bool fall_back_to_original_compiler = false;
2365 Args saved_orig_args;
eea89d4a 2366 std::optional<uint32_t> original_umask;
ea433578 2367 std::string saved_temp_dir;
2adbab62 2368
e1a53fd0
JR
2369 auto argv_parts = split_argv(argc, argv);
2370 if (argv_parts.compiler_and_args.empty()) {
2371 throw core::Fatal("no compiler given, see \"ccache --help\"");
2372 }
2373
dd8f65aa
JR
2374 {
2375 Context ctx;
e1a53fd0
JR
2376 ctx.initialize(std::move(argv_parts.compiler_and_args),
2377 argv_parts.config_settings);
dd8f65aa 2378 SignalHandler signal_handler(ctx);
f88e6084 2379 util::Finalizer finalizer([&ctx] { finalize_at_exit(ctx); });
dd8f65aa 2380
e1a53fd0 2381 initialize(ctx, argv, argv_parts.masquerading_as_compiler);
dd8f65aa 2382
e1a53fd0 2383 const auto result = do_cache_compilation(ctx);
23bbc238
JR
2384 ctx.storage.local.increment_statistics(result ? *result
2385 : result.error().counters());
2386 const auto& counters = ctx.storage.local.get_statistics_updates();
2387
2388 if (counters.get(Statistic::cache_miss) > 0) {
2389 if (!ctx.config.remote_only()) {
2390 ctx.storage.local.increment_statistic(Statistic::local_storage_miss);
2391 }
2392 if (ctx.storage.has_remote_storage()) {
2393 ctx.storage.local.increment_statistic(Statistic::remote_storage_miss);
2394 }
2395 } else if ((counters.get(Statistic::direct_cache_hit) > 0
2396 || counters.get(Statistic::preprocessed_cache_hit) > 0)
2397 && counters.get(Statistic::remote_storage_hit) > 0
2398 && !ctx.config.remote_only()) {
2399 ctx.storage.local.increment_statistic(Statistic::local_storage_miss);
2400 }
2401
85f5f8af
JR
2402 if (!result) {
2403 if (result.error().exit_code()) {
2404 return *result.error().exit_code();
dd8f65aa
JR
2405 }
2406 // Else: Fall back to running the real compiler.
2407 fall_back_to_original_compiler = true;
2adbab62 2408
3c201cf4 2409 original_umask = ctx.original_umask;
cc2236b2 2410
706f7443 2411 ASSERT(!ctx.orig_args.empty());
106a1d22 2412
dd8f65aa
JR
2413 ctx.orig_args.erase_with_prefix("--ccache-");
2414 add_prefix(ctx, ctx.orig_args, ctx.config.prefix_command());
2adbab62 2415
60904e7b 2416 LOG_RAW("Failed; falling back to running the real compiler");
2adbab62 2417
ea433578 2418 saved_temp_dir = ctx.config.temporary_dir();
dd8f65aa
JR
2419 saved_orig_args = std::move(ctx.orig_args);
2420 auto execv_argv = saved_orig_args.to_argv();
7019a3d0 2421 LOG("Executing {}", util::format_argv_for_logging(execv_argv.data()));
bfb7813a 2422 // Execute the original command below after ctx and finalizer have been
ea433578 2423 // destructed.
dd8f65aa
JR
2424 }
2425 }
ad52c600 2426
dd8f65aa 2427 if (fall_back_to_original_compiler) {
3c201cf4 2428 if (original_umask) {
6b53a79a 2429 util::set_umask(*original_umask);
3c201cf4 2430 }
ad52c600 2431 auto execv_argv = saved_orig_args.to_argv();
bfb7813a 2432 execute_noreturn(execv_argv.data(), saved_temp_dir);
eb266c99 2433 throw core::Fatal(
a4ab84f9 2434 FMT("execute_noreturn of {} failed: {}", execv_argv[0], strerror(errno)));
2adbab62 2435 }
dd8f65aa
JR
2436
2437 return EXIT_SUCCESS;
2adbab62
JR
2438}
2439
39606070 2440static tl::expected<core::StatisticsCounters, Failure>
e1a53fd0 2441do_cache_compilation(Context& ctx)
2adbab62 2442{
8b0f2eb6 2443 if (ctx.config.disable()) {
60904e7b 2444 LOG_RAW("ccache is disabled");
39606070 2445 return tl::unexpected(Statistic::none);
f5795cdb
JR
2446 }
2447
62ce4a31
JR
2448 if (ctx.actual_cwd.empty()) {
2449 LOG("Unable to determine current working directory: {}", strerror(errno));
39606070 2450 return tl::unexpected(Statistic::internal_error);
20696244 2451 }
f5795cdb 2452
5b4fd92c
JR
2453 // Set CCACHE_DISABLE so no process ccache executes from now on will risk
2454 // calling ccache second time. For instance, if the real compiler is a wrapper
2455 // script that calls "ccache $compiler ..." we want that inner ccache call to
2456 // be disabled.
09c32fb9 2457 util::setenv("CCACHE_DISABLE", "1");
5b4fd92c 2458
f5795cdb 2459 MTR_BEGIN("main", "process_args");
225497c0 2460 ProcessArgsResult processed = process_args(ctx);
fd8474e3
JR
2461 MTR_END("main", "process_args");
2462
225497c0 2463 if (processed.error) {
39606070 2464 return tl::unexpected(*processed.error);
f5795cdb 2465 }
bd9897fb 2466
85f5f8af 2467 TRY(set_up_uncached_err());
c4284c78 2468
c49fca9a
OS
2469 // VS_UNICODE_OUTPUT prevents capturing stdout/stderr, as the output is sent
2470 // directly to Visual Studio.
2471 if (ctx.config.compiler_type() == CompilerType::msvc) {
09c32fb9 2472 util::unsetenv("VS_UNICODE_OUTPUT");
c49fca9a
OS
2473 }
2474
fec40553
JR
2475 for (const auto& name : {"DEPENDENCIES_OUTPUT", "SUNPRO_DEPENDENCIES"}) {
2476 if (getenv(name)) {
2477 LOG("Unsupported environment variable: {}", name);
2478 return Statistic::unsupported_environment_variable;
2479 }
2480 }
2481
a2988ace
JR
2482 if (ctx.config.is_compiler_group_msvc()) {
2483 for (const auto& name : {"CL", "_CL_"}) {
2484 if (getenv(name)) {
2485 LOG("Unsupported environment variable: {}", name);
2486 return Statistic::unsupported_environment_variable;
2487 }
2488 }
2489 }
2490
caa5bcbb 2491 if (!ctx.config.run_second_cpp() && ctx.config.is_compiler_group_msvc()) {
543a919a
LL
2492 LOG_RAW("Second preprocessor cannot be disabled");
2493 ctx.config.set_run_second_cpp(true);
2494 }
2495
c86a4628
JR
2496 if (ctx.config.depend_mode()
2497 && !(ctx.config.run_second_cpp()
2498 && (ctx.args_info.generating_dependencies
2499 || ctx.args_info.generating_includes))) {
2500 LOG_RAW("Disabling depend mode");
2501 ctx.config.set_depend_mode(false);
f5795cdb
JR
2502 }
2503
0cd6f70b 2504 if (ctx.storage.has_remote_storage()) {
182eeb9f 2505 if (ctx.config.file_clone()) {
0cd6f70b 2506 LOG_RAW("Disabling file clone mode since remote storage is enabled");
182eeb9f
JR
2507 ctx.config.set_file_clone(false);
2508 }
2509 if (ctx.config.hard_link()) {
0cd6f70b 2510 LOG_RAW("Disabling hard link mode since remote storage is enabled");
182eeb9f
JR
2511 ctx.config.set_hard_link(false);
2512 }
2513 }
2514
60904e7b 2515 LOG("Source file: {}", ctx.args_info.input_file);
0ca27a6b 2516 if (ctx.args_info.generating_dependencies) {
60904e7b 2517 LOG("Dependency file: {}", ctx.args_info.output_dep);
f5795cdb 2518 }
b0cf85fc 2519 if (ctx.args_info.generating_coverage) {
60904e7b 2520 LOG_RAW("Coverage file is being generated");
f5795cdb 2521 }
177e6d86 2522 if (ctx.args_info.generating_stackusage) {
60904e7b 2523 LOG("Stack usage file: {}", ctx.args_info.output_su);
f5795cdb 2524 }
fdddb0b6 2525 if (ctx.args_info.generating_diagnostics) {
60904e7b 2526 LOG("Diagnostics file: {}", ctx.args_info.output_dia);
f5795cdb 2527 }
b18be33b 2528 if (!ctx.args_info.output_dwo.empty()) {
60904e7b 2529 LOG("Split dwarf file: {}", ctx.args_info.output_dwo);
f5795cdb
JR
2530 }
2531
60904e7b 2532 LOG("Object file: {}", ctx.args_info.output_obj);
4aa703f8 2533 MTR_META_THREAD_NAME(ctx.args_info.output_obj.c_str());
f5795cdb 2534
f8faf9b4 2535 if (ctx.config.debug() && ctx.config.debug_level() >= 2) {
d96b24a9
JR
2536 const auto path = prepare_debug_path(ctx.apparent_cwd,
2537 ctx.config.debug_dir(),
7c980edc 2538 ctx.time_of_invocation,
fec40553 2539 ctx.args_info.orig_output_obj,
7c980edc 2540 "input-text");
ea9a264e 2541 util::FileStream debug_text_file(path, "w");
f5795cdb 2542 if (debug_text_file) {
91aa7075 2543 ctx.hash_debug_files.push_back(std::move(debug_text_file));
f5795cdb 2544 } else {
60904e7b 2545 LOG("Failed to open {}: {}", path, strerror(errno));
f5795cdb 2546 }
f5795cdb
JR
2547 }
2548
91aa7075
JR
2549 FILE* debug_text_file = !ctx.hash_debug_files.empty()
2550 ? ctx.hash_debug_files.front().get()
2551 : nullptr;
2552
a5021452 2553 Hash common_hash;
a181d44d 2554 init_hash_debug(ctx, common_hash, 'c', "COMMON", debug_text_file);
f5795cdb 2555
b3c3e799
JR
2556 if (should_disable_ccache_for_input_file(ctx.args_info.input_file)) {
2557 LOG("{} found in {}, disabling ccache",
2558 k_ccache_disable_token,
2559 ctx.args_info.input_file);
39606070 2560 return tl::unexpected(Statistic::disabled);
b3c3e799
JR
2561 }
2562
705b14b9
JR
2563 {
2564 MTR_SCOPE("hash", "common_hash");
2565 TRY(hash_common_info(
2566 ctx, processed.preprocessor_args, common_hash, ctx.args_info));
2567 }
f5795cdb 2568
195011ad
JR
2569 if (processed.hash_actual_cwd) {
2570 common_hash.hash_delimiter("actual_cwd");
2571 common_hash.hash(ctx.actual_cwd);
2572 }
2573
f5795cdb 2574 // Try to find the hash using the manifest.
a5021452 2575 Hash direct_hash = common_hash;
a181d44d 2576 init_hash_debug(ctx, direct_hash, 'd', "DIRECT MODE", debug_text_file);
f5795cdb 2577
225497c0
AL
2578 Args args_to_hash = processed.preprocessor_args;
2579 args_to_hash.push_back(processed.extra_args_to_hash);
25e73c1f 2580
f5795cdb 2581 bool put_result_in_manifest = false;
0e4e4b63
JR
2582 std::optional<Hash::Digest> result_key;
2583 std::optional<Hash::Digest> result_key_from_manifest;
2584 std::optional<Hash::Digest> manifest_key;
c7c0837a 2585
8b0f2eb6 2586 if (ctx.config.direct_mode()) {
60904e7b 2587 LOG_RAW("Trying direct lookup");
705b14b9 2588 MTR_BEGIN("hash", "direct_hash");
85f5f8af 2589 const auto result_and_manifest_key = calculate_result_and_manifest_key(
dda86ed9 2590 ctx, args_to_hash, direct_hash, nullptr);
705b14b9 2591 MTR_END("hash", "direct_hash");
85f5f8af 2592 if (!result_and_manifest_key) {
39606070 2593 return tl::unexpected(result_and_manifest_key.error());
85f5f8af
JR
2594 }
2595 std::tie(result_key, manifest_key) = *result_and_manifest_key;
c7c0837a 2596 if (result_key) {
f5795cdb 2597 // If we can return from cache at this point then do so.
e08af162 2598 const auto from_cache_result =
a9567b9a 2599 from_cache(ctx, FromCacheCallMode::direct, *result_key);
e08af162 2600 if (!from_cache_result) {
39606070 2601 return tl::unexpected(from_cache_result.error());
e08af162 2602 } else if (*from_cache_result) {
a9567b9a 2603 return Statistic::direct_cache_hit;
b646eb0a 2604 }
f5795cdb
JR
2605
2606 // Wasn't able to return from cache at this point. However, the result
2607 // was already found in manifest, so don't re-add it later.
2608 put_result_in_manifest = false;
2609
c7c0837a 2610 result_key_from_manifest = result_key;
f5795cdb
JR
2611 } else {
2612 // Add result to manifest later.
2613 put_result_in_manifest = true;
2614 }
a9567b9a 2615
1dd9b230 2616 if (!ctx.config.recache()) {
0cd6f70b 2617 ctx.storage.local.increment_statistic(Statistic::direct_cache_miss);
1dd9b230 2618 }
f5795cdb
JR
2619 }
2620
8b0f2eb6 2621 if (ctx.config.read_only_direct()) {
60904e7b 2622 LOG_RAW("Read-only direct mode; running real compiler");
39606070 2623 return tl::unexpected(Statistic::cache_miss);
f5795cdb
JR
2624 }
2625
8b0f2eb6 2626 if (!ctx.config.depend_mode()) {
f5795cdb 2627 // Find the hash using the preprocessed output. Also updates
8b595b04 2628 // ctx.included_files.
a5021452 2629 Hash cpp_hash = common_hash;
a181d44d 2630 init_hash_debug(ctx, cpp_hash, 'p', "PREPROCESSOR MODE", debug_text_file);
f5795cdb
JR
2631
2632 MTR_BEGIN("hash", "cpp_hash");
85f5f8af 2633 const auto result_and_manifest_key = calculate_result_and_manifest_key(
dda86ed9 2634 ctx, args_to_hash, cpp_hash, &processed.preprocessor_args);
705b14b9 2635 MTR_END("hash", "cpp_hash");
85f5f8af 2636 if (!result_and_manifest_key) {
39606070 2637 return tl::unexpected(result_and_manifest_key.error());
85f5f8af
JR
2638 }
2639 result_key = result_and_manifest_key->first;
23aa971f 2640
c7c0837a 2641 // calculate_result_and_manifest_key always returns a non-nullopt result_key
dda86ed9 2642 // in preprocessor mode (non-nullptr last argument).
c7c0837a 2643 ASSERT(result_key);
fd8474e3 2644
c7c0837a 2645 if (result_key_from_manifest && result_key_from_manifest != result_key) {
f5795cdb
JR
2646 // The hash from manifest differs from the hash of the preprocessor
2647 // output. This could be because:
2648 //
2649 // - The preprocessor produces different output for the same input (not
2650 // likely).
2651 // - There's a bug in ccache (maybe incorrect handling of compiler
2652 // arguments).
2653 // - The user has used a different CCACHE_BASEDIR (most likely).
2654 //
2655 // The best thing here would probably be to remove the hash entry from
2656 // the manifest. For now, we use a simpler method: just remove the
2657 // manifest file.
60904e7b
JR
2658 LOG_RAW("Hash from manifest doesn't match preprocessor output");
2659 LOG_RAW("Likely reason: different CCACHE_BASEDIRs used");
2660 LOG_RAW("Removing manifest as a safety measure");
c7c0837a 2661 ctx.storage.remove(*result_key, core::CacheEntryType::result);
f5795cdb
JR
2662
2663 put_result_in_manifest = true;
2664 }
2665
2666 // If we can return from cache at this point then do.
e08af162
JR
2667 const auto from_cache_result =
2668 from_cache(ctx, FromCacheCallMode::cpp, *result_key);
2669 if (!from_cache_result) {
39606070 2670 return tl::unexpected(from_cache_result.error());
e08af162 2671 } else if (*from_cache_result) {
792b27b8 2672 if (ctx.config.direct_mode() && manifest_key && put_result_in_manifest) {
d663cb51
JR
2673 MTR_SCOPE("cache", "update_manifest");
2674 update_manifest(ctx, *manifest_key, *result_key);
2fad4567 2675 }
a9567b9a 2676 return Statistic::preprocessed_cache_hit;
b646eb0a 2677 }
a9567b9a 2678
fbe45b77
JR
2679 if (!ctx.config.recache()) {
2680 ctx.storage.local.increment_statistic(Statistic::preprocessed_cache_miss);
2681 }
f5795cdb
JR
2682 }
2683
8b0f2eb6 2684 if (ctx.config.read_only()) {
60904e7b 2685 LOG_RAW("Read-only mode; running real compiler");
39606070 2686 return tl::unexpected(Statistic::cache_miss);
f5795cdb
JR
2687 }
2688
225497c0 2689 add_prefix(ctx, processed.compiler_args, ctx.config.prefix_command());
f5795cdb
JR
2690
2691 // In depend_mode, extend the direct hash.
a5021452 2692 Hash* depend_mode_hash = ctx.config.depend_mode() ? &direct_hash : nullptr;
f5795cdb
JR
2693
2694 // Run real compiler, sending output to cache.
2695 MTR_BEGIN("cache", "to_cache");
85f5f8af
JR
2696 const auto digest = to_cache(ctx,
2697 processed.compiler_args,
2698 result_key,
2699 ctx.args_info.depend_extra_args,
2700 depend_mode_hash);
705b14b9 2701 MTR_END("cache", "to_cache");
85f5f8af 2702 if (!digest) {
39606070 2703 return tl::unexpected(digest.error());
85f5f8af
JR
2704 }
2705 result_key = *digest;
c7c0837a
JR
2706 if (ctx.config.direct_mode()) {
2707 ASSERT(manifest_key);
923b71c2 2708 MTR_SCOPE("cache", "update_manifest");
d663cb51 2709 update_manifest(ctx, *manifest_key, *result_key);
c7c0837a 2710 }
f5795cdb 2711
5fcec2b2 2712 return ctx.config.recache() ? Statistic::recache : Statistic::cache_miss;
f42859a1
AT
2713}
2714
73f6c52a 2715bool
f6ac29e8 2716is_ccache_executable(const fs::path& path)
73f6c52a 2717{
f6ac29e8 2718 std::string name = path.filename().string();
73f6c52a
JR
2719#ifdef _WIN32
2720 name = util::to_lowercase(name);
2721#endif
2722 return util::starts_with(name, "ccache");
2723}
2724
587b0244
JR
2725bool
2726file_path_matches_dir_prefix_or_file(const fs::path& dir_prefix_or_file,
2727 const fs::path& file_path)
2728{
2729 DEBUG_ASSERT(!dir_prefix_or_file.empty());
2730 DEBUG_ASSERT(!file_path.filename().empty());
2731
2732 auto end = std::mismatch(dir_prefix_or_file.begin(),
2733 dir_prefix_or_file.end(),
2734 file_path.begin(),
2735 file_path.end())
2736 .first;
2737 return end == dir_prefix_or_file.end() || end->empty();
2738}
2739
530dfe7c 2740int
9131b059 2741ccache_main(int argc, const char* const* argv)
f42859a1 2742{
728acfac 2743 try {
73f6c52a 2744 if (is_ccache_executable(argv[0])) {
728acfac 2745 if (argc < 2) {
451d92c8 2746 PRINT_RAW(stderr, core::get_usage_text(Util::base_name(argv[0])));
47e5952e 2747 exit(EXIT_FAILURE);
728acfac 2748 }
c7c0837a
JR
2749 // If the first argument isn't an option, then assume we are being
2750 // passed a compiler name and options.
728acfac 2751 if (argv[1][0] == '-') {
32c037e7 2752 return core::process_main_options(argc, argv);
728acfac 2753 }
f5795cdb 2754 }
f5795cdb 2755
cc2236b2 2756 return cache_compilation(argc, argv);
eb266c99 2757 } catch (const core::ErrorBase& e) {
01929c5c 2758 PRINT(stderr, "ccache: error: {}\n", e.what());
2adbab62 2759 return EXIT_FAILURE;
728acfac 2760 }
f42859a1 2761}