Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(612)

Side by Side Diff: tools/gn/ninja_target_writer.cc

Issue 1663813003: GN: Don't write stamp files for one rule. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « tools/gn/ninja_copy_target_writer_unittest.cc ('k') | tools/gn/ninja_target_writer_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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_target_writer.h" 5 #include "tools/gn/ninja_target_writer.h"
6 6
7 #include <sstream> 7 #include <sstream>
8 8
9 #include "base/files/file_util.h" 9 #include "base/files/file_util.h"
10 #include "base/strings/string_util.h" 10 #include "base/strings/string_util.h"
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after
140 if (written_anything) 140 if (written_anything)
141 out_ << std::endl; 141 out_ << std::endl;
142 } 142 }
143 143
144 OutputFile NinjaTargetWriter::WriteInputDepsStampAndGetDep( 144 OutputFile NinjaTargetWriter::WriteInputDepsStampAndGetDep(
145 const std::vector<const Target*>& extra_hard_deps) const { 145 const std::vector<const Target*>& extra_hard_deps) const {
146 CHECK(target_->toolchain()) 146 CHECK(target_->toolchain())
147 << "Toolchain not set on target " 147 << "Toolchain not set on target "
148 << target_->label().GetUserVisibleName(true); 148 << target_->label().GetUserVisibleName(true);
149 149
150 // For an action (where we run a script only once) the sources are the same 150 // ----------
151 // as the source prereqs. 151 // Collect all input files that are input deps of this target. Knowing the
152 bool list_sources_as_input_deps = (target_->output_type() == Target::ACTION); 152 // number before writing allows us to either skip writing the input deps
153 // stamp or optimize it. Use pointers to avoid copies here.
154 std::vector<const SourceFile*> input_deps_sources;
155 input_deps_sources.reserve(32);
153 156
154 // Actions get implicit dependencies on the script itself. 157 // Actions get implicit dependencies on the script itself.
155 bool add_script_source_as_dep = 158 if (target_->output_type() == Target::ACTION ||
156 (target_->output_type() == Target::ACTION) || 159 target_->output_type() == Target::ACTION_FOREACH)
157 (target_->output_type() == Target::ACTION_FOREACH); 160 input_deps_sources.push_back(&target_->action_values().script());
158 161
159 if (!add_script_source_as_dep && 162 // Input files.
160 extra_hard_deps.empty() && 163 for (const auto& input : target_->inputs())
161 target_->inputs().empty() && 164 input_deps_sources.push_back(&input);
162 target_->recursive_hard_deps().empty() &&
163 (!list_sources_as_input_deps || target_->sources().empty()) &&
164 target_->toolchain()->deps().empty())
165 return OutputFile(); // No input/hard deps.
166 165
167 // One potential optimization is if there are few input dependencies (or 166 // For an action (where we run a script only once) the sources are the same
168 // potentially few sources that depend on these) it's better to just write 167 // as the inputs. For action_foreach, the sources will be operated on
169 // all hard deps on each sources line than have this intermediate stamp. We 168 // separately so don't handle them here.
170 // do the stamp file because duplicating all the order-only deps for each 169 if (target_->output_type() == Target::ACTION) {
171 // source file can really explode the ninja file but this won't be the most 170 for (const auto& source : target_->sources())
172 // optimal thing in all cases. 171 input_deps_sources.push_back(&source);
173
174 OutputFile input_stamp_file(
175 RebasePath(GetTargetOutputDir(target_).value(),
176 settings_->build_settings()->build_dir(),
177 settings_->build_settings()->root_path_utf8()));
178 input_stamp_file.value().append(target_->label().name());
179 input_stamp_file.value().append(".inputdeps.stamp");
180
181 out_ << "build ";
182 path_output_.WriteFile(out_, input_stamp_file);
183 out_ << ": "
184 << GetNinjaRulePrefixForToolchain(settings_)
185 << Toolchain::ToolTypeToName(Toolchain::TYPE_STAMP);
186
187 // Script file (if applicable).
188 if (add_script_source_as_dep) {
189 out_ << " ";
190 path_output_.WriteFile(out_, target_->action_values().script());
191 } 172 }
192 173
193 // Input files are order-only deps. 174 // ----------
194 for (const auto& input : target_->inputs()) { 175 // Collect all target input dependencies of this target as was done for the
195 out_ << " "; 176 // files above.
196 path_output_.WriteFile(out_, input); 177 std::vector<const Target*> input_deps_targets;
197 } 178 input_deps_targets.reserve(32);
198 if (list_sources_as_input_deps) {
199 for (const auto& source : target_->sources()) {
200 out_ << " ";
201 path_output_.WriteFile(out_, source);
202 }
203 }
204
205 // The different souces of input deps may duplicate some targets, so uniquify
206 // them. These are sorted so the generated files are deterministic.
207 std::vector<const Target*> sorted_deps;
208 179
209 // Hard dependencies that are direct or indirect dependencies. 180 // Hard dependencies that are direct or indirect dependencies.
210 // These are large (up to 100s), hence why we check other 181 // These are large (up to 100s), hence why we check other
211 const std::set<const Target*>& hard_deps(target_->recursive_hard_deps()); 182 const std::set<const Target*>& hard_deps(target_->recursive_hard_deps());
183 for (const Target* target : hard_deps)
184 input_deps_targets.push_back(target);
212 185
213 // Extra hard dependencies passed in. Note that these are usually empty/small. 186 // Extra hard dependencies passed in. These are usually empty or small, and
187 // we don't want to duplicate the explicit hard deps of the target.
214 for (const Target* target : extra_hard_deps) { 188 for (const Target* target : extra_hard_deps) {
215 if (!hard_deps.count(target)) 189 if (!hard_deps.count(target))
216 sorted_deps.push_back(target); 190 input_deps_targets.push_back(target);
217 } 191 }
218 192
219 // Toolchain dependencies. These must be resolved before doing anything. 193 // Toolchain dependencies. These must be resolved before doing anything.
220 // This just writes all toolchain deps for simplicity. If we find that 194 // This just writes all toolchain deps for simplicity. If we find that
221 // toolchains often have more than one dependency, we could consider writing 195 // toolchains often have more than one dependency, we could consider writing
222 // a toolchain-specific stamp file and only include the stamp here. 196 // a toolchain-specific stamp file and only include the stamp here.
223 // Note that these are usually empty/small. 197 // Note that these are usually empty/small.
224 const LabelTargetVector& toolchain_deps = target_->toolchain()->deps(); 198 const LabelTargetVector& toolchain_deps = target_->toolchain()->deps();
225 for (const auto& toolchain_dep : toolchain_deps) { 199 for (const auto& toolchain_dep : toolchain_deps) {
226 // This could theoretically duplicate dependencies already in the list, 200 // This could theoretically duplicate dependencies already in the list,
227 // but shouldn't happen in practice, is inconvenient to check for, 201 // but it shouldn't happen in practice, is inconvenient to check for,
228 // and only results in harmless redundant dependencies listed. 202 // and only results in harmless redundant dependencies listed.
229 if (!hard_deps.count(toolchain_dep.ptr)) 203 input_deps_targets.push_back(toolchain_dep.ptr);
230 sorted_deps.push_back(toolchain_dep.ptr);
231 } 204 }
232 205
233 for (const Target* target : hard_deps) { 206 // ---------
234 sorted_deps.push_back(target); 207 // Write the outputs.
208
209 if (input_deps_sources.size() + input_deps_targets.size() == 0)
210 return OutputFile(); // No input dependencies.
211
212 // If we're only generating one input dependency, return it directly instead
213 // of writing a stamp file for it.
214 if (input_deps_sources.size() == 1 && input_deps_targets.size() == 0)
scottmg 2016/02/03 22:41:18 Did you check if it's worth pushing multiple throu
brettw 2016/02/03 22:50:44 No, but doing this for 2 will definitely increase
215 return OutputFile(settings_->build_settings(), *input_deps_sources[0]);
216 if (input_deps_sources.size() == 0 && input_deps_targets.size() == 1) {
217 const OutputFile& dep = input_deps_targets[0]->dependency_output_file();
218 DCHECK(!dep.value().empty());
219 return dep;
235 } 220 }
236 221
222 // Make a stamp file.
223 OutputFile input_stamp_file(
224 RebasePath(GetTargetOutputDir(target_).value(),
225 settings_->build_settings()->build_dir(),
226 settings_->build_settings()->root_path_utf8()));
227 input_stamp_file.value().append(target_->label().name());
228 input_stamp_file.value().append(".inputdeps.stamp");
229
230 out_ << "build ";
231 path_output_.WriteFile(out_, input_stamp_file);
232 out_ << ": "
233 << GetNinjaRulePrefixForToolchain(settings_)
234 << Toolchain::ToolTypeToName(Toolchain::TYPE_STAMP);
235
236 // File input deps.
237 for (const SourceFile* source : input_deps_sources) {
238 out_ << " ";
239 path_output_.WriteFile(out_, *source);
240 }
241
242 // Target input deps. Sort by label so the output is deterministic (otherwise
243 // some of the targets will have gone through std::sets which will have
244 // sorted them by pointer).
237 std::sort( 245 std::sort(
238 sorted_deps.begin(), sorted_deps.end(), 246 input_deps_targets.begin(), input_deps_targets.end(),
239 [](const Target* a, const Target* b) { return a->label() < b->label(); }); 247 [](const Target* a, const Target* b) { return a->label() < b->label(); });
240 248 for (const auto& dep : input_deps_targets) {
241 for (const auto& dep : sorted_deps) {
242 DCHECK(!dep->dependency_output_file().value().empty()); 249 DCHECK(!dep->dependency_output_file().value().empty());
243 out_ << " "; 250 out_ << " ";
244 path_output_.WriteFile(out_, dep->dependency_output_file()); 251 path_output_.WriteFile(out_, dep->dependency_output_file());
245 } 252 }
246 253
247 out_ << "\n"; 254 out_ << "\n";
248 return input_stamp_file; 255 return input_stamp_file;
249 } 256 }
250 257
251 void NinjaTargetWriter::WriteStampForTarget( 258 void NinjaTargetWriter::WriteStampForTarget(
(...skipping 15 matching lines...) Expand all
267 << GetNinjaRulePrefixForToolchain(settings_) 274 << GetNinjaRulePrefixForToolchain(settings_)
268 << Toolchain::ToolTypeToName(Toolchain::TYPE_STAMP); 275 << Toolchain::ToolTypeToName(Toolchain::TYPE_STAMP);
269 path_output_.WriteFiles(out_, files); 276 path_output_.WriteFiles(out_, files);
270 277
271 if (!order_only_deps.empty()) { 278 if (!order_only_deps.empty()) {
272 out_ << " ||"; 279 out_ << " ||";
273 path_output_.WriteFiles(out_, order_only_deps); 280 path_output_.WriteFiles(out_, order_only_deps);
274 } 281 }
275 out_ << std::endl; 282 out_ << std::endl;
276 } 283 }
OLDNEW
« no previous file with comments | « tools/gn/ninja_copy_target_writer_unittest.cc ('k') | tools/gn/ninja_target_writer_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698