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_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 21 matching lines...) Expand all Loading... |
32 out_(out), | 32 out_(out), |
33 path_output_(settings_->build_settings()->build_dir(), | 33 path_output_(settings_->build_settings()->build_dir(), |
34 settings_->build_settings()->root_path_utf8(), | 34 settings_->build_settings()->root_path_utf8(), |
35 ESCAPE_NINJA) { | 35 ESCAPE_NINJA) { |
36 } | 36 } |
37 | 37 |
38 NinjaTargetWriter::~NinjaTargetWriter() { | 38 NinjaTargetWriter::~NinjaTargetWriter() { |
39 } | 39 } |
40 | 40 |
41 // static | 41 // static |
42 void NinjaTargetWriter::RunAndWriteFile(const Target* target) { | 42 std::string NinjaTargetWriter::RunAndWriteFile(const Target* target) { |
43 const Settings* settings = target->settings(); | 43 const Settings* settings = target->settings(); |
44 | 44 |
45 ScopedTrace trace(TraceItem::TRACE_FILE_WRITE, | 45 ScopedTrace trace(TraceItem::TRACE_FILE_WRITE, |
46 target->label().GetUserVisibleName(false)); | 46 target->label().GetUserVisibleName(false)); |
47 trace.SetToolchain(settings->toolchain_label()); | 47 trace.SetToolchain(settings->toolchain_label()); |
48 | 48 |
49 base::FilePath ninja_file(settings->build_settings()->GetFullPath( | |
50 GetNinjaFileForTarget(target))); | |
51 | |
52 if (g_scheduler->verbose_logging()) | 49 if (g_scheduler->verbose_logging()) |
53 g_scheduler->Log("Writing", FilePathToUTF8(ninja_file)); | 50 g_scheduler->Log("Computing", target->label().GetUserVisibleName(true)); |
54 | |
55 base::CreateDirectory(ninja_file.DirName()); | |
56 | 51 |
57 // It's ridiculously faster to write to a string and then write that to | 52 // It's ridiculously faster to write to a string and then write that to |
58 // disk in one operation than to use an fstream here. | 53 // disk in one operation than to use an fstream here. |
59 std::stringstream file; | 54 std::stringstream rules; |
60 | 55 |
61 // Call out to the correct sub-type of writer. | 56 // Call out to the correct sub-type of writer. Binary targets need to be |
| 57 // written to separate files for compiler flag scoping, but other target |
| 58 // types can have their rules coalesced. |
| 59 // |
| 60 // In ninja, if a rule uses a variable (like $include_dirs) it will use |
| 61 // the value set by indenting it under the build line or it takes the value |
| 62 // from the end of the invoking scope (otherwise the current file). It does |
| 63 // not copy the value from what it was when the build line was encountered. |
| 64 // To avoid writing lots of duplicate rules for defines and cflags, etc. on |
| 65 // each source file build line, we use separate .ninja files with the shared |
| 66 // variables set at the top. |
| 67 // |
| 68 // Groups and actions don't use this type of flag, they make unique rules |
| 69 // or write variables scoped under each build line. As a result, they don't |
| 70 // need the separate files. |
| 71 bool needs_file_write = false; |
62 if (target->output_type() == Target::BUNDLE_DATA) { | 72 if (target->output_type() == Target::BUNDLE_DATA) { |
63 NinjaBundleDataTargetWriter writer(target, file); | 73 NinjaBundleDataTargetWriter writer(target, rules); |
64 writer.Run(); | 74 writer.Run(); |
65 } else if (target->output_type() == Target::CREATE_BUNDLE) { | 75 } else if (target->output_type() == Target::CREATE_BUNDLE) { |
66 NinjaCreateBundleTargetWriter writer(target, file); | 76 NinjaCreateBundleTargetWriter writer(target, rules); |
67 writer.Run(); | 77 writer.Run(); |
68 } else if (target->output_type() == Target::COPY_FILES) { | 78 } else if (target->output_type() == Target::COPY_FILES) { |
69 NinjaCopyTargetWriter writer(target, file); | 79 NinjaCopyTargetWriter writer(target, rules); |
70 writer.Run(); | 80 writer.Run(); |
71 } else if (target->output_type() == Target::ACTION || | 81 } else if (target->output_type() == Target::ACTION || |
72 target->output_type() == Target::ACTION_FOREACH) { | 82 target->output_type() == Target::ACTION_FOREACH) { |
73 NinjaActionTargetWriter writer(target, file); | 83 NinjaActionTargetWriter writer(target, rules); |
74 writer.Run(); | 84 writer.Run(); |
75 } else if (target->output_type() == Target::GROUP) { | 85 } else if (target->output_type() == Target::GROUP) { |
76 NinjaGroupTargetWriter writer(target, file); | 86 NinjaGroupTargetWriter writer(target, rules); |
77 writer.Run(); | 87 writer.Run(); |
78 } else if (target->IsBinary()) { | 88 } else if (target->IsBinary()) { |
79 NinjaBinaryTargetWriter writer(target, file); | 89 needs_file_write = true; |
| 90 NinjaBinaryTargetWriter writer(target, rules); |
80 writer.Run(); | 91 writer.Run(); |
81 } else { | 92 } else { |
82 CHECK(0) << "Output type of target not handled."; | 93 CHECK(0) << "Output type of target not handled."; |
83 } | 94 } |
84 | 95 |
85 WriteFileIfChanged(ninja_file, file.str(), nullptr); | 96 if (needs_file_write) { |
| 97 // Write the ninja file. |
| 98 SourceFile ninja_file = GetNinjaFileForTarget(target); |
| 99 base::FilePath full_ninja_file = |
| 100 settings->build_settings()->GetFullPath(ninja_file); |
| 101 base::CreateDirectory(full_ninja_file.DirName()); |
| 102 WriteFileIfChanged(full_ninja_file, rules.str(), nullptr); |
| 103 |
| 104 EscapeOptions options; |
| 105 options.mode = ESCAPE_NINJA; |
| 106 |
| 107 // Return the subninja command to load the rules file. |
| 108 std::string result = "subninja "; |
| 109 result.append(EscapeString( |
| 110 OutputFile(target->settings()->build_settings(), ninja_file).value(), |
| 111 options, nullptr)); |
| 112 result.push_back('\n'); |
| 113 return result; |
| 114 } |
| 115 |
| 116 // No separate file required, just return the rules. |
| 117 return rules.str(); |
86 } | 118 } |
87 | 119 |
88 void NinjaTargetWriter::WriteEscapedSubstitution(SubstitutionType type) { | 120 void NinjaTargetWriter::WriteEscapedSubstitution(SubstitutionType type) { |
89 EscapeOptions opts; | 121 EscapeOptions opts; |
90 opts.mode = ESCAPE_NINJA; | 122 opts.mode = ESCAPE_NINJA; |
91 | 123 |
92 out_ << kSubstitutionNinjaNames[type] << " = "; | 124 out_ << kSubstitutionNinjaNames[type] << " = "; |
93 EscapeStringToStream(out_, | 125 EscapeStringToStream(out_, |
94 SubstitutionWriter::GetTargetSubstitution(target_, type), | 126 SubstitutionWriter::GetTargetSubstitution(target_, type), |
95 opts); | 127 opts); |
(...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
284 << GetNinjaRulePrefixForToolchain(settings_) | 316 << GetNinjaRulePrefixForToolchain(settings_) |
285 << Toolchain::ToolTypeToName(Toolchain::TYPE_STAMP); | 317 << Toolchain::ToolTypeToName(Toolchain::TYPE_STAMP); |
286 path_output_.WriteFiles(out_, files); | 318 path_output_.WriteFiles(out_, files); |
287 | 319 |
288 if (!order_only_deps.empty()) { | 320 if (!order_only_deps.empty()) { |
289 out_ << " ||"; | 321 out_ << " ||"; |
290 path_output_.WriteFiles(out_, order_only_deps); | 322 path_output_.WriteFiles(out_, order_only_deps); |
291 } | 323 } |
292 out_ << std::endl; | 324 out_ << std::endl; |
293 } | 325 } |
OLD | NEW |