/* Whether the output is a precompiled header */
static bool output_is_precompiled_header = false;
+/* Whether we should output to the real object first before saving into cache */
+static bool output_to_real_object_first = false;
+
/*
* Whether we are using a precompiled header (either via -include or #include).
*/
}
tmp_stdout = format("%s.tmp.stdout.%s", cached_obj, tmp_string());
tmp_stderr = format("%s.tmp.stderr.%s", cached_obj, tmp_string());
- tmp_obj = format("%s.tmp.%s", cached_obj, tmp_string());
+
+ if (output_to_real_object_first) {
+ cc_log("Outputting to final destination");
+ tmp_obj = output_obj;
+ } else {
+ tmp_obj = format("%s.tmp.%s", cached_obj, tmp_string());
+ }
args_add(args, "-o");
args_add(args, tmp_obj);
fd = open(tmp_stderr, O_RDONLY | O_BINARY);
if (fd != -1) {
if (str_eq(output_obj, "/dev/null")
- || (access(tmp_obj, R_OK) == 0
+ || (! output_to_real_object_first
+ && access(tmp_obj, R_OK) == 0
&& move_file(tmp_obj, output_obj, 0) == 0)
|| errno == ENOENT) {
/* we can use a quick method of getting the failed output */
} else {
tmp_unlink(tmp_stderr);
}
- if (move_uncompressed_file(tmp_obj, cached_obj, enable_compression) != 0) {
+
+ if (output_to_real_object_first) {
+ if (copy_file(tmp_obj, cached_obj, enable_compression) != 0) {
+ cc_log("Failed to move %s to %s: %s", tmp_obj, cached_obj, strerror(errno));
+ stats_update(STATS_ERROR);
+ failed();
+ }
+ } else if (move_uncompressed_file(tmp_obj, cached_obj, enable_compression) != 0) {
cc_log("Failed to move %s to %s: %s", tmp_obj, cached_obj, strerror(errno));
stats_update(STATS_ERROR);
failed();
- } else {
- cc_log("Stored in cache: %s", cached_obj);
- stat(cached_obj, &st);
- added_bytes += file_size(&st);
- added_files += 1;
}
+ cc_log("Stored in cache: %s", cached_obj);
+ stat(cached_obj, &st);
+ added_bytes += file_size(&st);
+ added_files += 1;
/*
* Do an extra stat on the potentially compressed object file for the
goto out;
}
+ /* We need to output to the real object first here, otherwise
+ * runtime artifacts will be produced in the wrong place. */
+ if (compopt_needs_realdir(argv[i])) {
+ output_to_real_object_first = true;
+ if (base_dir) {
+ cc_log("Disabling base dir due to %s", argv[i]);
+ base_dir = NULL;
+ }
+ }
+
/* These are too hard in direct mode. */
if (enable_direct) {
if (compopt_too_hard_for_direct_mode(argv[i])) {
#define TAKES_CONCAT_ARG (1 << 3)
#define TAKES_PATH (1 << 4)
#define AFFECTS_CPP (1 << 5)
+#define NEEDS_REALDIR (1 << 6)
struct compopt {
const char *name;
};
static const struct compopt compopts[] = {
- {"--coverage", TOO_HARD},
+ {"--coverage", TOO_HARD}, /* implies -ftest-coverage */
{"--param", TAKES_ARG},
{"-A", TAKES_ARG},
{"-D", AFFECTS_CPP | TAKES_ARG | TAKES_CONCAT_ARG},
{"-aux-info", TAKES_ARG},
{"-b", TAKES_ARG},
{"-fbranch-probabilities", TOO_HARD},
- {"-fprofile-arcs", TOO_HARD},
- {"-fprofile-generate", TOO_HARD},
+ {"-fprofile-arcs", NEEDS_REALDIR},
+ {"-fprofile-generate", NEEDS_REALDIR},
{"-fprofile-use", TOO_HARD},
{"-frepo", TOO_HARD},
- {"-ftest-coverage", TOO_HARD},
+ {"-ftest-coverage", TOO_HARD}, /* generates a .gcno file at the same time */
{"-idirafter", AFFECTS_CPP | TAKES_ARG | TAKES_PATH},
{"-iframework", AFFECTS_CPP | TAKES_ARG | TAKES_CONCAT_ARG | TAKES_PATH},
{"-imacros", AFFECTS_CPP | TAKES_ARG | TAKES_PATH},
const struct compopt *co = find(option);
return co && (co->type & TAKES_ARG);
}
+
+bool
+compopt_needs_realdir(const char *option)
+{
+ const struct compopt *co = find(option);
+ return co && (co->type & NEEDS_REALDIR);
+}