| 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 | 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 302 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 313 out_ << "build "; | 313 out_ << "build "; |
| 314 path_output_.WriteFile(out_, internal_output_file); | 314 path_output_.WriteFile(out_, internal_output_file); |
| 315 if (external_output_file != internal_output_file) { | 315 if (external_output_file != internal_output_file) { |
| 316 out_ << " "; | 316 out_ << " "; |
| 317 path_output_.WriteFile(out_, external_output_file); | 317 path_output_.WriteFile(out_, external_output_file); |
| 318 } | 318 } |
| 319 out_ << ": " | 319 out_ << ": " |
| 320 << helper_.GetRulePrefix(target_->settings()) | 320 << helper_.GetRulePrefix(target_->settings()) |
| 321 << Toolchain::ToolTypeToName(tool_type_); | 321 << Toolchain::ToolTypeToName(tool_type_); |
| 322 | 322 |
| 323 std::set<OutputFile> extra_object_files; | 323 UniqueVector<OutputFile> extra_object_files; |
| 324 std::vector<const Target*> linkable_deps; | 324 UniqueVector<const Target*> linkable_deps; |
| 325 std::vector<const Target*> non_linkable_deps; | 325 UniqueVector<const Target*> non_linkable_deps; |
| 326 GetDeps(&extra_object_files, &linkable_deps, &non_linkable_deps); | 326 GetDeps(&extra_object_files, &linkable_deps, &non_linkable_deps); |
| 327 | 327 |
| 328 // Object files. | 328 // Object files. |
| 329 for (size_t i = 0; i < object_files.size(); i++) { | 329 for (size_t i = 0; i < object_files.size(); i++) { |
| 330 out_ << " "; | 330 out_ << " "; |
| 331 path_output_.WriteFile(out_, object_files[i]); | 331 path_output_.WriteFile(out_, object_files[i]); |
| 332 } | 332 } |
| 333 for (std::set<OutputFile>::iterator i = extra_object_files.begin(); | 333 for (size_t i = 0; i < extra_object_files.size(); i++) { |
| 334 i != extra_object_files.end(); ++i) { | |
| 335 out_ << " "; | 334 out_ << " "; |
| 336 path_output_.WriteFile(out_, *i); | 335 path_output_.WriteFile(out_, extra_object_files[i]); |
| 337 } | 336 } |
| 338 | 337 |
| 339 // Libs. | 338 // Libs. |
| 340 for (size_t i = 0; i < linkable_deps.size(); i++) { | 339 for (size_t i = 0; i < linkable_deps.size(); i++) { |
| 341 out_ << " "; | 340 out_ << " "; |
| 342 path_output_.WriteFile(out_, helper_.GetTargetOutputFile(linkable_deps[i])); | 341 path_output_.WriteFile(out_, helper_.GetTargetOutputFile(linkable_deps[i])); |
| 343 } | 342 } |
| 344 | 343 |
| 345 // Append data dependencies as implicit dependencies. | 344 // Append data dependencies as implicit dependencies. |
| 346 WriteImplicitDependencies(non_linkable_deps); | 345 WriteImplicitDependencies(non_linkable_deps); |
| 347 | 346 |
| 348 out_ << std::endl; | 347 out_ << std::endl; |
| 349 } | 348 } |
| 350 | 349 |
| 351 void NinjaBinaryTargetWriter::WriteSourceSetStamp( | 350 void NinjaBinaryTargetWriter::WriteSourceSetStamp( |
| 352 const std::vector<OutputFile>& object_files) { | 351 const std::vector<OutputFile>& object_files) { |
| 353 // The stamp rule for source sets is generally not used, since targets that | 352 // The stamp rule for source sets is generally not used, since targets that |
| 354 // depend on this will reference the object files directly. However, writing | 353 // depend on this will reference the object files directly. However, writing |
| 355 // this rule allows the user to type the name of the target and get a build | 354 // this rule allows the user to type the name of the target and get a build |
| 356 // which can be convenient for development. | 355 // which can be convenient for development. |
| 357 out_ << "build "; | 356 out_ << "build "; |
| 358 path_output_.WriteFile(out_, helper_.GetTargetOutputFile(target_)); | 357 path_output_.WriteFile(out_, helper_.GetTargetOutputFile(target_)); |
| 359 out_ << ": " | 358 out_ << ": " |
| 360 << helper_.GetRulePrefix(target_->settings()) | 359 << helper_.GetRulePrefix(target_->settings()) |
| 361 << "stamp"; | 360 << "stamp"; |
| 362 | 361 |
| 363 std::set<OutputFile> extra_object_files; | 362 UniqueVector<OutputFile> extra_object_files; |
| 364 std::vector<const Target*> linkable_deps; | 363 UniqueVector<const Target*> linkable_deps; |
| 365 std::vector<const Target*> non_linkable_deps; | 364 UniqueVector<const Target*> non_linkable_deps; |
| 366 GetDeps(&extra_object_files, &linkable_deps, &non_linkable_deps); | 365 GetDeps(&extra_object_files, &linkable_deps, &non_linkable_deps); |
| 367 | 366 |
| 368 // The classifier should never put extra object files in a source set: | 367 // The classifier should never put extra object files in a source set: |
| 369 // any source sets that we depend on should appear in our non-linkable | 368 // any source sets that we depend on should appear in our non-linkable |
| 370 // deps instead. | 369 // deps instead. |
| 371 DCHECK(extra_object_files.empty()); | 370 DCHECK(extra_object_files.empty()); |
| 372 | 371 |
| 373 for (size_t i = 0; i < object_files.size(); i++) { | 372 for (size_t i = 0; i < object_files.size(); i++) { |
| 374 out_ << " "; | 373 out_ << " "; |
| 375 path_output_.WriteFile(out_, object_files[i]); | 374 path_output_.WriteFile(out_, object_files[i]); |
| 376 } | 375 } |
| 377 | 376 |
| 378 // Append data dependencies as implicit dependencies. | 377 // Append data dependencies as implicit dependencies. |
| 379 WriteImplicitDependencies(non_linkable_deps); | 378 WriteImplicitDependencies(non_linkable_deps); |
| 380 | 379 |
| 381 out_ << std::endl; | 380 out_ << std::endl; |
| 382 } | 381 } |
| 383 | 382 |
| 384 void NinjaBinaryTargetWriter::GetDeps( | 383 void NinjaBinaryTargetWriter::GetDeps( |
| 385 std::set<OutputFile>* extra_object_files, | 384 UniqueVector<OutputFile>* extra_object_files, |
| 386 std::vector<const Target*>* linkable_deps, | 385 UniqueVector<const Target*>* linkable_deps, |
| 387 std::vector<const Target*>* non_linkable_deps) const { | 386 UniqueVector<const Target*>* non_linkable_deps) const { |
| 388 const LabelTargetVector& deps = target_->deps(); | 387 const LabelTargetVector& deps = target_->deps(); |
| 389 const std::set<const Target*>& inherited = target_->inherited_libraries(); | 388 const UniqueVector<const Target*>& inherited = |
| 389 target_->inherited_libraries(); |
| 390 | 390 |
| 391 // Normal deps. | 391 // Normal deps. |
| 392 for (size_t i = 0; i < deps.size(); i++) { | 392 for (size_t i = 0; i < deps.size(); i++) { |
| 393 if (inherited.find(deps[i].ptr) != inherited.end()) | |
| 394 continue; // Don't add dupes. | |
| 395 ClassifyDependency(deps[i].ptr, extra_object_files, | 393 ClassifyDependency(deps[i].ptr, extra_object_files, |
| 396 linkable_deps, non_linkable_deps); | 394 linkable_deps, non_linkable_deps); |
| 397 } | 395 } |
| 398 | 396 |
| 399 // Inherited libraries. | 397 // Inherited libraries. |
| 400 for (std::set<const Target*>::const_iterator i = inherited.begin(); | 398 for (size_t i = 0; i < inherited.size(); i++) { |
| 401 i != inherited.end(); ++i) { | 399 ClassifyDependency(inherited[i], extra_object_files, |
| 402 ClassifyDependency(*i, extra_object_files, | |
| 403 linkable_deps, non_linkable_deps); | 400 linkable_deps, non_linkable_deps); |
| 404 } | 401 } |
| 405 | 402 |
| 406 // Data deps. | 403 // Data deps. |
| 407 const LabelTargetVector& datadeps = target_->datadeps(); | 404 const LabelTargetVector& datadeps = target_->datadeps(); |
| 408 for (size_t i = 0; i < datadeps.size(); i++) | 405 for (size_t i = 0; i < datadeps.size(); i++) |
| 409 non_linkable_deps->push_back(datadeps[i].ptr); | 406 non_linkable_deps->push_back(datadeps[i].ptr); |
| 410 } | 407 } |
| 411 | 408 |
| 412 void NinjaBinaryTargetWriter::ClassifyDependency( | 409 void NinjaBinaryTargetWriter::ClassifyDependency( |
| 413 const Target* dep, | 410 const Target* dep, |
| 414 std::set<OutputFile>* extra_object_files, | 411 UniqueVector<OutputFile>* extra_object_files, |
| 415 std::vector<const Target*>* linkable_deps, | 412 UniqueVector<const Target*>* linkable_deps, |
| 416 std::vector<const Target*>* non_linkable_deps) const { | 413 UniqueVector<const Target*>* non_linkable_deps) const { |
| 417 // Only these types of outputs have libraries linked into them. Child deps of | 414 // Only these types of outputs have libraries linked into them. Child deps of |
| 418 // static libraries get pushed up the dependency tree until one of these is | 415 // static libraries get pushed up the dependency tree until one of these is |
| 419 // reached, and source sets don't link at all. | 416 // reached, and source sets don't link at all. |
| 420 bool can_link_libs = | 417 bool can_link_libs = |
| 421 (target_->output_type() == Target::EXECUTABLE || | 418 (target_->output_type() == Target::EXECUTABLE || |
| 422 target_->output_type() == Target::SHARED_LIBRARY); | 419 target_->output_type() == Target::SHARED_LIBRARY); |
| 423 | 420 |
| 424 if (dep->output_type() == Target::SOURCE_SET) { | 421 if (dep->output_type() == Target::SOURCE_SET) { |
| 425 // Source sets have their object files linked into final targets (shared | 422 // Source sets have their object files linked into final targets (shared |
| 426 // libraries and executables). Intermediate static libraries and other | 423 // libraries and executables). Intermediate static libraries and other |
| 427 // source sets just forward the dependency, otherwise the files in the | 424 // source sets just forward the dependency, otherwise the files in the |
| 428 // source set can easily get linked more than once which will cause | 425 // source set can easily get linked more than once which will cause |
| 429 // multiple definition errors. | 426 // multiple definition errors. |
| 430 // | 427 // |
| 431 // In the future, we may need a way to specify a "complete" static library | 428 // In the future, we may need a way to specify a "complete" static library |
| 432 // for cases where you want a static library that includes all source sets | 429 // for cases where you want a static library that includes all source sets |
| 433 // (like if you're shipping that to customers to link against). | 430 // (like if you're shipping that to customers to link against). |
| 434 if (target_->output_type() != Target::SOURCE_SET && | 431 if (target_->output_type() != Target::SOURCE_SET && |
| 435 target_->output_type() != Target::STATIC_LIBRARY) { | 432 target_->output_type() != Target::STATIC_LIBRARY) { |
| 436 // Linking in a source set to an executable or shared library, copy its | 433 // Linking in a source set to an executable or shared library, copy its |
| 437 // object files. | 434 // object files. |
| 438 for (size_t i = 0; i < dep->sources().size(); i++) { | 435 for (size_t i = 0; i < dep->sources().size(); i++) { |
| 439 SourceFileType input_file_type = GetSourceFileType(dep->sources()[i]); | 436 SourceFileType input_file_type = GetSourceFileType(dep->sources()[i]); |
| 440 if (input_file_type != SOURCE_UNKNOWN && | 437 if (input_file_type != SOURCE_UNKNOWN && |
| 441 input_file_type != SOURCE_H) { | 438 input_file_type != SOURCE_H) { |
| 442 // Note we need to specify the target as the source_set target | 439 // Note we need to specify the target as the source_set target |
| 443 // itself, since this is used to prefix the object file name. | 440 // itself, since this is used to prefix the object file name. |
| 444 extra_object_files->insert(helper_.GetOutputFileForSource( | 441 extra_object_files->push_back(helper_.GetOutputFileForSource( |
| 445 dep, dep->sources()[i], input_file_type)); | 442 dep, dep->sources()[i], input_file_type)); |
| 446 } | 443 } |
| 447 } | 444 } |
| 448 } | 445 } |
| 449 } else if (can_link_libs && dep->IsLinkable()) { | 446 } else if (can_link_libs && dep->IsLinkable()) { |
| 450 linkable_deps->push_back(dep); | 447 linkable_deps->push_back(dep); |
| 451 } else { | 448 } else { |
| 452 non_linkable_deps->push_back(dep); | 449 non_linkable_deps->push_back(dep); |
| 453 } | 450 } |
| 454 } | 451 } |
| 455 | 452 |
| 456 void NinjaBinaryTargetWriter::WriteImplicitDependencies( | 453 void NinjaBinaryTargetWriter::WriteImplicitDependencies( |
| 457 const std::vector<const Target*>& non_linkable_deps) { | 454 const UniqueVector<const Target*>& non_linkable_deps) { |
| 458 const std::vector<SourceFile>& data = target_->data(); | 455 const std::vector<SourceFile>& data = target_->data(); |
| 459 if (!non_linkable_deps.empty() || !data.empty()) { | 456 if (!non_linkable_deps.empty() || !data.empty()) { |
| 460 out_ << " ||"; | 457 out_ << " ||"; |
| 461 | 458 |
| 462 // Non-linkable targets. | 459 // Non-linkable targets. |
| 463 for (size_t i = 0; i < non_linkable_deps.size(); i++) { | 460 for (size_t i = 0; i < non_linkable_deps.size(); i++) { |
| 464 out_ << " "; | 461 out_ << " "; |
| 465 path_output_.WriteFile(out_, | 462 path_output_.WriteFile(out_, |
| 466 helper_.GetTargetOutputFile(non_linkable_deps[i])); | 463 helper_.GetTargetOutputFile(non_linkable_deps[i])); |
| 467 } | 464 } |
| 468 | 465 |
| 469 // Data files. | 466 // Data files. |
| 470 const std::vector<SourceFile>& data = target_->data(); | 467 const std::vector<SourceFile>& data = target_->data(); |
| 471 for (size_t i = 0; i < data.size(); i++) { | 468 for (size_t i = 0; i < data.size(); i++) { |
| 472 out_ << " "; | 469 out_ << " "; |
| 473 path_output_.WriteFile(out_, data[i]); | 470 path_output_.WriteFile(out_, data[i]); |
| 474 } | 471 } |
| 475 } | 472 } |
| 476 } | 473 } |
| OLD | NEW |