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

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

Issue 440333002: Support more configurability in GN toolchains (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: unsigned check Created 6 years, 4 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 | Annotate | Revision Log
« no previous file with comments | « tools/gn/ninja_target_writer.h ('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 <fstream> 7 #include <fstream>
8 #include <sstream> 8 #include <sstream>
9 9
10 #include "base/file_util.h" 10 #include "base/file_util.h"
11 #include "base/strings/string_util.h"
11 #include "tools/gn/err.h" 12 #include "tools/gn/err.h"
13 #include "tools/gn/filesystem_utils.h"
12 #include "tools/gn/ninja_action_target_writer.h" 14 #include "tools/gn/ninja_action_target_writer.h"
13 #include "tools/gn/ninja_binary_target_writer.h" 15 #include "tools/gn/ninja_binary_target_writer.h"
14 #include "tools/gn/ninja_copy_target_writer.h" 16 #include "tools/gn/ninja_copy_target_writer.h"
15 #include "tools/gn/ninja_group_target_writer.h" 17 #include "tools/gn/ninja_group_target_writer.h"
18 #include "tools/gn/ninja_utils.h"
16 #include "tools/gn/scheduler.h" 19 #include "tools/gn/scheduler.h"
17 #include "tools/gn/string_utils.h" 20 #include "tools/gn/string_utils.h"
21 #include "tools/gn/substitution_writer.h"
18 #include "tools/gn/target.h" 22 #include "tools/gn/target.h"
19 #include "tools/gn/trace.h" 23 #include "tools/gn/trace.h"
20 24
21 NinjaTargetWriter::NinjaTargetWriter(const Target* target, 25 NinjaTargetWriter::NinjaTargetWriter(const Target* target,
22 const Toolchain* toolchain,
23 std::ostream& out) 26 std::ostream& out)
24 : settings_(target->settings()), 27 : settings_(target->settings()),
25 target_(target), 28 target_(target),
26 toolchain_(toolchain),
27 out_(out), 29 out_(out),
28 path_output_(settings_->build_settings()->build_dir(), ESCAPE_NINJA), 30 path_output_(settings_->build_settings()->build_dir(), ESCAPE_NINJA) {
29 helper_(settings_->build_settings()) {
30 } 31 }
31 32
32 NinjaTargetWriter::~NinjaTargetWriter() { 33 NinjaTargetWriter::~NinjaTargetWriter() {
33 } 34 }
34 35
35 // static 36 // static
36 void NinjaTargetWriter::RunAndWriteFile(const Target* target, 37 void NinjaTargetWriter::RunAndWriteFile(const Target* target) {
37 const Toolchain* toolchain) {
38 const Settings* settings = target->settings(); 38 const Settings* settings = target->settings();
39 NinjaHelper helper(settings->build_settings());
40 39
41 ScopedTrace trace(TraceItem::TRACE_FILE_WRITE, 40 ScopedTrace trace(TraceItem::TRACE_FILE_WRITE,
42 target->label().GetUserVisibleName(false)); 41 target->label().GetUserVisibleName(false));
43 trace.SetToolchain(settings->toolchain_label()); 42 trace.SetToolchain(settings->toolchain_label());
44 43
45 base::FilePath ninja_file(settings->build_settings()->GetFullPath( 44 base::FilePath ninja_file(settings->build_settings()->GetFullPath(
46 helper.GetNinjaFileForTarget(target).GetSourceFile( 45 GetNinjaFileForTarget(target)));
47 settings->build_settings())));
48 46
49 if (g_scheduler->verbose_logging()) 47 if (g_scheduler->verbose_logging())
50 g_scheduler->Log("Writing", FilePathToUTF8(ninja_file)); 48 g_scheduler->Log("Writing", FilePathToUTF8(ninja_file));
51 49
52 base::CreateDirectory(ninja_file.DirName()); 50 base::CreateDirectory(ninja_file.DirName());
53 51
54 // It's rediculously faster to write to a string and then write that to 52 // It's rediculously faster to write to a string and then write that to
55 // disk in one operation than to use an fstream here. 53 // disk in one operation than to use an fstream here.
56 std::stringstream file; 54 std::stringstream file;
57 55
58 // Call out to the correct sub-type of writer. 56 // Call out to the correct sub-type of writer.
59 if (target->output_type() == Target::COPY_FILES) { 57 if (target->output_type() == Target::COPY_FILES) {
60 NinjaCopyTargetWriter writer(target, toolchain, file); 58 NinjaCopyTargetWriter writer(target, file);
61 writer.Run(); 59 writer.Run();
62 } else if (target->output_type() == Target::ACTION || 60 } else if (target->output_type() == Target::ACTION ||
63 target->output_type() == Target::ACTION_FOREACH) { 61 target->output_type() == Target::ACTION_FOREACH) {
64 NinjaActionTargetWriter writer(target, toolchain, file); 62 NinjaActionTargetWriter writer(target, file);
65 writer.Run(); 63 writer.Run();
66 } else if (target->output_type() == Target::GROUP) { 64 } else if (target->output_type() == Target::GROUP) {
67 NinjaGroupTargetWriter writer(target, toolchain, file); 65 NinjaGroupTargetWriter writer(target, file);
68 writer.Run(); 66 writer.Run();
69 } else if (target->output_type() == Target::EXECUTABLE || 67 } else if (target->output_type() == Target::EXECUTABLE ||
70 target->output_type() == Target::STATIC_LIBRARY || 68 target->output_type() == Target::STATIC_LIBRARY ||
71 target->output_type() == Target::SHARED_LIBRARY || 69 target->output_type() == Target::SHARED_LIBRARY ||
72 target->output_type() == Target::SOURCE_SET) { 70 target->output_type() == Target::SOURCE_SET) {
73 NinjaBinaryTargetWriter writer(target, toolchain, file); 71 NinjaBinaryTargetWriter writer(target, file);
74 writer.Run(); 72 writer.Run();
75 } else { 73 } else {
76 CHECK(0); 74 CHECK(0);
77 } 75 }
78 76
79 std::string contents = file.str(); 77 std::string contents = file.str();
80 base::WriteFile(ninja_file, contents.c_str(), 78 base::WriteFile(ninja_file, contents.c_str(),
81 static_cast<int>(contents.size())); 79 static_cast<int>(contents.size()));
82 } 80 }
83 81
82 void NinjaTargetWriter::WriteSharedVars(const SubstitutionBits& bits) {
83 bool written_anything = false;
84
85 // Target label.
86 if (bits.used[SUBSTITUTION_LABEL]) {
87 out_ << kSubstitutionNinjaNames[SUBSTITUTION_LABEL] << " = "
88 << SubstitutionWriter::GetTargetSubstitution(
89 target_, SUBSTITUTION_LABEL)
90 << std::endl;
91 written_anything = true;
92 }
93
94 // Root gen dir.
95 if (bits.used[SUBSTITUTION_ROOT_GEN_DIR]) {
96 out_ << kSubstitutionNinjaNames[SUBSTITUTION_ROOT_GEN_DIR] << " = "
97 << SubstitutionWriter::GetTargetSubstitution(
98 target_, SUBSTITUTION_ROOT_GEN_DIR)
99 << std::endl;
100 written_anything = true;
101 }
102
103 // Root out dir.
104 if (bits.used[SUBSTITUTION_ROOT_OUT_DIR]) {
105 out_ << kSubstitutionNinjaNames[SUBSTITUTION_ROOT_OUT_DIR] << " = "
106 << SubstitutionWriter::GetTargetSubstitution(
107 target_, SUBSTITUTION_ROOT_OUT_DIR)
108 << std::endl;
109 written_anything = true;
110 }
111
112 // Target gen dir.
113 if (bits.used[SUBSTITUTION_TARGET_GEN_DIR]) {
114 out_ << kSubstitutionNinjaNames[SUBSTITUTION_TARGET_GEN_DIR] << " = "
115 << SubstitutionWriter::GetTargetSubstitution(
116 target_, SUBSTITUTION_TARGET_GEN_DIR)
117 << std::endl;
118 written_anything = true;
119 }
120
121 // Target out dir.
122 if (bits.used[SUBSTITUTION_TARGET_OUT_DIR]) {
123 out_ << kSubstitutionNinjaNames[SUBSTITUTION_TARGET_OUT_DIR] << " = "
124 << SubstitutionWriter::GetTargetSubstitution(
125 target_, SUBSTITUTION_TARGET_OUT_DIR)
126 << std::endl;
127 written_anything = true;
128 }
129
130 // Target output name.
131 if (bits.used[SUBSTITUTION_TARGET_OUTPUT_NAME]) {
132 out_ << kSubstitutionNinjaNames[SUBSTITUTION_TARGET_OUTPUT_NAME] << " = "
133 << SubstitutionWriter::GetTargetSubstitution(
134 target_, SUBSTITUTION_TARGET_OUTPUT_NAME)
135 << std::endl;
136 written_anything = true;
137 }
138
139 // If we wrote any vars, separate them from the rest of the file that follows
140 // with a blank line.
141 if (written_anything)
142 out_ << std::endl;
143 }
144
84 std::string NinjaTargetWriter::WriteInputDepsStampAndGetDep( 145 std::string NinjaTargetWriter::WriteInputDepsStampAndGetDep(
85 const std::vector<const Target*>& extra_hard_deps) const { 146 const std::vector<const Target*>& extra_hard_deps) const {
147 CHECK(target_->toolchain())
148 << "Toolchain not set on target "
149 << target_->label().GetUserVisibleName(true);
150
86 // For an action (where we run a script only once) the sources are the same 151 // For an action (where we run a script only once) the sources are the same
87 // as the source prereqs. 152 // as the source prereqs.
88 bool list_sources_as_input_deps = (target_->output_type() == Target::ACTION); 153 bool list_sources_as_input_deps = (target_->output_type() == Target::ACTION);
89 154
90 // Actions get implicit dependencies on the script itself. 155 // Actions get implicit dependencies on the script itself.
91 bool add_script_source_as_dep = 156 bool add_script_source_as_dep =
92 (target_->output_type() == Target::ACTION) || 157 (target_->output_type() == Target::ACTION) ||
93 (target_->output_type() == Target::ACTION_FOREACH); 158 (target_->output_type() == Target::ACTION_FOREACH);
94 159
95 if (!add_script_source_as_dep && 160 if (!add_script_source_as_dep &&
96 extra_hard_deps.empty() && 161 extra_hard_deps.empty() &&
97 target_->inputs().empty() && 162 target_->inputs().empty() &&
98 target_->recursive_hard_deps().empty() && 163 target_->recursive_hard_deps().empty() &&
99 (!list_sources_as_input_deps || target_->sources().empty()) && 164 (!list_sources_as_input_deps || target_->sources().empty()) &&
100 toolchain_->deps().empty()) 165 target_->toolchain()->deps().empty())
101 return std::string(); // No input/hard deps. 166 return std::string(); // No input/hard deps.
102 167
103 // One potential optimization is if there are few input dependencies (or 168 // One potential optimization is if there are few input dependencies (or
104 // potentially few sources that depend on these) it's better to just write 169 // potentially few sources that depend on these) it's better to just write
105 // all hard deps on each sources line than have this intermediate stamp. We 170 // all hard deps on each sources line than have this intermediate stamp. We
106 // do the stamp file because duplicating all the order-only deps for each 171 // do the stamp file because duplicating all the order-only deps for each
107 // source file can really explode the ninja file but this won't be the most 172 // source file can really explode the ninja file but this won't be the most
108 // optimal thing in all cases. 173 // optimal thing in all cases.
109 174
110 OutputFile input_stamp_file = helper_.GetTargetOutputDir(target_); 175 OutputFile input_stamp_file(
176 RebaseSourceAbsolutePath(GetTargetOutputDir(target_).value(),
177 settings_->build_settings()->build_dir()));
111 input_stamp_file.value().append(target_->label().name()); 178 input_stamp_file.value().append(target_->label().name());
112 input_stamp_file.value().append(".inputdeps.stamp"); 179 input_stamp_file.value().append(".inputdeps.stamp");
113 180
114 std::ostringstream stamp_file_stream; 181 std::ostringstream stamp_file_stream;
115 path_output_.WriteFile(stamp_file_stream, input_stamp_file); 182 path_output_.WriteFile(stamp_file_stream, input_stamp_file);
116 std::string stamp_file_string = stamp_file_stream.str(); 183 std::string stamp_file_string = stamp_file_stream.str();
117 184
118 out_ << "build " << stamp_file_string << ": " + 185 out_ << "build " << stamp_file_string << ": "
119 helper_.GetRulePrefix(settings_) + "stamp"; 186 << GetNinjaRulePrefixForToolchain(settings_)
187 << Toolchain::ToolTypeToName(Toolchain::TYPE_STAMP);
120 188
121 // Script file (if applicable). 189 // Script file (if applicable).
122 if (add_script_source_as_dep) { 190 if (add_script_source_as_dep) {
123 out_ << " "; 191 out_ << " ";
124 path_output_.WriteFile(out_, target_->action_values().script()); 192 path_output_.WriteFile(out_, target_->action_values().script());
125 } 193 }
126 194
127 // Input files are order-only deps. 195 // Input files are order-only deps.
128 const Target::FileList& prereqs = target_->inputs(); 196 const Target::FileList& prereqs = target_->inputs();
129 for (size_t i = 0; i < prereqs.size(); i++) { 197 for (size_t i = 0; i < prereqs.size(); i++) {
130 out_ << " "; 198 out_ << " ";
131 path_output_.WriteFile(out_, prereqs[i]); 199 path_output_.WriteFile(out_, prereqs[i]);
132 } 200 }
133 if (list_sources_as_input_deps) { 201 if (list_sources_as_input_deps) {
134 const Target::FileList& sources = target_->sources(); 202 const Target::FileList& sources = target_->sources();
135 for (size_t i = 0; i < sources.size(); i++) { 203 for (size_t i = 0; i < sources.size(); i++) {
136 out_ << " "; 204 out_ << " ";
137 path_output_.WriteFile(out_, sources[i]); 205 path_output_.WriteFile(out_, sources[i]);
138 } 206 }
139 } 207 }
140 208
141 // Add on any hard deps that are direct or indirect dependencies. 209 // The different souces of input deps may duplicate some targets, so uniquify
210 // them (ordering doesn't matter for this case).
211 std::set<const Target*> unique_deps;
212
213 // Hard dependencies that are direct or indirect dependencies.
142 const std::set<const Target*>& hard_deps = target_->recursive_hard_deps(); 214 const std::set<const Target*>& hard_deps = target_->recursive_hard_deps();
143 for (std::set<const Target*>::const_iterator i = hard_deps.begin(); 215 for (std::set<const Target*>::const_iterator i = hard_deps.begin();
144 i != hard_deps.end(); ++i) { 216 i != hard_deps.end(); ++i) {
145 out_ << " "; 217 unique_deps.insert(*i);
146 path_output_.WriteFile(out_, helper_.GetTargetOutputFile(*i));
147 } 218 }
148 219
220 // Extra hard dependencies passed in.
221 unique_deps.insert(extra_hard_deps.begin(), extra_hard_deps.end());
222
149 // Toolchain dependencies. These must be resolved before doing anything. 223 // Toolchain dependencies. These must be resolved before doing anything.
150 // This just writs all toolchain deps for simplicity. If we find that 224 // This just writs all toolchain deps for simplicity. If we find that
151 // toolchains often have more than one dependency, we could consider writing 225 // toolchains often have more than one dependency, we could consider writing
152 // a toolchain-specific stamp file and only include the stamp here. 226 // a toolchain-specific stamp file and only include the stamp here.
153 const LabelTargetVector& toolchain_deps = toolchain_->deps(); 227 const LabelTargetVector& toolchain_deps = target_->toolchain()->deps();
154 for (size_t i = 0; i < toolchain_deps.size(); i++) { 228 for (size_t i = 0; i < toolchain_deps.size(); i++)
229 unique_deps.insert(toolchain_deps[i].ptr);
230
231 for (std::set<const Target*>::const_iterator i = unique_deps.begin();
232 i != unique_deps.end(); ++i) {
233 DCHECK(!(*i)->dependency_output_file().value().empty());
155 out_ << " "; 234 out_ << " ";
156 path_output_.WriteFile(out_, 235 path_output_.WriteFile(out_, (*i)->dependency_output_file());
157 helper_.GetTargetOutputFile(toolchain_deps[i].ptr));
158 }
159
160 // Extra hard deps passed in.
161 for (size_t i = 0; i < extra_hard_deps.size(); i++) {
162 out_ << " ";
163 path_output_.WriteFile(out_,
164 helper_.GetTargetOutputFile(extra_hard_deps[i]));
165 } 236 }
166 237
167 out_ << "\n"; 238 out_ << "\n";
168 return " | " + stamp_file_string; 239 return " | " + stamp_file_string;
169 } 240 }
241
242 void NinjaTargetWriter::WriteStampForTarget(
243 const std::vector<OutputFile>& files,
244 const std::vector<OutputFile>& order_only_deps) {
245 const OutputFile& stamp_file = target_->dependency_output_file();
246
247 // First validate that the target's dependency is a stamp file. Otherwise,
248 // we shouldn't have gotten here!
249 CHECK(EndsWith(stamp_file.value(), ".stamp", false))
250 << "Output should end in \".stamp\" for stamp file output. Instead got: "
251 << "\"" << stamp_file.value() << "\"";
252
253 out_ << "build ";
254 path_output_.WriteFile(out_, stamp_file);
255
256 out_ << ": "
257 << GetNinjaRulePrefixForToolchain(settings_)
258 << Toolchain::ToolTypeToName(Toolchain::TYPE_STAMP);
259 path_output_.WriteFiles(out_, files);
260
261 if (!order_only_deps.empty()) {
262 out_ << " ||";
263 path_output_.WriteFiles(out_, order_only_deps);
264 }
265 out_ << std::endl;
266 }
OLDNEW
« no previous file with comments | « tools/gn/ninja_target_writer.h ('k') | tools/gn/ninja_target_writer_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698