OLD | NEW |
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "tools/gn/ninja_binary_target_writer.h" | 5 #include "tools/gn/ninja_binary_target_writer.h" |
6 | 6 |
7 #include <set> | 7 #include <set> |
8 | 8 |
9 #include "base/strings/string_util.h" | 9 #include "base/strings/string_util.h" |
10 #include "tools/gn/config_values_extractors.h" | 10 #include "tools/gn/config_values_extractors.h" |
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
120 #undef WRITE_FLAGS | 120 #undef WRITE_FLAGS |
121 | 121 |
122 WriteSharedVars(subst); | 122 WriteSharedVars(subst); |
123 } | 123 } |
124 | 124 |
125 void NinjaBinaryTargetWriter::WriteSources( | 125 void NinjaBinaryTargetWriter::WriteSources( |
126 std::vector<OutputFile>* object_files) { | 126 std::vector<OutputFile>* object_files) { |
127 const Target::FileList& sources = target_->sources(); | 127 const Target::FileList& sources = target_->sources(); |
128 object_files->reserve(sources.size()); | 128 object_files->reserve(sources.size()); |
129 | 129 |
130 std::string implicit_deps = | 130 OutputFile input_dep = |
131 WriteInputDepsStampAndGetDep(std::vector<const Target*>()); | 131 WriteInputDepsStampAndGetDep(std::vector<const Target*>()); |
132 | 132 |
133 std::string rule_prefix = GetNinjaRulePrefixForToolchain(settings_); | 133 std::string rule_prefix = GetNinjaRulePrefixForToolchain(settings_); |
134 | 134 |
135 std::vector<OutputFile> tool_outputs; // Prevent reallocation in loop. | 135 std::vector<OutputFile> tool_outputs; // Prevent reallocation in loop. |
136 for (size_t i = 0; i < sources.size(); i++) { | 136 for (size_t i = 0; i < sources.size(); i++) { |
137 Toolchain::ToolType tool_type = Toolchain::TYPE_NONE; | 137 Toolchain::ToolType tool_type = Toolchain::TYPE_NONE; |
138 if (!GetOutputFilesForSource(target_, sources[i], | 138 if (!GetOutputFilesForSource(target_, sources[i], |
139 &tool_type, &tool_outputs)) | 139 &tool_type, &tool_outputs)) |
140 continue; // No output for this source. | 140 continue; // No output for this source. |
141 | 141 |
142 if (tool_type != Toolchain::TYPE_NONE) { | 142 if (tool_type != Toolchain::TYPE_NONE) { |
143 out_ << "build"; | 143 out_ << "build"; |
144 path_output_.WriteFiles(out_, tool_outputs); | 144 path_output_.WriteFiles(out_, tool_outputs); |
145 out_ << ": " << rule_prefix << Toolchain::ToolTypeToName(tool_type); | 145 out_ << ": " << rule_prefix << Toolchain::ToolTypeToName(tool_type); |
146 out_ << " "; | 146 out_ << " "; |
147 path_output_.WriteFile(out_, sources[i]); | 147 path_output_.WriteFile(out_, sources[i]); |
148 out_ << implicit_deps << std::endl; | 148 if (!input_dep.value().empty()) { |
| 149 // Write out the input dependencies as an order-only dependency. This |
| 150 // will cause Ninja to make sure the inputs are up-to-date before |
| 151 // compiling this source, but changes in the inputs deps won't cause |
| 152 // the file to be recompiled. |
| 153 // |
| 154 // This is important to prevent changes in unrelated actions that |
| 155 // are upstream of this target from causing everything to be recompiled. |
| 156 // |
| 157 // Why can we get away with this rather than using implicit deps ("|", |
| 158 // which will force rebuilds when the inputs change)? For source code, |
| 159 // the computed dependencies of all headers will be computed by the |
| 160 // compiler, which will cause source rebuilds if any "real" upstream |
| 161 // dependencies change. |
| 162 // |
| 163 // If a .cc file is generated by an input dependency, Ninja will see |
| 164 // the input to the build rule doesn't exist, and that it is an output |
| 165 // from a previous step, and build the previous step first. This is a |
| 166 // "real" dependency and doesn't need | or || to express. |
| 167 // |
| 168 // The only case where this rule matters is for the first build where |
| 169 // no .d files exist, and Ninja doesn't know what that source file |
| 170 // depends on. In this case it's sufficient to ensure that the upstream |
| 171 // dependencies are built first. This is exactly what Ninja's order- |
| 172 // only dependencies expresses. |
| 173 out_ << " || "; |
| 174 path_output_.WriteFile(out_, input_dep); |
| 175 } |
| 176 out_ << std::endl; |
149 } | 177 } |
150 | 178 |
151 // It's theoretically possible for a compiler to produce more than one | 179 // It's theoretically possible for a compiler to produce more than one |
152 // output, but we'll only link to the first output. | 180 // output, but we'll only link to the first output. |
153 object_files->push_back(tool_outputs[0]); | 181 object_files->push_back(tool_outputs[0]); |
154 } | 182 } |
155 out_ << std::endl; | 183 out_ << std::endl; |
156 } | 184 } |
157 | 185 |
158 void NinjaBinaryTargetWriter::WriteLinkerStuff( | 186 void NinjaBinaryTargetWriter::WriteLinkerStuff( |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
208 } | 236 } |
209 } | 237 } |
210 | 238 |
211 // Append implicit dependencies collected above. | 239 // Append implicit dependencies collected above. |
212 if (!implicit_deps.empty()) { | 240 if (!implicit_deps.empty()) { |
213 out_ << " |"; | 241 out_ << " |"; |
214 path_output_.WriteFiles(out_, implicit_deps); | 242 path_output_.WriteFiles(out_, implicit_deps); |
215 } | 243 } |
216 | 244 |
217 // Append data dependencies as order-only dependencies. | 245 // Append data dependencies as order-only dependencies. |
| 246 // |
| 247 // This will include data dependencies and input dependencies (like when |
| 248 // this target depends on an action). Having the data dependencies in this |
| 249 // list ensures that the data is available at runtime when the user builds |
| 250 // this target. |
| 251 // |
| 252 // The action dependencies are not strictly necessary in this case. They |
| 253 // should also have been collected via the input deps stamp that each source |
| 254 // file has for an order-only dependency, and since this target depends on |
| 255 // the sources, there is already an implicit order-only dependency. However, |
| 256 // it's extra work to separate these out and there's no disadvantage to |
| 257 // listing them again. |
218 WriteOrderOnlyDependencies(non_linkable_deps); | 258 WriteOrderOnlyDependencies(non_linkable_deps); |
219 | 259 |
220 // End of the link "build" line. | 260 // End of the link "build" line. |
221 out_ << std::endl; | 261 out_ << std::endl; |
222 | 262 |
223 // These go in the inner scope of the link line. | 263 // These go in the inner scope of the link line. |
224 WriteLinkerFlags(); | 264 WriteLinkerFlags(); |
225 WriteLibs(); | 265 WriteLibs(); |
226 WriteOutputExtension(); | 266 WriteOutputExtension(); |
227 WriteSolibs(solibs); | 267 WriteSolibs(solibs); |
(...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
429 return false; // No tool for this file (it's a header file or something). | 469 return false; // No tool for this file (it's a header file or something). |
430 const Tool* tool = target->toolchain()->GetTool(*computed_tool_type); | 470 const Tool* tool = target->toolchain()->GetTool(*computed_tool_type); |
431 if (!tool) | 471 if (!tool) |
432 return false; // Tool does not apply for this toolchain.file. | 472 return false; // Tool does not apply for this toolchain.file. |
433 | 473 |
434 // Figure out what output(s) this compiler produces. | 474 // Figure out what output(s) this compiler produces. |
435 SubstitutionWriter::ApplyListToCompilerAsOutputFile( | 475 SubstitutionWriter::ApplyListToCompilerAsOutputFile( |
436 target, source, tool->outputs(), outputs); | 476 target, source, tool->outputs(), outputs); |
437 return !outputs->empty(); | 477 return !outputs->empty(); |
438 } | 478 } |
OLD | NEW |