Index: tools/gn/ninja_binary_target_writer.cc |
diff --git a/tools/gn/ninja_binary_target_writer.cc b/tools/gn/ninja_binary_target_writer.cc |
index b96979d66c3009220572c675d9cc5a9c60243274..4c1a7d7e173e806a757e093f9a0315b158425c30 100644 |
--- a/tools/gn/ninja_binary_target_writer.cc |
+++ b/tools/gn/ninja_binary_target_writer.cc |
@@ -127,7 +127,7 @@ void NinjaBinaryTargetWriter::WriteSources( |
const Target::FileList& sources = target_->sources(); |
object_files->reserve(sources.size()); |
- std::string implicit_deps = |
+ OutputFile input_dep = |
WriteInputDepsStampAndGetDep(std::vector<const Target*>()); |
std::string rule_prefix = GetNinjaRulePrefixForToolchain(settings_); |
@@ -145,7 +145,35 @@ void NinjaBinaryTargetWriter::WriteSources( |
out_ << ": " << rule_prefix << Toolchain::ToolTypeToName(tool_type); |
out_ << " "; |
path_output_.WriteFile(out_, sources[i]); |
- out_ << implicit_deps << std::endl; |
+ if (!input_dep.value().empty()) { |
+ // Write out the input dependencies as an order-only dependency. This |
+ // will cause Ninja to make sure the inputs are up-to-date before |
+ // compiling this source, but changes in the inputs deps won't cause |
+ // the file to be recompiled. |
+ // |
+ // This is important to prevent changes in unrelated actions that |
+ // are upstream of this target from causing everything to be recompiled. |
+ // |
+ // Why can we get away with this rather than using implicit deps ("|", |
+ // which will force rebuilds when the inputs change)? For source code, |
+ // the computed dependencies of all headers will be computed by the |
+ // compiler, which will cause source rebuilds if any "real" upstream |
+ // dependencies change. |
+ // |
+ // If a .cc file is generated by an input dependency, Ninja will see |
+ // the input to the build rule doesn't exist, and that it is an output |
+ // from a previous step, and build the previous step first. This is a |
+ // "real" dependency and doesn't need | or || to express. |
+ // |
+ // The only case where this rule matters is for the first build where |
+ // no .d files exist, and Ninja doesn't know what that source file |
+ // depends on. In this case it's sufficient to ensure that the upstream |
+ // dependencies are built first. This is exactly what Ninja's order- |
+ // only dependencies expresses. |
+ out_ << " || "; |
+ path_output_.WriteFile(out_, input_dep); |
+ } |
+ out_ << std::endl; |
} |
// It's theoretically possible for a compiler to produce more than one |
@@ -215,6 +243,18 @@ void NinjaBinaryTargetWriter::WriteLinkerStuff( |
} |
// Append data dependencies as order-only dependencies. |
+ // |
+ // This will include data dependencies and input dependencies (like when |
+ // this target depends on an action). Having the data dependencies in this |
+ // list ensures that the data is available at runtime when the user builds |
+ // this target. |
+ // |
+ // The action dependencies are not strictly necessary in this case. They |
+ // should also have been collected via the input deps stamp that each source |
+ // file has for an order-only dependency, and since this target depends on |
+ // the sources, there is already an implicit order-only dependency. However, |
+ // it's extra work to separate these out and there's no disadvantage to |
+ // listing them again. |
WriteOrderOnlyDependencies(non_linkable_deps); |
// End of the link "build" line. |