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_target_writer.h" | 5 #include "tools/gn/ninja_target_writer.h" |
6 | 6 |
7 #include <fstream> | 7 #include <fstream> |
8 #include <sstream> | 8 #include <sstream> |
9 | 9 |
10 #include "base/file_util.h" | 10 #include "base/file_util.h" |
(...skipping 211 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
222 for (size_t i = 0; i < target_->script_args().size(); i++) { | 222 for (size_t i = 0; i < target_->script_args().size(); i++) { |
223 const std::string& arg = target_->script_args()[i]; | 223 const std::string& arg = target_->script_args()[i]; |
224 out_ << " "; | 224 out_ << " "; |
225 WriteCustomArg(arg); | 225 WriteCustomArg(arg); |
226 } | 226 } |
227 out_ << std::endl << std::endl; | 227 out_ << std::endl << std::endl; |
228 | 228 |
229 // Precompute the common dependencies for each step. This includes the | 229 // Precompute the common dependencies for each step. This includes the |
230 // script itself (changing the script should force a rebuild) and any data | 230 // script itself (changing the script should force a rebuild) and any data |
231 // files. | 231 // files. |
| 232 // |
| 233 // TODO(brettW) this needs to be re-thought. "data" is supposed to be runtime |
| 234 // data (i.e. for tests and such) rather than compile-time dependencies for |
| 235 // each target. If we really need this, we need to have a different way to |
| 236 // express it. |
| 237 // |
| 238 // One idea: add an "inputs" variable to specify this kind of thing. We |
| 239 // should probably make it an error to specify data but no inputs for a |
| 240 // script as a way to catch people doing the wrong way. |
232 std::ostringstream common_deps_stream; | 241 std::ostringstream common_deps_stream; |
233 path_output_.WriteFile(common_deps_stream, target_->script()); | 242 path_output_.WriteFile(common_deps_stream, target_->script()); |
234 const Target::FileList& datas = target_->data(); | 243 const Target::FileList& datas = target_->data(); |
235 for (size_t i = 0; i < datas.size(); i++) { | 244 for (size_t i = 0; i < datas.size(); i++) { |
236 common_deps_stream << " "; | 245 common_deps_stream << " "; |
237 path_output_.WriteFile(common_deps_stream, datas[i]); | 246 path_output_.WriteFile(common_deps_stream, datas[i]); |
238 } | 247 } |
239 const std::string& common_deps = common_deps_stream.str(); | 248 const std::string& common_deps = common_deps_stream.str(); |
240 | 249 |
241 // Collects all output files for writing below. | 250 // Collects all output files for writing below. |
(...skipping 208 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
450 if (target_->output_type() == Target::SHARED_LIBRARY) { | 459 if (target_->output_type() == Target::SHARED_LIBRARY) { |
451 if (settings_->IsWin()) { | 460 if (settings_->IsWin()) { |
452 internal_output_file = OutputFile(target_->label().name() + ".dll"); | 461 internal_output_file = OutputFile(target_->label().name() + ".dll"); |
453 } else { | 462 } else { |
454 internal_output_file = external_output_file; | 463 internal_output_file = external_output_file; |
455 } | 464 } |
456 } else { | 465 } else { |
457 internal_output_file = external_output_file; | 466 internal_output_file = external_output_file; |
458 } | 467 } |
459 | 468 |
460 // TODO(brettw) should we append data files to this? | |
461 | |
462 // In Python see "self.ninja.build(output, command, input," | 469 // In Python see "self.ninja.build(output, command, input," |
463 out_ << "build "; | 470 WriteLinkCommand(external_output_file, internal_output_file, object_files); |
464 path_output_.WriteFile(out_, internal_output_file); | |
465 if (external_output_file != internal_output_file) { | |
466 out_ << " "; | |
467 path_output_.WriteFile(out_, external_output_file); | |
468 } | |
469 out_ << ": " << GetCommandForTargetType(); | |
470 for (size_t i = 0; i < object_files.size(); i++) { | |
471 out_ << " "; | |
472 path_output_.WriteFile(out_, object_files[i]); | |
473 } | |
474 | |
475 if (target_->output_type() == Target::EXECUTABLE || | |
476 target_->output_type() == Target::SHARED_LIBRARY || | |
477 target_->output_type() == Target::LOADABLE_MODULE) { | |
478 const std::vector<const Target*>& deps = target_->deps(); | |
479 const std::set<const Target*>& inherited = target_->inherited_libraries(); | |
480 | |
481 // Now append linkable libraries to the linker command. | |
482 for (size_t i = 0; i < deps.size(); i++) { | |
483 if (deps[i]->IsLinkable() && | |
484 inherited.find(deps[i]) == inherited.end()) { | |
485 out_ << " "; | |
486 path_output_.WriteFile(out_, | |
487 helper_.GetTargetOutputFile(target_->deps()[i])); | |
488 } | |
489 } | |
490 for (std::set<const Target*>::const_iterator i = inherited.begin(); | |
491 i != inherited.end(); ++i) { | |
492 out_ << " "; | |
493 path_output_.WriteFile(out_, helper_.GetTargetOutputFile(*i)); | |
494 } | |
495 } | |
496 out_ << std::endl; | |
497 | 471 |
498 if (target_->output_type() == Target::SHARED_LIBRARY) { | 472 if (target_->output_type() == Target::SHARED_LIBRARY) { |
499 out_ << " soname = "; | 473 out_ << " soname = "; |
500 path_output_.WriteFile(out_, internal_output_file); | 474 path_output_.WriteFile(out_, internal_output_file); |
501 out_ << std::endl; | 475 out_ << std::endl; |
502 | 476 |
503 out_ << " lib = "; | 477 out_ << " lib = "; |
504 path_output_.WriteFile(out_, internal_output_file); | 478 path_output_.WriteFile(out_, internal_output_file); |
505 out_ << std::endl; | 479 out_ << std::endl; |
506 | 480 |
507 out_ << " dll = "; | 481 out_ << " dll = "; |
508 path_output_.WriteFile(out_, internal_output_file); | 482 path_output_.WriteFile(out_, internal_output_file); |
509 out_ << std::endl; | 483 out_ << std::endl; |
510 | 484 |
511 if (settings_->IsWin()) { | 485 if (settings_->IsWin()) { |
512 out_ << " implibflag = /IMPLIB:"; | 486 out_ << " implibflag = /IMPLIB:"; |
513 path_output_.WriteFile(out_, external_output_file); | 487 path_output_.WriteFile(out_, external_output_file); |
514 out_ << std::endl; | 488 out_ << std::endl; |
515 } | 489 } |
516 | 490 |
517 // TODO(brettw) postbuild steps. | 491 // TODO(brettw) postbuild steps. |
518 if (settings_->IsMac()) | 492 if (settings_->IsMac()) |
519 out_ << " postbuilds = $ && (export BUILT_PRODUCTS_DIR=/Users/brettw/prj/
src/out/gn; export CONFIGURATION=Debug; export DYLIB_INSTALL_NAME_BASE=@rpath; e
xport EXECUTABLE_NAME=libbase.dylib; export EXECUTABLE_PATH=libbase.dylib; expor
t FULL_PRODUCT_NAME=libbase.dylib; export LD_DYLIB_INSTALL_NAME=@rpath/libbase.d
ylib; export MACH_O_TYPE=mh_dylib; export PRODUCT_NAME=base; export PRODUCT_TYPE
=com.apple.product-type.library.dynamic; export SDKROOT=/Applications/Xcode.app/
Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.7.sdk; expo
rt SRCROOT=/Users/brettw/prj/src/out/gn/../../base; export SOURCE_ROOT=\"$${SRCR
OOT}\"; export TARGET_BUILD_DIR=/Users/brettw/prj/src/out/gn; export TEMP_DIR=\"
$${TMPDIR}\"; (cd ../../base && ../build/mac/strip_from_xcode); G=$$?; ((exit $$
G) || rm -rf libbase.dylib) && exit $$G)"; | 493 out_ << " postbuilds = $ && (export BUILT_PRODUCTS_DIR=/Users/brettw/prj/
src/out/gn; export CONFIGURATION=Debug; export DYLIB_INSTALL_NAME_BASE=@rpath; e
xport EXECUTABLE_NAME=libbase.dylib; export EXECUTABLE_PATH=libbase.dylib; expor
t FULL_PRODUCT_NAME=libbase.dylib; export LD_DYLIB_INSTALL_NAME=@rpath/libbase.d
ylib; export MACH_O_TYPE=mh_dylib; export PRODUCT_NAME=base; export PRODUCT_TYPE
=com.apple.product-type.library.dynamic; export SDKROOT=/Applications/Xcode.app/
Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.7.sdk; expo
rt SRCROOT=/Users/brettw/prj/src/out/gn/../../base; export SOURCE_ROOT=\"$${SRCR
OOT}\"; export TARGET_BUILD_DIR=/Users/brettw/prj/src/out/gn; export TEMP_DIR=\"
$${TMPDIR}\"; (cd ../../base && ../build/mac/strip_from_xcode); G=$$?; ((exit $$
G) || rm -rf libbase.dylib) && exit $$G)"; |
520 } | 494 } |
521 | 495 |
| 496 out_ << std::endl; |
| 497 } |
| 498 |
| 499 void NinjaTargetWriter::WriteLinkCommand( |
| 500 const OutputFile& external_output_file, |
| 501 const OutputFile& internal_output_file, |
| 502 const std::vector<OutputFile>& object_files) { |
| 503 out_ << "build "; |
| 504 path_output_.WriteFile(out_, internal_output_file); |
| 505 if (external_output_file != internal_output_file) { |
| 506 out_ << " "; |
| 507 path_output_.WriteFile(out_, external_output_file); |
| 508 } |
| 509 out_ << ": " << GetCommandForTargetType(); |
| 510 |
| 511 // Object files. |
| 512 for (size_t i = 0; i < object_files.size(); i++) { |
| 513 out_ << " "; |
| 514 path_output_.WriteFile(out_, object_files[i]); |
| 515 } |
| 516 |
| 517 // Library inputs (deps and inherited static libraries). |
| 518 // |
| 519 // Static libraries since they're just a collection of the object files so |
| 520 // don't need libraries linked with them, but we still need to go through |
| 521 // the list and find non-linkable data deps in the "deps" section. We'll |
| 522 // collect all non-linkable deps and put it in the order-only deps below. |
| 523 std::vector<const Target*> extra_data_deps; |
| 524 const std::vector<const Target*>& deps = target_->deps(); |
| 525 const std::set<const Target*>& inherited = target_->inherited_libraries(); |
| 526 for (size_t i = 0; i < deps.size(); i++) { |
| 527 if (inherited.find(deps[i]) != inherited.end()) |
| 528 continue; |
| 529 if (target_->output_type() != Target::STATIC_LIBRARY && |
| 530 deps[i]->IsLinkable()) { |
| 531 out_ << " "; |
| 532 path_output_.WriteFile(out_, helper_.GetTargetOutputFile(deps[i])); |
| 533 } else { |
| 534 extra_data_deps.push_back(deps[i]); |
| 535 } |
| 536 } |
| 537 for (std::set<const Target*>::const_iterator i = inherited.begin(); |
| 538 i != inherited.end(); ++i) { |
| 539 if (target_->output_type() == Target::STATIC_LIBRARY) { |
| 540 extra_data_deps.push_back(*i); |
| 541 } else { |
| 542 out_ << " "; |
| 543 path_output_.WriteFile(out_, helper_.GetTargetOutputFile(*i)); |
| 544 } |
| 545 } |
| 546 |
| 547 // Append data dependencies as order-only dependencies. |
| 548 const std::vector<const Target*>& datadeps = target_->datadeps(); |
| 549 const std::vector<SourceFile>& data = target_->data(); |
| 550 if (!extra_data_deps.empty() || !datadeps.empty() || !data.empty()) { |
| 551 out_ << " ||"; |
| 552 |
| 553 // Non-linkable deps in the deps section above. |
| 554 for (size_t i = 0; i < extra_data_deps.size(); i++) { |
| 555 out_ << " "; |
| 556 path_output_.WriteFile(out_, |
| 557 helper_.GetTargetOutputFile(extra_data_deps[i])); |
| 558 } |
| 559 |
| 560 // Data deps. |
| 561 for (size_t i = 0; i < datadeps.size(); i++) { |
| 562 out_ << " "; |
| 563 path_output_.WriteFile(out_, helper_.GetTargetOutputFile(datadeps[i])); |
| 564 } |
| 565 |
| 566 // Data files. |
| 567 const std::vector<SourceFile>& data = target_->data(); |
| 568 for (size_t i = 0; i < data.size(); i++) { |
| 569 out_ << " "; |
| 570 path_output_.WriteFile(out_, data[i]); |
| 571 } |
| 572 } |
522 | 573 |
523 out_ << std::endl; | 574 out_ << std::endl; |
524 } | 575 } |
525 | 576 |
526 const char* NinjaTargetWriter::GetCommandForSourceType( | 577 const char* NinjaTargetWriter::GetCommandForSourceType( |
527 SourceFileType type) const { | 578 SourceFileType type) const { |
528 if (type == SOURCE_C) | 579 if (type == SOURCE_C) |
529 return "cc"; | 580 return "cc"; |
530 if (type == SOURCE_CC) | 581 if (type == SOURCE_CC) |
531 return "cxx"; | 582 return "cxx"; |
(...skipping 26 matching lines...) Expand all Loading... |
558 // TODO(brettw) stuff about standalong static libraryes on Unix in | 609 // TODO(brettw) stuff about standalong static libraryes on Unix in |
559 // WriteTarget in the Python one, and lots of postbuild steps. | 610 // WriteTarget in the Python one, and lots of postbuild steps. |
560 return "alink"; | 611 return "alink"; |
561 } | 612 } |
562 | 613 |
563 if (target_->output_type() == Target::SHARED_LIBRARY) | 614 if (target_->output_type() == Target::SHARED_LIBRARY) |
564 return "solink"; | 615 return "solink"; |
565 | 616 |
566 return "link"; | 617 return "link"; |
567 } | 618 } |
OLD | NEW |