Chromium Code Reviews| 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/gyp_binary_target_writer.h" | 5 #include "tools/gn/gyp_binary_target_writer.h" |
| 6 | 6 |
| 7 #include <set> | 7 #include <set> |
| 8 | 8 |
| 9 #include "base/logging.h" | 9 #include "base/logging.h" |
| 10 #include "base/strings/string_util.h" | 10 #include "base/strings/string_util.h" |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 86 // The arch was passed as one GN string value, e.g. "-arch i386". Return | 86 // The arch was passed as one GN string value, e.g. "-arch i386". Return |
| 87 // the stuff following the space and delete the item. | 87 // the stuff following the space and delete the item. |
| 88 std::string ret = cur.substr(6); | 88 std::string ret = cur.substr(6); |
| 89 cflags->erase(cflags->begin() + i); | 89 cflags->erase(cflags->begin() + i); |
| 90 return ret; | 90 return ret; |
| 91 } | 91 } |
| 92 } | 92 } |
| 93 return std::string(); | 93 return std::string(); |
| 94 } | 94 } |
| 95 | 95 |
| 96 // Searches for -miphoneos-version-min, returns the resulting value, and | |
| 97 // removes it from the list. Returns the empty string if it's not found. | |
| 98 std::string GetIPhoneVersionMin(std::vector<std::string>* cflags) { | |
| 99 // Searches for the "-arch" option and returns the corresponding GYP value. | |
| 100 const char prefix[] = "-miphoneos-version-min="; | |
| 101 for (size_t i = 0; i < cflags->size(); i++) { | |
| 102 const std::string& cur = (*cflags)[i]; | |
| 103 if (StartsWithASCII(cur, prefix, true)) { | |
| 104 std::string result = cur.substr(arraysize(prefix) - 1); | |
| 105 cflags->erase(cflags->begin() + i); | |
| 106 return result; | |
| 107 } | |
| 108 } | |
| 109 return std::string(); | |
| 110 } | |
| 111 | |
| 96 // Finds all values from the given getter from all configs in the given list, | 112 // Finds all values from the given getter from all configs in the given list, |
| 97 // and adds them to the given result vector. | 113 // and adds them to the given result vector. |
| 98 template<typename T> | 114 template<typename T> |
| 99 void FillConfigListValues( | 115 void FillConfigListValues( |
| 100 const LabelConfigVector& configs, | 116 const LabelConfigVector& configs, |
| 101 const std::vector<T>& (ConfigValues::* getter)() const, | 117 const std::vector<T>& (ConfigValues::* getter)() const, |
| 102 std::vector<T>* result) { | 118 std::vector<T>* result) { |
| 103 for (size_t config_i = 0; config_i < configs.size(); config_i++) { | 119 for (size_t config_i = 0; config_i < configs.size(); config_i++) { |
| 104 const std::vector<T>& values = | 120 const std::vector<T>& values = |
| 105 (configs[config_i].ptr->config_values().*getter)(); | 121 (configs[config_i].ptr->config_values().*getter)(); |
| 106 for (size_t val_i = 0; val_i < values.size(); val_i++) | 122 for (size_t val_i = 0; val_i < values.size(); val_i++) |
| 107 result->push_back(values[val_i]); | 123 result->push_back(values[val_i]); |
| 108 } | 124 } |
| 109 } | 125 } |
| 110 | 126 |
| 127 bool IsClang(const Target* target) { | |
| 128 const Value* is_clang = | |
| 129 target->settings()->base_config()->GetValue("is_clang"); | |
| 130 return is_clang && is_clang->type() == Value::BOOLEAN && | |
| 131 is_clang->boolean_value(); | |
| 132 } | |
| 133 | |
| 134 bool IsIOS(const Target* target) { | |
| 135 const Value* is_ios = target->settings()->base_config()->GetValue("is_ios"); | |
| 136 return is_ios && is_ios->type() == Value::BOOLEAN && is_ios->boolean_value(); | |
| 137 } | |
| 138 | |
| 139 // Returns true if the current target is an iOS simulator build. | |
| 140 bool IsIOSSimulator(const std::vector<std::string>& cflags) { | |
| 141 // Search for the sysroot flag. We expect one flag to be the | |
| 142 // switch, and the following one to be the value. | |
|
Nico
2014/02/05 04:19:35
I think both -isysroot foo and -isysroot=foo might
| |
| 143 const char sysroot[] = "-isysroot"; | |
| 144 for (size_t i = 0; i < cflags.size(); i++) { | |
| 145 const std::string& cur = cflags[i]; | |
| 146 if (cur == sysroot) { | |
| 147 if (i == cflags.size() - 1) | |
| 148 return false; // No following value. | |
| 149 | |
| 150 // The argument is a file path, we check the prefix of the file name. | |
| 151 base::FilePath path(UTF8ToFilePath(cflags[i + 1])); | |
| 152 std::string path_file_part = FilePathToUTF8(path.BaseName()); | |
| 153 return StartsWithASCII(path_file_part, "iphonesimulator", false); | |
| 154 } | |
| 155 } | |
| 156 return false; | |
| 157 } | |
| 158 | |
| 111 } // namespace | 159 } // namespace |
| 112 | 160 |
| 113 GypBinaryTargetWriter::Flags::Flags() {} | 161 GypBinaryTargetWriter::Flags::Flags() {} |
| 114 GypBinaryTargetWriter::Flags::~Flags() {} | 162 GypBinaryTargetWriter::Flags::~Flags() {} |
| 115 | 163 |
| 116 GypBinaryTargetWriter::GypBinaryTargetWriter(const TargetGroup& group, | 164 GypBinaryTargetWriter::GypBinaryTargetWriter(const TargetGroup& group, |
| 117 const Toolchain* debug_toolchain, | 165 const Toolchain* debug_toolchain, |
| 118 const SourceDir& gyp_dir, | 166 const SourceDir& gyp_dir, |
| 119 std::ostream& out) | 167 std::ostream& out) |
| 120 : GypTargetWriter(group.get()->item()->AsTarget(), debug_toolchain, | 168 : GypTargetWriter(group.get()->item()->AsTarget(), debug_toolchain, |
| (...skipping 254 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 375 indent + kExtraIndent * 2); | 423 indent + kExtraIndent * 2); |
| 376 | 424 |
| 377 // ...LD flags. | 425 // ...LD flags. |
| 378 // TODO(brettw) EnableUAC defaults to on and needs to be set. Also | 426 // TODO(brettw) EnableUAC defaults to on and needs to be set. Also |
| 379 // UACExecutionLevel and UACUIAccess depends on that and defaults to 0/false. | 427 // UACExecutionLevel and UACUIAccess depends on that and defaults to 0/false. |
| 380 WriteNamedArray("AdditionalOptions", flags.ldflags, 14); | 428 WriteNamedArray("AdditionalOptions", flags.ldflags, 14); |
| 381 Indent(indent + kExtraIndent) << "},\n"; | 429 Indent(indent + kExtraIndent) << "},\n"; |
| 382 Indent(indent) << "},\n"; | 430 Indent(indent) << "},\n"; |
| 383 } | 431 } |
| 384 | 432 |
| 385 void GypBinaryTargetWriter::WriteMacFlags(Flags& flags, int indent) { | 433 void GypBinaryTargetWriter::WriteMacFlags(const Target* target, |
| 434 Flags& flags, | |
| 435 int indent) { | |
| 386 WriteNamedArray("defines", flags.defines, indent); | 436 WriteNamedArray("defines", flags.defines, indent); |
| 387 WriteIncludeDirs(flags, indent); | 437 WriteIncludeDirs(flags, indent); |
| 388 | 438 |
| 389 // Libraries and library directories. | 439 // Libraries and library directories. |
| 390 EscapeOptions escape_options; | 440 EscapeOptions escape_options; |
| 391 escape_options.mode = ESCAPE_JSON; | 441 escape_options.mode = ESCAPE_JSON; |
| 392 if (!flags.lib_dirs.empty()) { | 442 if (!flags.lib_dirs.empty()) { |
| 393 Indent(indent + kExtraIndent) << "'library_dirs': ["; | 443 Indent(indent + kExtraIndent) << "'library_dirs': ["; |
| 394 for (size_t i = 0; i < flags.lib_dirs.size(); i++) { | 444 for (size_t i = 0; i < flags.lib_dirs.size(); i++) { |
| 395 out_ << " '"; | 445 out_ << " '"; |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 407 out_ << " '-l"; | 457 out_ << " '-l"; |
| 408 EscapeStringToStream(out_, flags.libs[i], escape_options); | 458 EscapeStringToStream(out_, flags.libs[i], escape_options); |
| 409 out_ << "',"; | 459 out_ << "',"; |
| 410 } | 460 } |
| 411 out_ << " ],\n"; | 461 out_ << " ],\n"; |
| 412 Indent(indent) << "},\n"; | 462 Indent(indent) << "},\n"; |
| 413 } | 463 } |
| 414 | 464 |
| 415 Indent(indent) << "'xcode_settings': {\n"; | 465 Indent(indent) << "'xcode_settings': {\n"; |
| 416 | 466 |
| 417 // Architecture. GYP uses this to write the -arch flag passed to the | 467 // Architecture. GYP reads this value and uses it to generate the -arch |
| 418 // compiler, it doesn't look at our -arch flag. So we need to specify it in | 468 // flag, so we always want to remove it from the cflags (which is a side |
| 419 // this special var and not in the cflags to avoid duplicates or conflicts. | 469 // effect of what GetMacArch does), even in cases where we don't use the |
| 470 // value (in the iOS arm below). | |
| 420 std::string arch = GetMacArch(&flags.cflags); | 471 std::string arch = GetMacArch(&flags.cflags); |
| 421 if (arch == "i386") | 472 if (IsIOS(target)) { |
| 422 Indent(indent + kExtraIndent) << "'ARCHS': [ 'i386' ],\n"; | 473 // When writing an iOS "target" (not host) target, we set VALID_ARCHS |
| 423 else if (arch == "x86_64") | 474 // instead of ARCHS and always use this hardcoded value. This matches the |
| 424 Indent(indent + kExtraIndent) << "'ARCHS': [ 'x86_64' ],\n"; | 475 // GYP build. |
| 476 Indent(indent + kExtraIndent) << "'VALID_ARCHS': 'armv7 i386',\n"; | |
| 477 | |
| 478 // Tell XCode to target both iPhone and iPad. GN has no such concept. | |
| 479 Indent(indent + kExtraIndent) << "'TARGETED_DEVICE_FAMILY': '1,2',\n"; | |
|
Nico
2014/02/05 04:19:35
Hm, hardcoding this stuff in the gn binary seems s
brettw
2014/02/05 04:29:30
Yeah. Is there a command line option this maps to?
Nico
2014/02/05 04:55:27
I think this is written into the UIDeviceFamily pl
| |
| 480 | |
| 481 if (IsIOSSimulator(flags.cflags)) { | |
| 482 Indent(indent + kExtraIndent) << "'SDKROOT': 'iphonesimulator',\n"; | |
| 483 } else { | |
| 484 Indent(indent + kExtraIndent) << "'SDKROOT': 'iphoneos',\n"; | |
| 485 std::string min_ver = GetIPhoneVersionMin(&flags.cflags); | |
| 486 if (!min_ver.empty()) | |
| 487 Indent(indent + kExtraIndent) << "'IPHONEOS_DEPLOYMENT_TARGET': '',\n"; | |
| 488 } | |
| 489 } else { | |
| 490 // When doing regular Mac and "host" iOS (which look like regular Mac) | |
| 491 // builds, we can set the ARCHS value to what's specified in the build. | |
| 492 if (arch == "i386") | |
| 493 Indent(indent + kExtraIndent) << "'ARCHS': [ 'i386' ],\n"; | |
| 494 else if (arch == "x86_64") | |
| 495 Indent(indent + kExtraIndent) << "'ARCHS': [ 'x86_64' ],\n"; | |
|
Nico
2014/02/05 04:19:36
remoting sets ARCHS to both i386, x86_64 I think (
brettw
2014/02/05 04:29:30
Okay, we'll have to deal with that when it comes u
Nico
2014/02/05 04:55:27
The commit message on how this is done in gyp/ninj
brettw
2014/02/05 06:18:53
I *think* the way to do this in GN would be to jus
| |
| 496 } | |
| 425 | 497 |
| 426 // C/C++ flags. | 498 // C/C++ flags. |
| 427 if (!flags.cflags.empty() || !flags.cflags_c.empty() || | 499 if (!flags.cflags.empty() || !flags.cflags_c.empty() || |
| 428 !flags.cflags_objc.empty()) { | 500 !flags.cflags_objc.empty()) { |
| 429 Indent(indent + kExtraIndent) << "'OTHER_CFLAGS': ["; | 501 Indent(indent + kExtraIndent) << "'OTHER_CFLAGS': ["; |
| 430 WriteArrayValues(out_, flags.cflags); | 502 WriteArrayValues(out_, flags.cflags); |
| 431 WriteArrayValues(out_, flags.cflags_c); | 503 WriteArrayValues(out_, flags.cflags_c); |
| 432 WriteArrayValues(out_, flags.cflags_objc); | 504 WriteArrayValues(out_, flags.cflags_objc); |
| 433 out_ << " ],\n"; | 505 out_ << " ],\n"; |
| 434 } | 506 } |
| 435 if (!flags.cflags.empty() || !flags.cflags_cc.empty() || | 507 if (!flags.cflags.empty() || !flags.cflags_cc.empty() || |
| 436 !flags.cflags_objcc.empty()) { | 508 !flags.cflags_objcc.empty()) { |
| 437 Indent(indent + kExtraIndent) << "'OTHER_CPLUSPLUSFLAGS': ["; | 509 Indent(indent + kExtraIndent) << "'OTHER_CPLUSPLUSFLAGS': ["; |
| 438 WriteArrayValues(out_, flags.cflags); | 510 WriteArrayValues(out_, flags.cflags); |
| 439 WriteArrayValues(out_, flags.cflags_cc); | 511 WriteArrayValues(out_, flags.cflags_cc); |
| 440 WriteArrayValues(out_, flags.cflags_objcc); | 512 WriteArrayValues(out_, flags.cflags_objcc); |
| 441 out_ << " ],\n"; | 513 out_ << " ],\n"; |
| 442 } | 514 } |
| 443 | 515 |
| 444 // Ld flags. Don't write these for static libraries. Otherwise, they'll be | 516 // Ld flags. Don't write these for static libraries. Otherwise, they'll be |
| 445 // passed to the library tool which doesn't expect it (the toolchain does | 517 // passed to the library tool which doesn't expect it (the toolchain does |
| 446 // not use ldflags so these are ignored in the normal build). | 518 // not use ldflags so these are ignored in the normal build). |
| 447 if (target_->output_type() != Target::STATIC_LIBRARY) | 519 if (target->output_type() != Target::STATIC_LIBRARY) |
| 448 WriteNamedArray("OTHER_LDFLAGS", flags.ldflags, indent + kExtraIndent); | 520 WriteNamedArray("OTHER_LDFLAGS", flags.ldflags, indent + kExtraIndent); |
| 449 | 521 |
| 450 // Write the compiler that XCode should use. When we're using clang, we want | 522 // Write the compiler that XCode should use. When we're using clang, we want |
| 451 // the custom one, otherwise don't add this and the default compiler will be | 523 // the custom one, otherwise don't add this and the default compiler will be |
| 452 // used. | 524 // used. |
| 453 // | 525 // |
| 454 // TODO(brettw) this is a hack. We could add a way for the GN build to set | 526 // TODO(brettw) this is a hack. We could add a way for the GN build to set |
| 455 // these values but as far as I can see this is the only use for them, so | 527 // these values but as far as I can see this is the only use for them, so |
| 456 // currently we manually check the build config's is_clang value. | 528 // currently we manually check the build config's is_clang value. |
| 457 const Value* is_clang = | 529 if (IsClang(target)) { |
| 458 target_->settings()->base_config()->GetValue("is_clang"); | |
| 459 if (is_clang && is_clang->type() == Value::BOOLEAN && | |
| 460 is_clang->boolean_value()) { | |
| 461 base::FilePath clang_path = | 530 base::FilePath clang_path = |
| 462 target_->settings()->build_settings()->GetFullPath(SourceFile( | 531 target_->settings()->build_settings()->GetFullPath(SourceFile( |
| 463 "//third_party/llvm-build/Release+Asserts/bin/clang")); | 532 "//third_party/llvm-build/Release+Asserts/bin/clang")); |
| 464 base::FilePath clang_pp_path = | 533 base::FilePath clang_pp_path = |
| 465 target_->settings()->build_settings()->GetFullPath(SourceFile( | 534 target_->settings()->build_settings()->GetFullPath(SourceFile( |
| 466 "//third_party/llvm-build/Release+Asserts/bin/clang++")); | 535 "//third_party/llvm-build/Release+Asserts/bin/clang++")); |
| 467 | 536 |
| 468 Indent(indent + kExtraIndent) | 537 Indent(indent + kExtraIndent) |
| 469 << "'CC': '" << FilePathToUTF8(clang_path) << "',\n"; | 538 << "'CC': '" << FilePathToUTF8(clang_path) << "',\n"; |
| 470 Indent(indent + kExtraIndent) | 539 Indent(indent + kExtraIndent) |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 526 if (host) { | 595 if (host) { |
| 527 // Write out the first part of the conditional. | 596 // Write out the first part of the conditional. |
| 528 Indent(indent) << kToolsetTargetCondition; | 597 Indent(indent) << kToolsetTargetCondition; |
| 529 extra_indent = kExtraIndent; | 598 extra_indent = kExtraIndent; |
| 530 } | 599 } |
| 531 | 600 |
| 532 // Always write the target flags (may or may not be inside a target | 601 // Always write the target flags (may or may not be inside a target |
| 533 // conditional). | 602 // conditional). |
| 534 { | 603 { |
| 535 Flags flags(FlagsFromTarget(target->item()->AsTarget())); | 604 Flags flags(FlagsFromTarget(target->item()->AsTarget())); |
| 536 WriteMacFlags(flags, indent + extra_indent); | 605 WriteMacFlags(target->item()->AsTarget(), flags, indent + extra_indent); |
| 537 } | 606 } |
| 538 | 607 |
| 539 // Now optionally write the host conditional arm. | 608 // Now optionally write the host conditional arm. |
| 540 if (host) { | 609 if (host) { |
| 541 Indent(indent) << kToolsetTargetElse; | 610 Indent(indent) << kToolsetTargetElse; |
| 542 Flags flags(FlagsFromTarget(host->item()->AsTarget())); | 611 Flags flags(FlagsFromTarget(host->item()->AsTarget())); |
| 543 WriteMacFlags(flags, indent + kExtraIndent); | 612 WriteMacFlags(host->item()->AsTarget(), flags, indent + kExtraIndent); |
| 544 Indent(indent) << kToolsetTargetEnd; | 613 Indent(indent) << kToolsetTargetEnd; |
| 545 } | 614 } |
| 546 } | 615 } |
| 547 | 616 |
| 548 void GypBinaryTargetWriter::WriteSources(const Target* target, int indent) { | 617 void GypBinaryTargetWriter::WriteSources(const Target* target, int indent) { |
| 549 Indent(indent) << "'sources': [\n"; | 618 Indent(indent) << "'sources': [\n"; |
| 550 | 619 |
| 551 const Target::FileList& sources = target->sources(); | 620 const Target::FileList& sources = target->sources(); |
| 552 for (size_t i = 0; i < sources.size(); i++) { | 621 for (size_t i = 0; i < sources.size(); i++) { |
| 553 const SourceFile& input_file = sources[i]; | 622 const SourceFile& input_file = sources[i]; |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 598 if (target_->direct_dependent_configs().empty()) | 667 if (target_->direct_dependent_configs().empty()) |
| 599 return; | 668 return; |
| 600 Indent(indent) << "'direct_dependent_settings': {\n"; | 669 Indent(indent) << "'direct_dependent_settings': {\n"; |
| 601 | 670 |
| 602 Flags flags(FlagsFromConfigList(target_->direct_dependent_configs())); | 671 Flags flags(FlagsFromConfigList(target_->direct_dependent_configs())); |
| 603 if (target_->settings()->IsLinux()) | 672 if (target_->settings()->IsLinux()) |
| 604 WriteLinuxFlags(flags, indent + kExtraIndent); | 673 WriteLinuxFlags(flags, indent + kExtraIndent); |
| 605 else if (target_->settings()->IsWin()) | 674 else if (target_->settings()->IsWin()) |
| 606 WriteVCFlags(flags, indent + kExtraIndent); | 675 WriteVCFlags(flags, indent + kExtraIndent); |
| 607 else if (target_->settings()->IsMac()) | 676 else if (target_->settings()->IsMac()) |
| 608 WriteMacFlags(flags, indent + kExtraIndent); | 677 WriteMacFlags(target_, flags, indent + kExtraIndent); |
| 609 Indent(indent) << "},\n"; | 678 Indent(indent) << "},\n"; |
| 610 } | 679 } |
| 611 | 680 |
| 612 void GypBinaryTargetWriter::WriteAllDependentSettings(int indent) { | 681 void GypBinaryTargetWriter::WriteAllDependentSettings(int indent) { |
| 613 if (target_->all_dependent_configs().empty()) | 682 if (target_->all_dependent_configs().empty()) |
| 614 return; | 683 return; |
| 615 Indent(indent) << "'all_dependent_settings': {\n"; | 684 Indent(indent) << "'all_dependent_settings': {\n"; |
| 616 | 685 |
| 617 Flags flags(FlagsFromConfigList(target_->all_dependent_configs())); | 686 Flags flags(FlagsFromConfigList(target_->all_dependent_configs())); |
| 618 if (target_->settings()->IsLinux()) | 687 if (target_->settings()->IsLinux()) |
| 619 WriteLinuxFlags(flags, indent + kExtraIndent); | 688 WriteLinuxFlags(flags, indent + kExtraIndent); |
| 620 else if (target_->settings()->IsWin()) | 689 else if (target_->settings()->IsWin()) |
| 621 WriteVCFlags(flags, indent + kExtraIndent); | 690 WriteVCFlags(flags, indent + kExtraIndent); |
| 622 else if (target_->settings()->IsMac()) | 691 else if (target_->settings()->IsMac()) |
| 623 WriteMacFlags(flags, indent + kExtraIndent); | 692 WriteMacFlags(target_, flags, indent + kExtraIndent); |
| 624 Indent(indent) << "},\n"; | 693 Indent(indent) << "},\n"; |
| 625 } | 694 } |
| 626 | 695 |
| 627 GypBinaryTargetWriter::Flags GypBinaryTargetWriter::FlagsFromTarget( | 696 GypBinaryTargetWriter::Flags GypBinaryTargetWriter::FlagsFromTarget( |
| 628 const Target* target) const { | 697 const Target* target) const { |
| 629 Flags ret; | 698 Flags ret; |
| 630 | 699 |
| 631 // Extracts a vector of the given type and name from the config values. | 700 // Extracts a vector of the given type and name from the config values. |
| 632 #define EXTRACT(type, name) \ | 701 #define EXTRACT(type, name) \ |
| 633 { \ | 702 { \ |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 689 return; | 758 return; |
| 690 | 759 |
| 691 EscapeOptions options; | 760 EscapeOptions options; |
| 692 options.mode = ESCAPE_JSON; | 761 options.mode = ESCAPE_JSON; |
| 693 | 762 |
| 694 Indent(indent) << "'" << name << "': ["; | 763 Indent(indent) << "'" << name << "': ["; |
| 695 WriteArrayValues(out_, values); | 764 WriteArrayValues(out_, values); |
| 696 out_ << " ],\n"; | 765 out_ << " ],\n"; |
| 697 } | 766 } |
| 698 | 767 |
| OLD | NEW |