Index: tools/gn/command_gen.cc |
diff --git a/tools/gn/command_gen.cc b/tools/gn/command_gen.cc |
index 06b99ca1124d6a63fb92907b190fbe3874dca054..7de9aedeeec7be261149e5d4e310f6353abd02d3 100644 |
--- a/tools/gn/command_gen.cc |
+++ b/tools/gn/command_gen.cc |
@@ -46,32 +46,44 @@ const char kSwitchJsonFileName[] = "json-file-name"; |
const char kSwitchJsonIdeScript[] = "json-ide-script"; |
const char kSwitchJsonIdeScriptArgs[] = "json-ide-script-args"; |
+// Collects Ninja rules for each toolchain. The lock protectes the rules. |
+struct TargetWriteInfo { |
+ base::Lock lock; |
+ NinjaWriter::PerToolchainRules rules; |
+}; |
+ |
// Called on worker thread to write the ninja file. |
-void BackgroundDoWrite(const Target* target) { |
- NinjaTargetWriter::RunAndWriteFile(target); |
+void BackgroundDoWrite(TargetWriteInfo* write_info, const Target* target) { |
+ std::string rule = NinjaTargetWriter::RunAndWriteFile(target); |
+ DCHECK(!rule.empty()); |
+ |
+ { |
+ base::AutoLock lock(write_info->lock); |
+ write_info->rules[target->toolchain()].emplace_back( |
+ target, std::move(rule)); |
+ } |
+ |
g_scheduler->DecrementWorkCount(); |
} |
// Called on the main thread. |
-void ItemResolvedCallback(base::subtle::Atomic32* write_counter, |
- scoped_refptr<Builder> builder, |
+void ItemResolvedCallback(TargetWriteInfo* write_info, |
const BuilderRecord* record) { |
- base::subtle::NoBarrier_AtomicIncrement(write_counter, 1); |
- |
const Item* item = record->item(); |
const Target* target = item->AsTarget(); |
if (target) { |
g_scheduler->IncrementWorkCount(); |
- g_scheduler->ScheduleWork(base::Bind(&BackgroundDoWrite, target)); |
+ g_scheduler->ScheduleWork(base::Bind(&BackgroundDoWrite, |
+ write_info, target)); |
} |
} |
// Returns a pointer to the target with the given file as an output, or null |
// if no targets generate the file. This is brute force since this is an |
// error condition and performance shouldn't matter. |
-const Target* FindTargetThatGeneratesFile(const Builder* builder, |
+const Target* FindTargetThatGeneratesFile(const Builder& builder, |
const SourceFile& file) { |
- std::vector<const Target*> targets = builder->GetAllResolvedTargets(); |
+ std::vector<const Target*> targets = builder.GetAllResolvedTargets(); |
if (targets.empty()) |
return nullptr; |
@@ -87,7 +99,7 @@ const Target* FindTargetThatGeneratesFile(const Builder* builder, |
// Prints an error that the given file was present as a source or input in |
// the given target(s) but was not generated by any of its dependencies. |
-void PrintInvalidGeneratedInput(const Builder* builder, |
+void PrintInvalidGeneratedInput(const Builder& builder, |
const SourceFile& file, |
const std::vector<const Target*>& targets) { |
std::string err; |
@@ -167,7 +179,7 @@ bool CheckForInvalidGeneratedInputs(Setup* setup) { |
bool RunIdeWriter(const std::string& ide, |
const BuildSettings* build_settings, |
- Builder* builder, |
+ const Builder& builder, |
Err* err) { |
const base::CommandLine* command_line = |
base::CommandLine::ForCurrentProcess(); |
@@ -373,27 +385,36 @@ int RunGen(const std::vector<std::string>& args) { |
if (command_line->HasSwitch(kSwitchCheck)) |
setup->set_check_public_headers(true); |
- // Cause the load to also generate the ninja files for each target. We wrap |
- // the writing to maintain a counter. |
- base::subtle::Atomic32 write_counter = 0; |
- setup->builder()->set_resolved_callback( |
- base::Bind(&ItemResolvedCallback, &write_counter, |
- scoped_refptr<Builder>(setup->builder()))); |
+ // Cause the load to also generate the ninja files for each target. |
+ TargetWriteInfo write_info; |
+ setup->builder().set_resolved_callback( |
+ base::Bind(&ItemResolvedCallback, &write_info)); |
// Do the actual load. This will also write out the target ninja files. |
if (!setup->Run()) |
return 1; |
+ // Sort the targets in each toolchain according to their label. This makes |
+ // the ninja files have deterministic content. |
+ for (auto& cur_toolchain : write_info.rules) { |
+ std::sort(cur_toolchain.second.begin(), cur_toolchain.second.end(), |
+ [](const NinjaWriter::TargetRulePair& a, |
+ const NinjaWriter::TargetRulePair& b) { |
+ return a.first->label() < b.first->label(); |
+ }); |
+ } |
+ |
Err err; |
// Write the root ninja files. |
if (!NinjaWriter::RunAndWriteFiles(&setup->build_settings(), |
setup->builder(), |
+ write_info.rules, |
&err)) { |
err.PrintToStdout(); |
return 1; |
} |
- if (!WriteRuntimeDepsFilesIfNecessary(*setup->builder(), &err)) { |
+ if (!WriteRuntimeDepsFilesIfNecessary(setup->builder(), &err)) { |
err.PrintToStdout(); |
return 1; |
} |
@@ -413,8 +434,11 @@ int RunGen(const std::vector<std::string>& args) { |
if (!command_line->HasSwitch(switches::kQuiet)) { |
OutputString("Done. ", DECORATION_GREEN); |
- std::string stats = "Wrote " + |
- base::IntToString(static_cast<int>(write_counter)) + |
+ size_t targets_collected = 0; |
+ for (const auto& rules : write_info.rules) |
+ targets_collected += rules.second.size(); |
+ |
+ std::string stats = "Made " + base::SizeTToString(targets_collected) + |
" targets from " + |
base::IntToString( |
setup->scheduler().input_file_manager()->GetInputFileCount()) + |