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 |