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

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

Issue 26267003: Add the concept of a source set to GN. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 2 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_binary_target_writer.h ('k') | tools/gn/ninja_binary_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_binary_target_writer.h" 5 #include "tools/gn/ninja_binary_target_writer.h"
6 6
7 #include <set> 7 #include <set>
8 8
9 #include "base/strings/string_util.h" 9 #include "base/strings/string_util.h"
10 #include "tools/gn/config_values_extractors.h" 10 #include "tools/gn/config_values_extractors.h"
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
72 72
73 Toolchain::ToolType GetToolTypeForTarget(const Target* target) { 73 Toolchain::ToolType GetToolTypeForTarget(const Target* target) {
74 switch (target->output_type()) { 74 switch (target->output_type()) {
75 case Target::STATIC_LIBRARY: 75 case Target::STATIC_LIBRARY:
76 return Toolchain::TYPE_ALINK; 76 return Toolchain::TYPE_ALINK;
77 case Target::SHARED_LIBRARY: 77 case Target::SHARED_LIBRARY:
78 return Toolchain::TYPE_SOLINK; 78 return Toolchain::TYPE_SOLINK;
79 case Target::EXECUTABLE: 79 case Target::EXECUTABLE:
80 return Toolchain::TYPE_LINK; 80 return Toolchain::TYPE_LINK;
81 default: 81 default:
82 NOTREACHED();
83 return Toolchain::TYPE_NONE; 82 return Toolchain::TYPE_NONE;
84 } 83 }
85 } 84 }
86 85
87 } // namespace 86 } // namespace
88 87
89 NinjaBinaryTargetWriter::NinjaBinaryTargetWriter(const Target* target, 88 NinjaBinaryTargetWriter::NinjaBinaryTargetWriter(const Target* target,
90 std::ostream& out) 89 std::ostream& out)
91 : NinjaTargetWriter(target, out), 90 : NinjaTargetWriter(target, out),
92 tool_type_(GetToolTypeForTarget(target)){ 91 tool_type_(GetToolTypeForTarget(target)){
93 } 92 }
94 93
95 NinjaBinaryTargetWriter::~NinjaBinaryTargetWriter() { 94 NinjaBinaryTargetWriter::~NinjaBinaryTargetWriter() {
96 } 95 }
97 96
98 void NinjaBinaryTargetWriter::Run() { 97 void NinjaBinaryTargetWriter::Run() {
99 WriteEnvironment(); 98 WriteEnvironment();
100 99
101 WriteCompilerVars(); 100 WriteCompilerVars();
102 101
103 std::vector<OutputFile> obj_files; 102 std::vector<OutputFile> obj_files;
104 WriteSources(&obj_files); 103 WriteSources(&obj_files);
105 104
106 WriteLinkerStuff(obj_files); 105 if (target_->output_type() == Target::SOURCE_SET)
106 WriteSourceSetStamp(obj_files);
107 else
108 WriteLinkerStuff(obj_files);
107 } 109 }
108 110
109 void NinjaBinaryTargetWriter::WriteCompilerVars() { 111 void NinjaBinaryTargetWriter::WriteCompilerVars() {
110 // Defines. 112 // Defines.
111 out_ << "defines ="; 113 out_ << "defines =";
112 RecursiveTargetConfigToStream<std::string>(target_, &ConfigValues::defines, 114 RecursiveTargetConfigToStream<std::string>(target_, &ConfigValues::defines,
113 DefineWriter(), out_); 115 DefineWriter(), out_);
114 out_ << std::endl; 116 out_ << std::endl;
115 117
116 // Include directories. 118 // Include directories.
(...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after
302 out_ << "build "; 304 out_ << "build ";
303 path_output_.WriteFile(out_, internal_output_file); 305 path_output_.WriteFile(out_, internal_output_file);
304 if (external_output_file != internal_output_file) { 306 if (external_output_file != internal_output_file) {
305 out_ << " "; 307 out_ << " ";
306 path_output_.WriteFile(out_, external_output_file); 308 path_output_.WriteFile(out_, external_output_file);
307 } 309 }
308 out_ << ": " 310 out_ << ": "
309 << helper_.GetRulePrefix(GetToolchain()) 311 << helper_.GetRulePrefix(GetToolchain())
310 << Toolchain::ToolTypeToName(tool_type_); 312 << Toolchain::ToolTypeToName(tool_type_);
311 313
314 std::set<OutputFile> extra_object_files;
315 std::vector<const Target*> linkable_deps;
316 std::vector<const Target*> non_linkable_deps;
317 GetDeps(&extra_object_files, &linkable_deps, &non_linkable_deps);
318
312 // Object files. 319 // Object files.
313 for (size_t i = 0; i < object_files.size(); i++) { 320 for (size_t i = 0; i < object_files.size(); i++) {
314 out_ << " "; 321 out_ << " ";
315 path_output_.WriteFile(out_, object_files[i]); 322 path_output_.WriteFile(out_, object_files[i]);
316 } 323 }
324 for (std::set<OutputFile>::iterator i = extra_object_files.begin();
325 i != extra_object_files.end(); ++i) {
326 out_ << " ";
327 path_output_.WriteFile(out_, *i);
328 }
317 329
318 // Library inputs (deps and inherited static libraries). 330 // Libs.
319 // 331 for (size_t i = 0; i < linkable_deps.size(); i++) {
320 // Static libraries since they're just a collection of the object files so 332 out_ << " ";
321 // don't need libraries linked with them, but we still need to go through 333 path_output_.WriteFile(out_, helper_.GetTargetOutputFile(linkable_deps[i]));
322 // the list and find non-linkable data deps in the "deps" section. We'll
323 // collect all non-linkable deps and put it in the implicit deps below.
324 std::vector<const Target*> extra_data_deps;
325 const std::vector<const Target*>& deps = target_->deps();
326 const std::set<const Target*>& inherited = target_->inherited_libraries();
327 for (size_t i = 0; i < deps.size(); i++) {
328 if (inherited.find(deps[i]) != inherited.end())
329 continue;
330 if (target_->output_type() != Target::STATIC_LIBRARY &&
331 deps[i]->IsLinkable()) {
332 out_ << " ";
333 path_output_.WriteFile(out_, helper_.GetTargetOutputFile(deps[i]));
334 } else {
335 extra_data_deps.push_back(deps[i]);
336 }
337 }
338 for (std::set<const Target*>::const_iterator i = inherited.begin();
339 i != inherited.end(); ++i) {
340 if (target_->output_type() == Target::STATIC_LIBRARY) {
341 extra_data_deps.push_back(*i);
342 } else {
343 out_ << " ";
344 path_output_.WriteFile(out_, helper_.GetTargetOutputFile(*i));
345 }
346 } 334 }
347 335
348 // External link deps from GYP. This is indexed by a label with no toolchain. 336 // External link deps from GYP. This is indexed by a label with no toolchain.
349 typedef BuildSettings::AdditionalLibsMap LibsMap; 337 typedef BuildSettings::AdditionalLibsMap LibsMap;
350 const LibsMap& libs = settings_->build_settings()->external_link_deps(); 338 const LibsMap& libs = settings_->build_settings()->external_link_deps();
351 Label libs_key(target_->label().dir(), target_->label().name()); 339 Label libs_key(target_->label().dir(), target_->label().name());
352 LibsMap::const_iterator libs_end = libs.upper_bound(libs_key); 340 LibsMap::const_iterator libs_end = libs.upper_bound(libs_key);
353 for (LibsMap::const_iterator i = libs.lower_bound(libs_key); 341 for (LibsMap::const_iterator i = libs.lower_bound(libs_key);
354 i != libs_end; ++i) { 342 i != libs_end; ++i) {
355 out_ << " "; 343 out_ << " ";
356 path_output_.WriteFile(out_, i->second); 344 path_output_.WriteFile(out_, i->second);
357 } 345 }
358 346
359 // Append data dependencies as implicit dependencies. 347 // Append data dependencies as implicit dependencies.
348 WriteImplicitDependencies(non_linkable_deps);
349
350 out_ << std::endl;
351 }
352
353 void NinjaBinaryTargetWriter::WriteSourceSetStamp(
354 const std::vector<OutputFile>& object_files) {
355 // The stamp rule for source sets is generally not used, since targets that
356 // depend on this will reference the object files directly. However, writing
357 // this rule allows the user to type the name of the target and get a build
358 // which can be convenient for development.
359 out_ << "build ";
360 path_output_.WriteFile(out_, helper_.GetTargetOutputFile(target_));
361 out_ << ": "
362 << helper_.GetRulePrefix(target_->settings()->toolchain())
363 << "stamp";
364
365 std::set<OutputFile> extra_object_files;
366 std::vector<const Target*> linkable_deps;
367 std::vector<const Target*> non_linkable_deps;
368 GetDeps(&extra_object_files, &linkable_deps, &non_linkable_deps);
369
370 // The classifier should never put extra object files in a source set:
371 // any source sets that we depend on should appear in our non-linkable
372 // deps instead.
373 DCHECK(extra_object_files.empty());
374
375 for (size_t i = 0; i < object_files.size(); i++) {
376 out_ << " ";
377 path_output_.WriteFile(out_, object_files[i]);
378 }
379
380 // Append data dependencies as implicit dependencies.
381 WriteImplicitDependencies(non_linkable_deps);
382
383 out_ << std::endl;
384 }
385
386 void NinjaBinaryTargetWriter::GetDeps(
387 std::set<OutputFile>* extra_object_files,
388 std::vector<const Target*>* linkable_deps,
389 std::vector<const Target*>* non_linkable_deps) const {
390 const std::vector<const Target*>& deps = target_->deps();
391 const std::set<const Target*>& inherited = target_->inherited_libraries();
392
393 // Normal deps.
394 for (size_t i = 0; i < deps.size(); i++) {
395 if (inherited.find(deps[i]) != inherited.end())
396 continue; // Don't add dupes.
397 ClassifyDependency(deps[i], extra_object_files,
398 linkable_deps, non_linkable_deps);
399 }
400
401 // Inherited libraries.
402 for (std::set<const Target*>::const_iterator i = inherited.begin();
403 i != inherited.end(); ++i) {
404 ClassifyDependency(*i, extra_object_files,
405 linkable_deps, non_linkable_deps);
406 }
407
408 // Data deps.
360 const std::vector<const Target*>& datadeps = target_->datadeps(); 409 const std::vector<const Target*>& datadeps = target_->datadeps();
410 for (size_t i = 0; i < datadeps.size(); i++)
411 non_linkable_deps->push_back(datadeps[i]);
412 }
413
414 void NinjaBinaryTargetWriter::ClassifyDependency(
415 const Target* dep,
416 std::set<OutputFile>* extra_object_files,
417 std::vector<const Target*>* linkable_deps,
418 std::vector<const Target*>* non_linkable_deps) const {
419 // Only these types of outputs have libraries linked into them. Child deps of
420 // static libraries get pushed up the dependency tree until one of these is
421 // reached, and source sets don't link at all.
422 bool can_link_libs =
423 (target_->output_type() == Target::EXECUTABLE ||
424 target_->output_type() == Target::SHARED_LIBRARY);
425
426 if (dep->output_type() == Target::SOURCE_SET) {
427 if (target_->output_type() == Target::SOURCE_SET) {
428 // When a source set depends on another source set, add it as a data
429 // dependency so if the user says "ninja second_source_set" it will
430 // also compile the first (what you would expect) even though we'll
431 // never do anything with the first one's files.
432 non_linkable_deps->push_back(dep);
433 } else {
434 // Linking in a source set, copy its object files.
435 for (size_t i = 0; i < dep->sources().size(); i++) {
436 SourceFileType input_file_type = GetSourceFileType(
437 dep->sources()[i], dep->settings()->target_os());
438 if (input_file_type != SOURCE_UNKNOWN &&
439 input_file_type != SOURCE_H) {
440 // Note we need to specify the target as the source_set target
441 // itself, since this is used to prefix the object file name.
442 extra_object_files->insert(helper_.GetOutputFileForSource(
443 dep, dep->sources()[i], input_file_type));
444 }
445 }
446 }
447 } else if (can_link_libs && dep->IsLinkable()) {
448 linkable_deps->push_back(dep);
449 } else {
450 non_linkable_deps->push_back(dep);
451 }
452 }
453
454 void NinjaBinaryTargetWriter::WriteImplicitDependencies(
455 const std::vector<const Target*>& non_linkable_deps) {
361 const std::vector<SourceFile>& data = target_->data(); 456 const std::vector<SourceFile>& data = target_->data();
362 if (!extra_data_deps.empty() || !datadeps.empty() || !data.empty()) { 457 if (!non_linkable_deps.empty() || !data.empty()) {
363 out_ << " ||"; 458 out_ << " ||";
364 459
365 // Non-linkable deps in the deps section above. 460 // Non-linkable targets.
366 for (size_t i = 0; i < extra_data_deps.size(); i++) { 461 for (size_t i = 0; i < non_linkable_deps.size(); i++) {
367 out_ << " "; 462 out_ << " ";
368 path_output_.WriteFile(out_, 463 path_output_.WriteFile(out_,
369 helper_.GetTargetOutputFile(extra_data_deps[i])); 464 helper_.GetTargetOutputFile(non_linkable_deps[i]));
370 }
371
372 // Data deps.
373 for (size_t i = 0; i < datadeps.size(); i++) {
374 out_ << " ";
375 path_output_.WriteFile(out_, helper_.GetTargetOutputFile(datadeps[i]));
376 } 465 }
377 466
378 // Data files. 467 // Data files.
379 const std::vector<SourceFile>& data = target_->data(); 468 const std::vector<SourceFile>& data = target_->data();
380 for (size_t i = 0; i < data.size(); i++) { 469 for (size_t i = 0; i < data.size(); i++) {
381 out_ << " "; 470 out_ << " ";
382 path_output_.WriteFile(out_, data[i]); 471 path_output_.WriteFile(out_, data[i]);
383 } 472 }
384 } 473 }
385
386 out_ << std::endl;
387 } 474 }
OLDNEW
« no previous file with comments | « tools/gn/ninja_binary_target_writer.h ('k') | tools/gn/ninja_binary_target_writer_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698