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

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

Issue 2071573003: GN: Use implicit dependency for binary input deps (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Update tests Created 4 years, 6 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
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 <stddef.h> 7 #include <stddef.h>
8 #include <string.h> 8 #include <string.h>
9 9
10 #include <cstring> 10 #include <cstring>
(...skipping 252 matching lines...) Expand 10 before | Expand all | Expand 10 after
263 } 263 }
264 264
265 void NinjaBinaryTargetWriter::Run() { 265 void NinjaBinaryTargetWriter::Run() {
266 // Figure out what source types are needed. 266 // Figure out what source types are needed.
267 SourceFileTypeSet used_types; 267 SourceFileTypeSet used_types;
268 for (const auto& source : target_->sources()) 268 for (const auto& source : target_->sources())
269 used_types.Set(GetSourceFileType(source)); 269 used_types.Set(GetSourceFileType(source));
270 270
271 WriteCompilerVars(used_types); 271 WriteCompilerVars(used_types);
272 272
273 // The input dependencies will be an order-only dependency. This will cause 273 // The input dependencies will be an implicit dependency. This will cause
274 // Ninja to make sure the inputs are up to date before compiling this source, 274 // Ninja to make sure the inputs are up to date before compiling this source;
275 // but changes in the inputs deps won't cause the file to be recompiled. 275 // changes in the inputs deps will cause the file to be recompiled.
276 // 276 //
277 // This is important to prevent changes in unrelated actions that are 277 // This is to make sure that we force rebuild the source when the inputs
278 // upstream of this target from causing everything to be recompiled. 278 // change. Why cannot we rely on the dependencies computed by the compiler?
279 // 279 // These dependencies only include headers and might miss other resources
280 // Why can we get away with this rather than using implicit deps ("|", which 280 // that are used by the input file.
281 // will force rebuilds when the inputs change)? For source code, the 281 OutputFile input_dep =
282 // computed dependencies of all headers will be computed by the compiler,
283 // which will cause source rebuilds if any "real" upstream dependencies
284 // change.
285 //
286 // If a .cc file is generated by an input dependency, Ninja will see the
287 // input to the build rule doesn't exist, and that it is an output from a
288 // previous step, and build the previous step first. This is a "real"
289 // dependency and doesn't need | or || to express.
290 //
291 // The only case where this rule matters is for the first build where no .d
292 // files exist, and Ninja doesn't know what that source file depends on. In
293 // this case it's sufficient to ensure that the upstream dependencies are
294 // built first. This is exactly what Ninja's order-only dependencies
295 // expresses.
296 OutputFile order_only_dep =
297 WriteInputDepsStampAndGetDep(std::vector<const Target*>()); 282 WriteInputDepsStampAndGetDep(std::vector<const Target*>());
298 283
299 // For GCC builds, the .gch files are not object files, but still need to be 284 // For GCC builds, the .gch files are not object files, but still need to be
300 // added as explicit dependencies below. The .gch output files are placed in 285 // added as explicit dependencies below. The .gch output files are placed in
301 // |pch_other_files|. This is to prevent linking against them. 286 // |pch_other_files|. This is to prevent linking against them.
302 std::vector<OutputFile> pch_obj_files; 287 std::vector<OutputFile> pch_obj_files;
303 std::vector<OutputFile> pch_other_files; 288 std::vector<OutputFile> pch_other_files;
304 WritePCHCommands(used_types, order_only_dep, 289 WritePCHCommands(used_types, input_dep,
305 &pch_obj_files, &pch_other_files); 290 &pch_obj_files, &pch_other_files);
306 std::vector<OutputFile>* pch_files = !pch_obj_files.empty() ? 291 std::vector<OutputFile>* pch_files = !pch_obj_files.empty() ?
307 &pch_obj_files : &pch_other_files; 292 &pch_obj_files : &pch_other_files;
308 293
309 // Treat all pch output files as explicit dependencies of all 294 // Treat all pch output files as explicit dependencies of all
310 // compiles that support them. Some notes: 295 // compiles that support them. Some notes:
311 // 296 //
312 // - On Windows, the .pch file is the input to the compile, not the 297 // - On Windows, the .pch file is the input to the compile, not the
313 // precompiled header's corresponding object file that we're using here. 298 // precompiled header's corresponding object file that we're using here.
314 // But Ninja's depslog doesn't support multiple outputs from the 299 // But Ninja's depslog doesn't support multiple outputs from the
315 // precompiled header compile step (it outputs both the .pch file and a 300 // precompiled header compile step (it outputs both the .pch file and a
316 // corresponding .obj file). So we consistently list the .obj file and the 301 // corresponding .obj file). So we consistently list the .obj file and the
317 // .pch file we really need comes along with it. 302 // .pch file we really need comes along with it.
318 // 303 //
319 // - GCC .gch files are not object files, therefore they are not added to the 304 // - GCC .gch files are not object files, therefore they are not added to the
320 // object file list. 305 // object file list.
321 std::vector<OutputFile> obj_files; 306 std::vector<OutputFile> obj_files;
322 std::vector<SourceFile> other_files; 307 std::vector<SourceFile> other_files;
323 WriteSources(*pch_files, order_only_dep, &obj_files, &other_files); 308 WriteSources(*pch_files, input_dep, &obj_files, &other_files);
324 309
325 // Link all MSVC pch object files. The vector will be empty on GCC toolchains. 310 // Link all MSVC pch object files. The vector will be empty on GCC toolchains.
326 obj_files.insert(obj_files.end(), pch_obj_files.begin(), pch_obj_files.end()); 311 obj_files.insert(obj_files.end(), pch_obj_files.begin(), pch_obj_files.end());
327 if (!CheckForDuplicateObjectFiles(obj_files)) 312 if (!CheckForDuplicateObjectFiles(obj_files))
328 return; 313 return;
329 314
330 if (target_->output_type() == Target::SOURCE_SET) { 315 if (target_->output_type() == Target::SOURCE_SET) {
331 WriteSourceSetStamp(obj_files); 316 WriteSourceSetStamp(obj_files);
332 #ifndef NDEBUG 317 #ifndef NDEBUG
333 // Verify that the function that separately computes a source set's object 318 // Verify that the function that separately computes a source set's object
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after
446 } 431 }
447 } else { 432 } else {
448 RecursiveTargetConfigStringsToStream(target_, getter, 433 RecursiveTargetConfigStringsToStream(target_, getter,
449 flag_escape_options, out_); 434 flag_escape_options, out_);
450 } 435 }
451 out_ << std::endl; 436 out_ << std::endl;
452 } 437 }
453 438
454 void NinjaBinaryTargetWriter::WritePCHCommands( 439 void NinjaBinaryTargetWriter::WritePCHCommands(
455 const SourceFileTypeSet& used_types, 440 const SourceFileTypeSet& used_types,
456 const OutputFile& order_only_dep, 441 const OutputFile& input_dep,
457 std::vector<OutputFile>* object_files, 442 std::vector<OutputFile>* object_files,
458 std::vector<OutputFile>* other_files) { 443 std::vector<OutputFile>* other_files) {
459 if (!target_->config_values().has_precompiled_headers()) 444 if (!target_->config_values().has_precompiled_headers())
460 return; 445 return;
461 446
462 const Tool* tool_c = target_->toolchain()->GetTool(Toolchain::TYPE_CC); 447 const Tool* tool_c = target_->toolchain()->GetTool(Toolchain::TYPE_CC);
463 if (tool_c && 448 if (tool_c &&
464 tool_c->precompiled_header_type() != Tool::PCH_NONE && 449 tool_c->precompiled_header_type() != Tool::PCH_NONE &&
465 used_types.Get(SOURCE_C)) { 450 used_types.Get(SOURCE_C)) {
466 WritePCHCommand(SUBSTITUTION_CFLAGS_C, 451 WritePCHCommand(SUBSTITUTION_CFLAGS_C,
467 Toolchain::TYPE_CC, 452 Toolchain::TYPE_CC,
468 tool_c->precompiled_header_type(), 453 tool_c->precompiled_header_type(),
469 order_only_dep, object_files, other_files); 454 input_dep, object_files, other_files);
470 } 455 }
471 const Tool* tool_cxx = target_->toolchain()->GetTool(Toolchain::TYPE_CXX); 456 const Tool* tool_cxx = target_->toolchain()->GetTool(Toolchain::TYPE_CXX);
472 if (tool_cxx && 457 if (tool_cxx &&
473 tool_cxx->precompiled_header_type() != Tool::PCH_NONE && 458 tool_cxx->precompiled_header_type() != Tool::PCH_NONE &&
474 used_types.Get(SOURCE_CPP)) { 459 used_types.Get(SOURCE_CPP)) {
475 WritePCHCommand(SUBSTITUTION_CFLAGS_CC, 460 WritePCHCommand(SUBSTITUTION_CFLAGS_CC,
476 Toolchain::TYPE_CXX, 461 Toolchain::TYPE_CXX,
477 tool_cxx->precompiled_header_type(), 462 tool_cxx->precompiled_header_type(),
478 order_only_dep, object_files, other_files); 463 input_dep, object_files, other_files);
479 } 464 }
480 465
481 const Tool* tool_objc = target_->toolchain()->GetTool(Toolchain::TYPE_OBJC); 466 const Tool* tool_objc = target_->toolchain()->GetTool(Toolchain::TYPE_OBJC);
482 if (tool_objc && 467 if (tool_objc &&
483 tool_objc->precompiled_header_type() == Tool::PCH_GCC && 468 tool_objc->precompiled_header_type() == Tool::PCH_GCC &&
484 used_types.Get(SOURCE_M)) { 469 used_types.Get(SOURCE_M)) {
485 WritePCHCommand(SUBSTITUTION_CFLAGS_OBJC, 470 WritePCHCommand(SUBSTITUTION_CFLAGS_OBJC,
486 Toolchain::TYPE_OBJC, 471 Toolchain::TYPE_OBJC,
487 tool_objc->precompiled_header_type(), 472 tool_objc->precompiled_header_type(),
488 order_only_dep, object_files, other_files); 473 input_dep, object_files, other_files);
489 } 474 }
490 475
491 const Tool* tool_objcxx = 476 const Tool* tool_objcxx =
492 target_->toolchain()->GetTool(Toolchain::TYPE_OBJCXX); 477 target_->toolchain()->GetTool(Toolchain::TYPE_OBJCXX);
493 if (tool_objcxx && 478 if (tool_objcxx &&
494 tool_objcxx->precompiled_header_type() == Tool::PCH_GCC && 479 tool_objcxx->precompiled_header_type() == Tool::PCH_GCC &&
495 used_types.Get(SOURCE_MM)) { 480 used_types.Get(SOURCE_MM)) {
496 WritePCHCommand(SUBSTITUTION_CFLAGS_OBJCC, 481 WritePCHCommand(SUBSTITUTION_CFLAGS_OBJCC,
497 Toolchain::TYPE_OBJCXX, 482 Toolchain::TYPE_OBJCXX,
498 tool_objcxx->precompiled_header_type(), 483 tool_objcxx->precompiled_header_type(),
499 order_only_dep, object_files, other_files); 484 input_dep, object_files, other_files);
500 } 485 }
501 } 486 }
502 487
503 void NinjaBinaryTargetWriter::WritePCHCommand( 488 void NinjaBinaryTargetWriter::WritePCHCommand(
504 SubstitutionType flag_type, 489 SubstitutionType flag_type,
505 Toolchain::ToolType tool_type, 490 Toolchain::ToolType tool_type,
506 Tool::PrecompiledHeaderType header_type, 491 Tool::PrecompiledHeaderType header_type,
507 const OutputFile& order_only_dep, 492 const OutputFile& input_dep,
508 std::vector<OutputFile>* object_files, 493 std::vector<OutputFile>* object_files,
509 std::vector<OutputFile>* other_files) { 494 std::vector<OutputFile>* other_files) {
510 switch (header_type) { 495 switch (header_type) {
511 case Tool::PCH_MSVC: 496 case Tool::PCH_MSVC:
512 WriteWindowsPCHCommand(flag_type, tool_type, order_only_dep, 497 WriteWindowsPCHCommand(flag_type, tool_type, input_dep,
513 object_files); 498 object_files);
514 break; 499 break;
515 case Tool::PCH_GCC: 500 case Tool::PCH_GCC:
516 WriteGCCPCHCommand(flag_type, tool_type, order_only_dep, 501 WriteGCCPCHCommand(flag_type, tool_type, input_dep,
517 other_files); 502 other_files);
518 break; 503 break;
519 case Tool::PCH_NONE: 504 case Tool::PCH_NONE:
520 NOTREACHED() << "Cannot write a PCH command with no PCH header type"; 505 NOTREACHED() << "Cannot write a PCH command with no PCH header type";
521 break; 506 break;
522 } 507 }
523 } 508 }
524 509
525 void NinjaBinaryTargetWriter::WriteGCCPCHCommand( 510 void NinjaBinaryTargetWriter::WriteGCCPCHCommand(
526 SubstitutionType flag_type, 511 SubstitutionType flag_type,
527 Toolchain::ToolType tool_type, 512 Toolchain::ToolType tool_type,
528 const OutputFile& order_only_dep, 513 const OutputFile& input_dep,
529 std::vector<OutputFile>* gch_files) { 514 std::vector<OutputFile>* gch_files) {
530 // Compute the pch output file (it will be language-specific). 515 // Compute the pch output file (it will be language-specific).
531 std::vector<OutputFile> outputs; 516 std::vector<OutputFile> outputs;
532 GetPCHOutputFiles(target_, tool_type, &outputs); 517 GetPCHOutputFiles(target_, tool_type, &outputs);
533 if (outputs.empty()) 518 if (outputs.empty())
534 return; 519 return;
535 520
536 gch_files->insert(gch_files->end(), outputs.begin(), outputs.end()); 521 gch_files->insert(gch_files->end(), outputs.begin(), outputs.end());
537 522
523 std::vector<OutputFile> deps;
524 if (!input_dep.value().empty()) {
brettw 2016/06/16 19:41:34 No {}, same for the additions below.
Petr Hosek 2016/06/16 23:11:47 Done.
525 deps.push_back(input_dep);
526 }
527
538 // Build line to compile the file. 528 // Build line to compile the file.
539 WriteCompilerBuildLine(target_->config_values().precompiled_source(), 529 WriteCompilerBuildLine(target_->config_values().precompiled_source(),
540 std::vector<OutputFile>(), order_only_dep, tool_type, 530 deps, tool_type, outputs);
541 outputs);
542 531
543 // This build line needs a custom language-specific flags value. Rule-specific 532 // This build line needs a custom language-specific flags value. Rule-specific
544 // variables are just indented underneath the rule line. 533 // variables are just indented underneath the rule line.
545 out_ << " " << kSubstitutionNinjaNames[flag_type] << " ="; 534 out_ << " " << kSubstitutionNinjaNames[flag_type] << " =";
546 535
547 // Each substitution flag is overwritten in the target rule to replace the 536 // Each substitution flag is overwritten in the target rule to replace the
548 // implicitly generated -include flag with the -x <header lang> flag required 537 // implicitly generated -include flag with the -x <header lang> flag required
549 // for .gch targets. 538 // for .gch targets.
550 EscapeOptions opts = GetFlagOptions(); 539 EscapeOptions opts = GetFlagOptions();
551 if (tool_type == Toolchain::TYPE_CC) { 540 if (tool_type == Toolchain::TYPE_CC) {
(...skipping 14 matching lines...) Expand all
566 out_ << " -x " << GetPCHLangForToolType(tool_type); 555 out_ << " -x " << GetPCHLangForToolType(tool_type);
567 556
568 // Write two blank lines to help separate the PCH build lines from the 557 // Write two blank lines to help separate the PCH build lines from the
569 // regular source build lines. 558 // regular source build lines.
570 out_ << std::endl << std::endl; 559 out_ << std::endl << std::endl;
571 } 560 }
572 561
573 void NinjaBinaryTargetWriter::WriteWindowsPCHCommand( 562 void NinjaBinaryTargetWriter::WriteWindowsPCHCommand(
574 SubstitutionType flag_type, 563 SubstitutionType flag_type,
575 Toolchain::ToolType tool_type, 564 Toolchain::ToolType tool_type,
576 const OutputFile& order_only_dep, 565 const OutputFile& input_dep,
577 std::vector<OutputFile>* object_files) { 566 std::vector<OutputFile>* object_files) {
578 // Compute the pch output file (it will be language-specific). 567 // Compute the pch output file (it will be language-specific).
579 std::vector<OutputFile> outputs; 568 std::vector<OutputFile> outputs;
580 GetPCHOutputFiles(target_, tool_type, &outputs); 569 GetPCHOutputFiles(target_, tool_type, &outputs);
581 if (outputs.empty()) 570 if (outputs.empty())
582 return; 571 return;
583 572
584 object_files->insert(object_files->end(), outputs.begin(), outputs.end()); 573 object_files->insert(object_files->end(), outputs.begin(), outputs.end());
585 574
575 std::vector<OutputFile> deps;
576 if (!input_dep.value().empty()) {
577 deps.push_back(input_dep);
578 }
579
586 // Build line to compile the file. 580 // Build line to compile the file.
587 WriteCompilerBuildLine(target_->config_values().precompiled_source(), 581 WriteCompilerBuildLine(target_->config_values().precompiled_source(),
588 std::vector<OutputFile>(), order_only_dep, tool_type, 582 deps, tool_type, outputs);
589 outputs);
590 583
591 // This build line needs a custom language-specific flags value. Rule-specific 584 // This build line needs a custom language-specific flags value. Rule-specific
592 // variables are just indented underneath the rule line. 585 // variables are just indented underneath the rule line.
593 out_ << " " << kSubstitutionNinjaNames[flag_type] << " ="; 586 out_ << " " << kSubstitutionNinjaNames[flag_type] << " =";
594 587
595 // Append the command to generate the .pch file. 588 // Append the command to generate the .pch file.
596 // This adds the value to the existing flag instead of overwriting it. 589 // This adds the value to the existing flag instead of overwriting it.
597 out_ << " ${" << kSubstitutionNinjaNames[flag_type] << "}"; 590 out_ << " ${" << kSubstitutionNinjaNames[flag_type] << "}";
598 out_ << " /Yc" << target_->config_values().precompiled_header(); 591 out_ << " /Yc" << target_->config_values().precompiled_header();
599 592
600 // Write two blank lines to help separate the PCH build lines from the 593 // Write two blank lines to help separate the PCH build lines from the
601 // regular source build lines. 594 // regular source build lines.
602 out_ << std::endl << std::endl; 595 out_ << std::endl << std::endl;
603 } 596 }
604 597
605 void NinjaBinaryTargetWriter::WriteSources( 598 void NinjaBinaryTargetWriter::WriteSources(
606 const std::vector<OutputFile>& pch_deps, 599 const std::vector<OutputFile>& pch_deps,
607 const OutputFile& order_only_dep, 600 const OutputFile& input_dep,
608 std::vector<OutputFile>* object_files, 601 std::vector<OutputFile>* object_files,
609 std::vector<SourceFile>* other_files) { 602 std::vector<SourceFile>* other_files) {
610 object_files->reserve(object_files->size() + target_->sources().size()); 603 object_files->reserve(object_files->size() + target_->sources().size());
611 604
612 std::vector<OutputFile> tool_outputs; // Prevent reallocation in loop. 605 std::vector<OutputFile> tool_outputs; // Prevent reallocation in loop.
613 std::vector<OutputFile> deps; 606 std::vector<OutputFile> deps;
607
614 for (const auto& source : target_->sources()) { 608 for (const auto& source : target_->sources()) {
615 // Clear the vector but maintain the max capacity to prevent reallocations. 609 // Clear the vector but maintain the max capacity to prevent reallocations.
616 deps.resize(0); 610 deps.resize(0);
617 Toolchain::ToolType tool_type = Toolchain::TYPE_NONE; 611 Toolchain::ToolType tool_type = Toolchain::TYPE_NONE;
618 if (!target_->GetOutputFilesForSource(source, &tool_type, &tool_outputs)) { 612 if (!target_->GetOutputFilesForSource(source, &tool_type, &tool_outputs)) {
619 if (GetSourceFileType(source) == SOURCE_DEF) 613 if (GetSourceFileType(source) == SOURCE_DEF)
620 other_files->push_back(source); 614 other_files->push_back(source);
621 continue; // No output for this source. 615 continue; // No output for this source.
622 } 616 }
623 617
618 if (!input_dep.value().empty()) {
619 deps.push_back(input_dep);
620 }
621
624 if (tool_type != Toolchain::TYPE_NONE) { 622 if (tool_type != Toolchain::TYPE_NONE) {
625 // Only include PCH deps that correspond to the tool type, for instance, 623 // Only include PCH deps that correspond to the tool type, for instance,
626 // do not specify target_name.precompile.cc.obj (a CXX PCH file) as a dep 624 // do not specify target_name.precompile.cc.obj (a CXX PCH file) as a dep
627 // for the output of a C tool type. 625 // for the output of a C tool type.
628 // 626 //
629 // This makes the assumption that pch_deps only contains pch output files 627 // This makes the assumption that pch_deps only contains pch output files
630 // with the naming scheme specified in GetWindowsPCHObjectExtension or 628 // with the naming scheme specified in GetWindowsPCHObjectExtension or
631 // GetGCCPCHOutputExtension. 629 // GetGCCPCHOutputExtension.
632 const Tool* tool = target_->toolchain()->GetTool(tool_type); 630 const Tool* tool = target_->toolchain()->GetTool(tool_type);
633 if (tool->precompiled_header_type() != Tool::PCH_NONE) { 631 if (tool->precompiled_header_type() != Tool::PCH_NONE) {
634 for (const auto& dep : pch_deps) { 632 for (const auto& dep : pch_deps) {
635 const std::string& output_value = dep.value(); 633 const std::string& output_value = dep.value();
636 size_t extension_offset = FindExtensionOffset(output_value); 634 size_t extension_offset = FindExtensionOffset(output_value);
637 if (extension_offset == std::string::npos) 635 if (extension_offset == std::string::npos)
638 continue; 636 continue;
639 std::string output_extension; 637 std::string output_extension;
640 if (tool->precompiled_header_type() == Tool::PCH_MSVC) { 638 if (tool->precompiled_header_type() == Tool::PCH_MSVC) {
641 output_extension = GetWindowsPCHObjectExtension( 639 output_extension = GetWindowsPCHObjectExtension(
642 tool_type, output_value.substr(extension_offset - 1)); 640 tool_type, output_value.substr(extension_offset - 1));
643 } else if (tool->precompiled_header_type() == Tool::PCH_GCC) { 641 } else if (tool->precompiled_header_type() == Tool::PCH_GCC) {
644 output_extension = GetGCCPCHOutputExtension(tool_type); 642 output_extension = GetGCCPCHOutputExtension(tool_type);
645 } 643 }
646 if (output_value.compare(output_value.size() - 644 if (output_value.compare(output_value.size() -
647 output_extension.size(), output_extension.size(), 645 output_extension.size(), output_extension.size(),
648 output_extension) == 0) { 646 output_extension) == 0) {
649 deps.push_back(dep); 647 deps.push_back(dep);
650 } 648 }
651 } 649 }
652 } 650 }
653 WriteCompilerBuildLine(source, deps, order_only_dep, tool_type, 651 WriteCompilerBuildLine(source, deps, tool_type, tool_outputs);
654 tool_outputs);
655 } 652 }
656 653
657 // It's theoretically possible for a compiler to produce more than one 654 // It's theoretically possible for a compiler to produce more than one
658 // output, but we'll only link to the first output. 655 // output, but we'll only link to the first output.
659 object_files->push_back(tool_outputs[0]); 656 object_files->push_back(tool_outputs[0]);
660 } 657 }
661 out_ << std::endl; 658 out_ << std::endl;
662 } 659 }
663 660
664 void NinjaBinaryTargetWriter::WriteCompilerBuildLine( 661 void NinjaBinaryTargetWriter::WriteCompilerBuildLine(
665 const SourceFile& source, 662 const SourceFile& source,
666 const std::vector<OutputFile>& extra_deps, 663 const std::vector<OutputFile>& extra_deps,
667 const OutputFile& order_only_dep,
668 Toolchain::ToolType tool_type, 664 Toolchain::ToolType tool_type,
669 const std::vector<OutputFile>& outputs) { 665 const std::vector<OutputFile>& outputs) {
670 out_ << "build"; 666 out_ << "build";
671 path_output_.WriteFiles(out_, outputs); 667 path_output_.WriteFiles(out_, outputs);
672 668
673 out_ << ": " << rule_prefix_ << Toolchain::ToolTypeToName(tool_type); 669 out_ << ": " << rule_prefix_ << Toolchain::ToolTypeToName(tool_type);
674 out_ << " "; 670 out_ << " ";
675 path_output_.WriteFile(out_, source); 671 path_output_.WriteFile(out_, source);
676 672
677 if (!extra_deps.empty()) { 673 if (!extra_deps.empty()) {
678 out_ << " |"; 674 out_ << " |";
679 for (const OutputFile& dep : extra_deps) { 675 for (const OutputFile& dep : extra_deps) {
680 out_ << " "; 676 out_ << " ";
681 path_output_.WriteFile(out_, dep); 677 path_output_.WriteFile(out_, dep);
682 } 678 }
683 } 679 }
684
685 if (!order_only_dep.value().empty()) {
686 out_ << " || ";
687 path_output_.WriteFile(out_, order_only_dep);
688 }
689 out_ << std::endl; 680 out_ << std::endl;
690 } 681 }
691 682
692 void NinjaBinaryTargetWriter::WriteLinkerStuff( 683 void NinjaBinaryTargetWriter::WriteLinkerStuff(
693 const std::vector<OutputFile>& object_files, 684 const std::vector<OutputFile>& object_files,
694 const std::vector<SourceFile>& other_files) { 685 const std::vector<SourceFile>& other_files) {
695 std::vector<OutputFile> output_files; 686 std::vector<OutputFile> output_files;
696 SubstitutionWriter::ApplyListToLinkerAsOutputFile( 687 SubstitutionWriter::ApplyListToLinkerAsOutputFile(
697 target_, tool_, tool_->outputs(), &output_files); 688 target_, tool_, tool_->outputs(), &output_files);
698 689
699 out_ << "build"; 690 out_ << "build";
700 path_output_.WriteFiles(out_, output_files); 691 path_output_.WriteFiles(out_, output_files);
701 692
702 out_ << ": " << rule_prefix_ 693 out_ << ": " << rule_prefix_
703 << Toolchain::ToolTypeToName( 694 << Toolchain::ToolTypeToName(
704 target_->toolchain()->GetToolTypeForTargetFinalOutput(target_)); 695 target_->toolchain()->GetToolTypeForTargetFinalOutput(target_));
705 696
706 UniqueVector<OutputFile> extra_object_files; 697 UniqueVector<OutputFile> extra_object_files;
707 UniqueVector<const Target*> linkable_deps; 698 UniqueVector<const Target*> linkable_deps;
708 UniqueVector<const Target*> non_linkable_deps; 699 UniqueVector<const Target*> non_linkable_deps;
709 GetDeps(&extra_object_files, &linkable_deps, &non_linkable_deps); 700 GetDeps(&extra_object_files, &linkable_deps, &non_linkable_deps);
710 701
711 // Object files. 702 // Object files.
712 path_output_.WriteFiles(out_, object_files); 703 path_output_.WriteFiles(out_, object_files);
713 path_output_.WriteFiles(out_, extra_object_files); 704 path_output_.WriteFiles(out_, extra_object_files);
714 705
715 // Dependencies. 706 // Dependencies.
716 std::vector<OutputFile> implicit_deps; 707 std::vector<OutputFile> input_deps;
717 std::vector<OutputFile> solibs; 708 std::vector<OutputFile> solibs;
718 for (const Target* cur : linkable_deps) { 709 for (const Target* cur : linkable_deps) {
719 // All linkable deps should have a link output file. 710 // All linkable deps should have a link output file.
720 DCHECK(!cur->link_output_file().value().empty()) 711 DCHECK(!cur->link_output_file().value().empty())
721 << "No link output file for " 712 << "No link output file for "
722 << target_->label().GetUserVisibleName(false); 713 << target_->label().GetUserVisibleName(false);
723 714
724 if (cur->dependency_output_file().value() != 715 if (cur->dependency_output_file().value() !=
725 cur->link_output_file().value()) { 716 cur->link_output_file().value()) {
726 // This is a shared library with separate link and deps files. Save for 717 // This is a shared library with separate link and deps files. Save for
727 // later. 718 // later.
728 implicit_deps.push_back(cur->dependency_output_file()); 719 input_deps.push_back(cur->dependency_output_file());
729 solibs.push_back(cur->link_output_file()); 720 solibs.push_back(cur->link_output_file());
730 } else { 721 } else {
731 // Normal case, just link to this target. 722 // Normal case, just link to this target.
732 out_ << " "; 723 out_ << " ";
733 path_output_.WriteFile(out_, cur->link_output_file()); 724 path_output_.WriteFile(out_, cur->link_output_file());
734 } 725 }
735 } 726 }
736 727
737 const SourceFile* optional_def_file = nullptr; 728 const SourceFile* optional_def_file = nullptr;
738 if (!other_files.empty()) { 729 if (!other_files.empty()) {
739 for (const SourceFile& src_file : other_files) { 730 for (const SourceFile& src_file : other_files) {
740 if (GetSourceFileType(src_file) == SOURCE_DEF) { 731 if (GetSourceFileType(src_file) == SOURCE_DEF) {
741 optional_def_file = &src_file; 732 optional_def_file = &src_file;
742 implicit_deps.push_back( 733 input_deps.push_back(
743 OutputFile(settings_->build_settings(), src_file)); 734 OutputFile(settings_->build_settings(), src_file));
744 break; // Only one def file is allowed. 735 break; // Only one def file is allowed.
745 } 736 }
746 } 737 }
747 } 738 }
748 739
749 // Libraries specified by paths. 740 // Libraries specified by paths.
750 const OrderedSet<LibFile>& libs = target_->all_libs(); 741 const OrderedSet<LibFile>& libs = target_->all_libs();
751 for (size_t i = 0; i < libs.size(); i++) { 742 for (size_t i = 0; i < libs.size(); i++) {
752 if (libs[i].is_source_file()) { 743 if (libs[i].is_source_file()) {
753 implicit_deps.push_back( 744 input_deps.push_back(
754 OutputFile(settings_->build_settings(), libs[i].source_file())); 745 OutputFile(settings_->build_settings(), libs[i].source_file()));
755 } 746 }
756 } 747 }
757 748
758 // Append implicit dependencies collected above. 749 // Append implicit dependencies collected above.
759 if (!implicit_deps.empty()) { 750 if (!input_deps.empty()) {
760 out_ << " |"; 751 out_ << " |";
761 path_output_.WriteFiles(out_, implicit_deps); 752 path_output_.WriteFiles(out_, input_deps);
762 } 753 }
763 754
764 // Append data dependencies as order-only dependencies. 755 // Append data dependencies as order-only dependencies.
765 // 756 //
766 // This will include data dependencies and input dependencies (like when 757 // This will include data dependencies and input dependencies (like when
767 // this target depends on an action). Having the data dependencies in this 758 // this target depends on an action). Having the data dependencies in this
768 // list ensures that the data is available at runtime when the user builds 759 // list ensures that the data is available at runtime when the user builds
769 // this target. 760 // this target.
770 // 761 //
771 // The action dependencies are not strictly necessary in this case. They 762 // The action dependencies are not strictly necessary in this case. They
(...skipping 243 matching lines...) Expand 10 before | Expand all | Expand 10 after
1015 "\n" 1006 "\n"
1016 "In the latter case, either rename one of the files or move one of\n" 1007 "In the latter case, either rename one of the files or move one of\n"
1017 "the sources to a separate source_set to avoid them both being in\n" 1008 "the sources to a separate source_set to avoid them both being in\n"
1018 "the same target."); 1009 "the same target.");
1019 g_scheduler->FailWithError(err); 1010 g_scheduler->FailWithError(err);
1020 return false; 1011 return false;
1021 } 1012 }
1022 } 1013 }
1023 return true; 1014 return true;
1024 } 1015 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698