| Index: tools/gn/ninja_target_writer.cc
|
| diff --git a/tools/gn/ninja_target_writer.cc b/tools/gn/ninja_target_writer.cc
|
| index 69e9d9051d2b8070f235dbfdb99415bdc1ecf591..ccb3eb7ec7c715c906d12da8f83bf0cae5f18ce4 100644
|
| --- a/tools/gn/ninja_target_writer.cc
|
| +++ b/tools/gn/ninja_target_writer.cc
|
| @@ -39,50 +39,82 @@ NinjaTargetWriter::~NinjaTargetWriter() {
|
| }
|
|
|
| // static
|
| -void NinjaTargetWriter::RunAndWriteFile(const Target* target) {
|
| +std::string NinjaTargetWriter::RunAndWriteFile(const Target* target) {
|
| const Settings* settings = target->settings();
|
|
|
| ScopedTrace trace(TraceItem::TRACE_FILE_WRITE,
|
| target->label().GetUserVisibleName(false));
|
| trace.SetToolchain(settings->toolchain_label());
|
|
|
| - base::FilePath ninja_file(settings->build_settings()->GetFullPath(
|
| - GetNinjaFileForTarget(target)));
|
| -
|
| if (g_scheduler->verbose_logging())
|
| - g_scheduler->Log("Writing", FilePathToUTF8(ninja_file));
|
| -
|
| - base::CreateDirectory(ninja_file.DirName());
|
| + g_scheduler->Log("Computing", target->label().GetUserVisibleName(true));
|
|
|
| // It's ridiculously faster to write to a string and then write that to
|
| // disk in one operation than to use an fstream here.
|
| - std::stringstream file;
|
| -
|
| - // Call out to the correct sub-type of writer.
|
| + std::stringstream rules;
|
| +
|
| + // Call out to the correct sub-type of writer. Binary targets need to be
|
| + // written to separate files for compiler flag scoping, but other target
|
| + // types can have their rules coalesced.
|
| + //
|
| + // In ninja, if a rule uses a variable (like $include_dirs) it will use
|
| + // the value set by indenting it under the build line or it takes the value
|
| + // from the end of the invoking scope (otherwise the current file). It does
|
| + // not copy the value from what it was when the build line was encountered.
|
| + // To avoid writing lots of duplicate rules for defines and cflags, etc. on
|
| + // each source file build line, we use separate .ninja files with the shared
|
| + // variables set at the top.
|
| + //
|
| + // Groups and actions don't use this type of flag, they make unique rules
|
| + // or write variables scoped under each build line. As a result, they don't
|
| + // need the separate files.
|
| + bool needs_file_write = false;
|
| if (target->output_type() == Target::BUNDLE_DATA) {
|
| - NinjaBundleDataTargetWriter writer(target, file);
|
| + NinjaBundleDataTargetWriter writer(target, rules);
|
| writer.Run();
|
| } else if (target->output_type() == Target::CREATE_BUNDLE) {
|
| - NinjaCreateBundleTargetWriter writer(target, file);
|
| + NinjaCreateBundleTargetWriter writer(target, rules);
|
| writer.Run();
|
| } else if (target->output_type() == Target::COPY_FILES) {
|
| - NinjaCopyTargetWriter writer(target, file);
|
| + NinjaCopyTargetWriter writer(target, rules);
|
| writer.Run();
|
| } else if (target->output_type() == Target::ACTION ||
|
| target->output_type() == Target::ACTION_FOREACH) {
|
| - NinjaActionTargetWriter writer(target, file);
|
| + NinjaActionTargetWriter writer(target, rules);
|
| writer.Run();
|
| } else if (target->output_type() == Target::GROUP) {
|
| - NinjaGroupTargetWriter writer(target, file);
|
| + NinjaGroupTargetWriter writer(target, rules);
|
| writer.Run();
|
| } else if (target->IsBinary()) {
|
| - NinjaBinaryTargetWriter writer(target, file);
|
| + needs_file_write = true;
|
| + NinjaBinaryTargetWriter writer(target, rules);
|
| writer.Run();
|
| } else {
|
| CHECK(0) << "Output type of target not handled.";
|
| }
|
|
|
| - WriteFileIfChanged(ninja_file, file.str(), nullptr);
|
| + if (needs_file_write) {
|
| + // Write the ninja file.
|
| + SourceFile ninja_file = GetNinjaFileForTarget(target);
|
| + base::FilePath full_ninja_file =
|
| + settings->build_settings()->GetFullPath(ninja_file);
|
| + base::CreateDirectory(full_ninja_file.DirName());
|
| + WriteFileIfChanged(full_ninja_file, rules.str(), nullptr);
|
| +
|
| + EscapeOptions options;
|
| + options.mode = ESCAPE_NINJA;
|
| +
|
| + // Return the subninja command to load the rules file.
|
| + std::string result = "subninja ";
|
| + result.append(EscapeString(
|
| + OutputFile(target->settings()->build_settings(), ninja_file).value(),
|
| + options, nullptr));
|
| + result.push_back('\n');
|
| + return result;
|
| + }
|
| +
|
| + // No separate file required, just return the rules.
|
| + return rules.str();
|
| }
|
|
|
| void NinjaTargetWriter::WriteEscapedSubstitution(SubstitutionType type) {
|
|
|