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_binary_target_writer.h" | 5 #include "tools/gn/ninja_binary_target_writer.h" |
6 | 6 |
7 #include <set> | 7 #include <set> |
8 #include <sstream> | 8 #include <sstream> |
9 | 9 |
10 #include "base/strings/string_util.h" | 10 #include "base/strings/string_util.h" |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
73 tool_(target->toolchain()->GetToolForTargetFinalOutput(target)) { | 73 tool_(target->toolchain()->GetToolForTargetFinalOutput(target)) { |
74 } | 74 } |
75 | 75 |
76 NinjaBinaryTargetWriter::~NinjaBinaryTargetWriter() { | 76 NinjaBinaryTargetWriter::~NinjaBinaryTargetWriter() { |
77 } | 77 } |
78 | 78 |
79 void NinjaBinaryTargetWriter::Run() { | 79 void NinjaBinaryTargetWriter::Run() { |
80 WriteCompilerVars(); | 80 WriteCompilerVars(); |
81 | 81 |
82 std::vector<OutputFile> obj_files; | 82 std::vector<OutputFile> obj_files; |
83 WriteSources(&obj_files); | 83 std::vector<SourceFile> other_files; |
| 84 WriteSources(&obj_files, &other_files); |
84 | 85 |
85 if (target_->output_type() == Target::SOURCE_SET) | 86 if (target_->output_type() == Target::SOURCE_SET) |
86 WriteSourceSetStamp(obj_files); | 87 WriteSourceSetStamp(obj_files); |
87 else | 88 else |
88 WriteLinkerStuff(obj_files); | 89 WriteLinkerStuff(obj_files, other_files); |
89 } | 90 } |
90 | 91 |
91 void NinjaBinaryTargetWriter::WriteCompilerVars() { | 92 void NinjaBinaryTargetWriter::WriteCompilerVars() { |
92 const SubstitutionBits& subst = target_->toolchain()->substitution_bits(); | 93 const SubstitutionBits& subst = target_->toolchain()->substitution_bits(); |
93 | 94 |
94 // Defines. | 95 // Defines. |
95 if (subst.used[SUBSTITUTION_DEFINES]) { | 96 if (subst.used[SUBSTITUTION_DEFINES]) { |
96 out_ << kSubstitutionNinjaNames[SUBSTITUTION_DEFINES] << " ="; | 97 out_ << kSubstitutionNinjaNames[SUBSTITUTION_DEFINES] << " ="; |
97 RecursiveTargetConfigToStream<std::string>( | 98 RecursiveTargetConfigToStream<std::string>( |
98 target_, &ConfigValues::defines, DefineWriter(), out_); | 99 target_, &ConfigValues::defines, DefineWriter(), out_); |
(...skipping 28 matching lines...) Expand all Loading... |
127 WRITE_FLAGS(cflags_cc, SUBSTITUTION_CFLAGS_CC) | 128 WRITE_FLAGS(cflags_cc, SUBSTITUTION_CFLAGS_CC) |
128 WRITE_FLAGS(cflags_objc, SUBSTITUTION_CFLAGS_OBJC) | 129 WRITE_FLAGS(cflags_objc, SUBSTITUTION_CFLAGS_OBJC) |
129 WRITE_FLAGS(cflags_objcc, SUBSTITUTION_CFLAGS_OBJCC) | 130 WRITE_FLAGS(cflags_objcc, SUBSTITUTION_CFLAGS_OBJCC) |
130 | 131 |
131 #undef WRITE_FLAGS | 132 #undef WRITE_FLAGS |
132 | 133 |
133 WriteSharedVars(subst); | 134 WriteSharedVars(subst); |
134 } | 135 } |
135 | 136 |
136 void NinjaBinaryTargetWriter::WriteSources( | 137 void NinjaBinaryTargetWriter::WriteSources( |
137 std::vector<OutputFile>* object_files) { | 138 std::vector<OutputFile>* object_files, |
| 139 std::vector<SourceFile>* other_files) { |
138 object_files->reserve(target_->sources().size()); | 140 object_files->reserve(target_->sources().size()); |
139 | 141 |
140 OutputFile input_dep = | 142 OutputFile input_dep = |
141 WriteInputDepsStampAndGetDep(std::vector<const Target*>()); | 143 WriteInputDepsStampAndGetDep(std::vector<const Target*>()); |
142 | 144 |
143 std::string rule_prefix = GetNinjaRulePrefixForToolchain(settings_); | 145 std::string rule_prefix = GetNinjaRulePrefixForToolchain(settings_); |
144 | 146 |
145 std::vector<OutputFile> tool_outputs; // Prevent reallocation in loop. | 147 std::vector<OutputFile> tool_outputs; // Prevent reallocation in loop. |
146 for (const auto& source : target_->sources()) { | 148 for (const auto& source : target_->sources()) { |
147 Toolchain::ToolType tool_type = Toolchain::TYPE_NONE; | 149 Toolchain::ToolType tool_type = Toolchain::TYPE_NONE; |
148 if (!GetOutputFilesForSource(target_, source, | 150 if (!GetOutputFilesForSource(target_, source, &tool_type, &tool_outputs)) { |
149 &tool_type, &tool_outputs)) | 151 if (GetSourceFileType(source) == SOURCE_DEF) |
| 152 other_files->push_back(source); |
150 continue; // No output for this source. | 153 continue; // No output for this source. |
| 154 } |
151 | 155 |
152 if (tool_type != Toolchain::TYPE_NONE) { | 156 if (tool_type != Toolchain::TYPE_NONE) { |
153 out_ << "build"; | 157 out_ << "build"; |
154 path_output_.WriteFiles(out_, tool_outputs); | 158 path_output_.WriteFiles(out_, tool_outputs); |
155 | 159 |
156 out_ << ": " << rule_prefix << Toolchain::ToolTypeToName(tool_type); | 160 out_ << ": " << rule_prefix << Toolchain::ToolTypeToName(tool_type); |
157 out_ << " "; | 161 out_ << " "; |
158 path_output_.WriteFile(out_, source); | 162 path_output_.WriteFile(out_, source); |
159 if (!input_dep.value().empty()) { | 163 if (!input_dep.value().empty()) { |
160 // Write out the input dependencies as an order-only dependency. This | 164 // Write out the input dependencies as an order-only dependency. This |
(...skipping 27 matching lines...) Expand all Loading... |
188 } | 192 } |
189 | 193 |
190 // It's theoretically possible for a compiler to produce more than one | 194 // It's theoretically possible for a compiler to produce more than one |
191 // output, but we'll only link to the first output. | 195 // output, but we'll only link to the first output. |
192 object_files->push_back(tool_outputs[0]); | 196 object_files->push_back(tool_outputs[0]); |
193 } | 197 } |
194 out_ << std::endl; | 198 out_ << std::endl; |
195 } | 199 } |
196 | 200 |
197 void NinjaBinaryTargetWriter::WriteLinkerStuff( | 201 void NinjaBinaryTargetWriter::WriteLinkerStuff( |
198 const std::vector<OutputFile>& object_files) { | 202 const std::vector<OutputFile>& object_files, |
| 203 const std::vector<SourceFile>& other_files) { |
199 std::vector<OutputFile> output_files; | 204 std::vector<OutputFile> output_files; |
200 SubstitutionWriter::ApplyListToLinkerAsOutputFile( | 205 SubstitutionWriter::ApplyListToLinkerAsOutputFile( |
201 target_, tool_, tool_->outputs(), &output_files); | 206 target_, tool_, tool_->outputs(), &output_files); |
202 | 207 |
203 out_ << "build"; | 208 out_ << "build"; |
204 path_output_.WriteFiles(out_, output_files); | 209 path_output_.WriteFiles(out_, output_files); |
205 | 210 |
206 out_ << ": " | 211 out_ << ": " |
207 << GetNinjaRulePrefixForToolchain(settings_) | 212 << GetNinjaRulePrefixForToolchain(settings_) |
208 << Toolchain::ToolTypeToName( | 213 << Toolchain::ToolTypeToName( |
(...skipping 29 matching lines...) Expand all Loading... |
238 // later. | 243 // later. |
239 implicit_deps.push_back(cur->dependency_output_file()); | 244 implicit_deps.push_back(cur->dependency_output_file()); |
240 solibs.push_back(cur->link_output_file()); | 245 solibs.push_back(cur->link_output_file()); |
241 } else { | 246 } else { |
242 // Normal case, just link to this target. | 247 // Normal case, just link to this target. |
243 out_ << " "; | 248 out_ << " "; |
244 path_output_.WriteFile(out_, cur->link_output_file()); | 249 path_output_.WriteFile(out_, cur->link_output_file()); |
245 } | 250 } |
246 } | 251 } |
247 | 252 |
| 253 const SourceFile* optional_def_file = nullptr; |
| 254 if (!other_files.empty()) { |
| 255 for (const SourceFile& src_file : other_files) { |
| 256 if (GetSourceFileType(src_file) == SOURCE_DEF) { |
| 257 optional_def_file = &src_file; |
| 258 implicit_deps.push_back( |
| 259 OutputFile(settings_->build_settings(), src_file)); |
| 260 break; // Only one def file is allowed. |
| 261 } |
| 262 } |
| 263 } |
| 264 |
248 // Append implicit dependencies collected above. | 265 // Append implicit dependencies collected above. |
249 if (!implicit_deps.empty()) { | 266 if (!implicit_deps.empty()) { |
250 out_ << " |"; | 267 out_ << " |"; |
251 path_output_.WriteFiles(out_, implicit_deps); | 268 path_output_.WriteFiles(out_, implicit_deps); |
252 } | 269 } |
253 | 270 |
254 // Append data dependencies as order-only dependencies. | 271 // Append data dependencies as order-only dependencies. |
255 // | 272 // |
256 // This will include data dependencies and input dependencies (like when | 273 // This will include data dependencies and input dependencies (like when |
257 // this target depends on an action). Having the data dependencies in this | 274 // this target depends on an action). Having the data dependencies in this |
258 // list ensures that the data is available at runtime when the user builds | 275 // list ensures that the data is available at runtime when the user builds |
259 // this target. | 276 // this target. |
260 // | 277 // |
261 // The action dependencies are not strictly necessary in this case. They | 278 // The action dependencies are not strictly necessary in this case. They |
262 // should also have been collected via the input deps stamp that each source | 279 // should also have been collected via the input deps stamp that each source |
263 // file has for an order-only dependency, and since this target depends on | 280 // file has for an order-only dependency, and since this target depends on |
264 // the sources, there is already an implicit order-only dependency. However, | 281 // the sources, there is already an implicit order-only dependency. However, |
265 // it's extra work to separate these out and there's no disadvantage to | 282 // it's extra work to separate these out and there's no disadvantage to |
266 // listing them again. | 283 // listing them again. |
267 WriteOrderOnlyDependencies(non_linkable_deps); | 284 WriteOrderOnlyDependencies(non_linkable_deps); |
268 | 285 |
269 // End of the link "build" line. | 286 // End of the link "build" line. |
270 out_ << std::endl; | 287 out_ << std::endl; |
271 | 288 |
272 // These go in the inner scope of the link line. | 289 // These go in the inner scope of the link line. |
273 WriteLinkerFlags(); | 290 WriteLinkerFlags(optional_def_file); |
| 291 |
274 WriteLibs(); | 292 WriteLibs(); |
275 WriteOutputExtension(); | 293 WriteOutputExtension(); |
276 WriteSolibs(solibs); | 294 WriteSolibs(solibs); |
277 } | 295 } |
278 | 296 |
279 void NinjaBinaryTargetWriter::WriteLinkerFlags() { | 297 void NinjaBinaryTargetWriter::WriteLinkerFlags( |
| 298 const SourceFile* optional_def_file) { |
280 out_ << " ldflags ="; | 299 out_ << " ldflags ="; |
281 | 300 |
282 // First the ldflags from the target and its config. | 301 // First the ldflags from the target and its config. |
283 EscapeOptions flag_options = GetFlagOptions(); | 302 EscapeOptions flag_options = GetFlagOptions(); |
284 RecursiveTargetConfigStringsToStream(target_, &ConfigValues::ldflags, | 303 RecursiveTargetConfigStringsToStream(target_, &ConfigValues::ldflags, |
285 flag_options, out_); | 304 flag_options, out_); |
286 | 305 |
287 // Followed by library search paths that have been recursively pushed | 306 // Followed by library search paths that have been recursively pushed |
288 // through the dependency tree. | 307 // through the dependency tree. |
289 const OrderedSet<SourceDir> all_lib_dirs = target_->all_lib_dirs(); | 308 const OrderedSet<SourceDir> all_lib_dirs = target_->all_lib_dirs(); |
290 if (!all_lib_dirs.empty()) { | 309 if (!all_lib_dirs.empty()) { |
291 // Since we're passing these on the command line to the linker and not | 310 // Since we're passing these on the command line to the linker and not |
292 // to Ninja, we need to do shell escaping. | 311 // to Ninja, we need to do shell escaping. |
293 PathOutput lib_path_output(path_output_.current_dir(), | 312 PathOutput lib_path_output(path_output_.current_dir(), |
294 settings_->build_settings()->root_path_utf8(), | 313 settings_->build_settings()->root_path_utf8(), |
295 ESCAPE_NINJA_COMMAND); | 314 ESCAPE_NINJA_COMMAND); |
296 for (size_t i = 0; i < all_lib_dirs.size(); i++) { | 315 for (size_t i = 0; i < all_lib_dirs.size(); i++) { |
297 out_ << " " << tool_->lib_dir_switch(); | 316 out_ << " " << tool_->lib_dir_switch(); |
298 lib_path_output.WriteDir(out_, all_lib_dirs[i], | 317 lib_path_output.WriteDir(out_, all_lib_dirs[i], |
299 PathOutput::DIR_NO_LAST_SLASH); | 318 PathOutput::DIR_NO_LAST_SLASH); |
300 } | 319 } |
301 } | 320 } |
| 321 |
| 322 if (optional_def_file) { |
| 323 out_ << " /DEF:"; |
| 324 path_output_.WriteFile(out_, *optional_def_file); |
| 325 } |
| 326 |
302 out_ << std::endl; | 327 out_ << std::endl; |
303 } | 328 } |
304 | 329 |
305 void NinjaBinaryTargetWriter::WriteLibs() { | 330 void NinjaBinaryTargetWriter::WriteLibs() { |
306 out_ << " libs ="; | 331 out_ << " libs ="; |
307 | 332 |
308 // Libraries that have been recursively pushed through the dependency tree. | 333 // Libraries that have been recursively pushed through the dependency tree. |
309 EscapeOptions lib_escape_opts; | 334 EscapeOptions lib_escape_opts; |
310 lib_escape_opts.mode = ESCAPE_NINJA_COMMAND; | 335 lib_escape_opts.mode = ESCAPE_NINJA_COMMAND; |
311 const OrderedSet<std::string> all_libs = target_->all_libs(); | 336 const OrderedSet<std::string> all_libs = target_->all_libs(); |
(...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
478 return false; // No tool for this file (it's a header file or something). | 503 return false; // No tool for this file (it's a header file or something). |
479 const Tool* tool = target->toolchain()->GetTool(*computed_tool_type); | 504 const Tool* tool = target->toolchain()->GetTool(*computed_tool_type); |
480 if (!tool) | 505 if (!tool) |
481 return false; // Tool does not apply for this toolchain.file. | 506 return false; // Tool does not apply for this toolchain.file. |
482 | 507 |
483 // Figure out what output(s) this compiler produces. | 508 // Figure out what output(s) this compiler produces. |
484 SubstitutionWriter::ApplyListToCompilerAsOutputFile( | 509 SubstitutionWriter::ApplyListToCompilerAsOutputFile( |
485 target, source, tool->outputs(), outputs); | 510 target, source, tool->outputs(), outputs); |
486 return !outputs->empty(); | 511 return !outputs->empty(); |
487 } | 512 } |
OLD | NEW |