| 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()) +
|
|
|