Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 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/xcode_writer.h" | 5 #include "tools/gn/xcode_writer.h" |
| 6 | 6 |
| 7 #include <iomanip> | 7 #include <iomanip> |
| 8 #include <map> | 8 #include <map> |
| 9 #include <memory> | 9 #include <memory> |
| 10 #include <sstream> | 10 #include <sstream> |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 25 #include "tools/gn/settings.h" | 25 #include "tools/gn/settings.h" |
| 26 #include "tools/gn/source_file.h" | 26 #include "tools/gn/source_file.h" |
| 27 #include "tools/gn/target.h" | 27 #include "tools/gn/target.h" |
| 28 #include "tools/gn/value.h" | 28 #include "tools/gn/value.h" |
| 29 #include "tools/gn/variables.h" | 29 #include "tools/gn/variables.h" |
| 30 #include "tools/gn/xcode_object.h" | 30 #include "tools/gn/xcode_object.h" |
| 31 | 31 |
| 32 namespace { | 32 namespace { |
| 33 | 33 |
| 34 using TargetToFileList = std::unordered_map<const Target*, Target::FileList>; | 34 using TargetToFileList = std::unordered_map<const Target*, Target::FileList>; |
| 35 using TargetToNativeTarget = | |
| 36 std::unordered_map<const Target*, PBXNativeTarget*>; | |
| 37 using FileToTargets = std::map<SourceFile, | |
| 38 std::vector<const Target*>, | |
| 39 bool (*)(const SourceFile&, const SourceFile&)>; | |
| 35 | 40 |
| 36 const char kEarlGreyFileNameIdentifier[] = "egtest.mm"; | 41 const char kEarlGreyFileNameIdentifier[] = "egtest.mm"; |
| 37 const char kXCTestFileNameIdentifier[] = "xctest.mm"; | 42 const char kXCTestFileNameIdentifier[] = "xctest.mm"; |
| 38 const char kXCTestModuleTargetNamePostfix[] = "_module"; | 43 const char kXCTestModuleTargetNamePostfix[] = "_module"; |
| 44 const char kXCTestFileReferenceFolder[] = "xctests/"; | |
| 39 | 45 |
| 40 struct SafeEnvironmentVariableInfo { | 46 struct SafeEnvironmentVariableInfo { |
| 41 const char* name; | 47 const char* name; |
| 42 bool capture_at_generation; | 48 bool capture_at_generation; |
| 43 }; | 49 }; |
| 44 | 50 |
| 45 SafeEnvironmentVariableInfo kSafeEnvironmentVariables[] = { | 51 SafeEnvironmentVariableInfo kSafeEnvironmentVariables[] = { |
| 46 {"HOME", true}, {"LANG", true}, {"PATH", true}, | 52 {"HOME", true}, {"LANG", true}, {"PATH", true}, |
| 47 {"USER", true}, {"TMPDIR", false}, | 53 {"USER", true}, {"TMPDIR", false}, |
| 48 }; | 54 }; |
| (...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 186 std::vector<Target::FileList>* file_lists) { | 192 std::vector<Target::FileList>* file_lists) { |
| 187 TargetToFileList xctest_files_per_target; | 193 TargetToFileList xctest_files_per_target; |
| 188 | 194 |
| 189 for (const Target* target : application_targets) { | 195 for (const Target* target : application_targets) { |
| 190 DCHECK(IsApplicationTarget(target)); | 196 DCHECK(IsApplicationTarget(target)); |
| 191 SearchXCTestFiles(target, &xctest_files_per_target); | 197 SearchXCTestFiles(target, &xctest_files_per_target); |
| 192 file_lists->push_back(xctest_files_per_target[target]); | 198 file_lists->push_back(xctest_files_per_target[target]); |
| 193 } | 199 } |
| 194 } | 200 } |
| 195 | 201 |
| 202 // Maps each xctest file to a list of xctest application targets that contains | |
| 203 // the file. | |
| 204 void MapXCTestFileToApplicationTargets( | |
| 205 const std::vector<const Target*>& xctest_application_targets, | |
| 206 const std::vector<Target::FileList>& xctest_file_lists, | |
| 207 FileToTargets* xctest_file_to_application_targets) { | |
| 208 DCHECK_EQ(xctest_application_targets.size(), xctest_file_lists.size()); | |
| 209 | |
| 210 for (size_t i = 0; i < xctest_application_targets.size(); ++i) { | |
| 211 const Target* xctest_application_target = xctest_application_targets[i]; | |
| 212 DCHECK(IsApplicationTarget(xctest_application_target)); | |
| 213 | |
| 214 for (const SourceFile& source : xctest_file_lists[i]) { | |
| 215 if (xctest_file_to_application_targets->find(source) == | |
|
sdefresne
2017/01/05 12:14:02
I think you can avoid doing the search twice by us
liaoyuke
2017/01/05 17:43:12
Done.
| |
| 216 xctest_file_to_application_targets->end()) { | |
| 217 xctest_file_to_application_targets->insert( | |
| 218 std::make_pair(source, std::vector<const Target*>())); | |
| 219 } | |
| 220 | |
| 221 (*xctest_file_to_application_targets)[source].push_back( | |
| 222 xctest_application_target); | |
| 223 } | |
| 224 } | |
| 225 } | |
| 226 | |
| 196 class CollectPBXObjectsPerClassHelper : public PBXObjectVisitor { | 227 class CollectPBXObjectsPerClassHelper : public PBXObjectVisitor { |
| 197 public: | 228 public: |
| 198 CollectPBXObjectsPerClassHelper() {} | 229 CollectPBXObjectsPerClassHelper() {} |
| 199 | 230 |
| 200 void Visit(PBXObject* object) override { | 231 void Visit(PBXObject* object) override { |
| 201 DCHECK(object); | 232 DCHECK(object); |
| 202 objects_per_class_[object->Class()].push_back(object); | 233 objects_per_class_[object->Class()].push_back(object); |
| 203 } | 234 } |
| 204 | 235 |
| 205 const std::map<PBXObjectClass, std::vector<const PBXObject*>>& | 236 const std::map<PBXObjectClass, std::vector<const PBXObject*>>& |
| (...skipping 204 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 410 std::vector<Target::FileList> xctest_file_lists; | 441 std::vector<Target::FileList> xctest_file_lists; |
| 411 FindXCTestFilesForTargets(xctest_application_targets, &xctest_file_lists); | 442 FindXCTestFilesForTargets(xctest_application_targets, &xctest_file_lists); |
| 412 DCHECK_EQ(xctest_application_targets.size(), xctest_file_lists.size()); | 443 DCHECK_EQ(xctest_application_targets.size(), xctest_file_lists.size()); |
| 413 | 444 |
| 414 std::string build_path; | 445 std::string build_path; |
| 415 std::unique_ptr<base::Environment> env(base::Environment::Create()); | 446 std::unique_ptr<base::Environment> env(base::Environment::Create()); |
| 416 | 447 |
| 417 main_project->AddAggregateTarget( | 448 main_project->AddAggregateTarget( |
| 418 "All", GetBuildScript(root_target, ninja_extra_args, env.get())); | 449 "All", GetBuildScript(root_target, ninja_extra_args, env.get())); |
| 419 | 450 |
| 451 TargetToNativeTarget xctest_application_to_module_native_target; | |
| 452 | |
| 420 for (const Target* target : targets) { | 453 for (const Target* target : targets) { |
| 421 switch (target->output_type()) { | 454 switch (target->output_type()) { |
| 422 case Target::EXECUTABLE: | 455 case Target::EXECUTABLE: |
| 423 if (target_os == XcodeWriter::WRITER_TARGET_OS_IOS) | 456 if (target_os == XcodeWriter::WRITER_TARGET_OS_IOS) |
| 424 continue; | 457 continue; |
| 425 | 458 |
| 426 main_project->AddNativeTarget( | 459 main_project->AddNativeTarget( |
| 427 target->label().name(), "compiled.mach-o.executable", | 460 target->label().name(), "compiled.mach-o.executable", |
| 428 target->output_name().empty() ? target->label().name() | 461 target->output_name().empty() ? target->label().name() |
| 429 : target->output_name(), | 462 : target->output_name(), |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 440 // discovery of tests function for XCTest, but the compilation is done | 473 // discovery of tests function for XCTest, but the compilation is done |
| 441 // via ninja and thus must prevent Xcode from linking object files via | 474 // via ninja and thus must prevent Xcode from linking object files via |
| 442 // this hack. | 475 // this hack. |
| 443 PBXAttributes extra_attributes; | 476 PBXAttributes extra_attributes; |
| 444 if (IsXCTestModuleTarget(target)) { | 477 if (IsXCTestModuleTarget(target)) { |
| 445 extra_attributes["OTHER_LDFLAGS"] = "-help"; | 478 extra_attributes["OTHER_LDFLAGS"] = "-help"; |
| 446 extra_attributes["ONLY_ACTIVE_ARCH"] = "YES"; | 479 extra_attributes["ONLY_ACTIVE_ARCH"] = "YES"; |
| 447 extra_attributes["DEBUG_INFORMATION_FORMAT"] = "dwarf"; | 480 extra_attributes["DEBUG_INFORMATION_FORMAT"] = "dwarf"; |
| 448 } | 481 } |
| 449 | 482 |
| 450 main_project->AddNativeTarget( | 483 PBXNativeTarget* native_target = main_project->AddNativeTarget( |
| 451 target->label().name(), std::string(), | 484 target->label().name(), std::string(), |
| 452 RebasePath(target->bundle_data() | 485 RebasePath(target->bundle_data() |
| 453 .GetBundleRootDirOutput(target->settings()) | 486 .GetBundleRootDirOutput(target->settings()) |
| 454 .value(), | 487 .value(), |
| 455 build_settings->build_dir()), | 488 build_settings->build_dir()), |
| 456 target->bundle_data().product_type(), | 489 target->bundle_data().product_type(), |
| 457 GetBuildScript(target->label().name(), ninja_extra_args, env.get()), | 490 GetBuildScript(target->label().name(), ninja_extra_args, env.get()), |
| 458 extra_attributes); | 491 extra_attributes); |
| 492 | |
| 493 if (!IsXCTestModuleTarget(target)) | |
| 494 continue; | |
| 495 | |
| 496 // populate |xctest_application_to_module_native_target| for XCTest | |
|
sdefresne
2017/01/05 12:14:02
s/populate/Populate/
liaoyuke
2017/01/05 17:43:12
Done.
| |
| 497 // module targets. | |
| 498 const Target* application_target = | |
| 499 FindXCTestApplicationTarget(target, xctest_application_targets); | |
| 500 xctest_application_to_module_native_target.insert( | |
| 501 std::make_pair(application_target, native_target)); | |
| 502 | |
| 459 break; | 503 break; |
| 460 } | 504 } |
| 461 | 505 |
| 462 default: | 506 default: |
| 463 break; | 507 break; |
| 464 } | 508 } |
| 465 } | 509 } |
| 466 | 510 |
| 511 FileToTargets xctest_file_to_application_targets( | |
|
sdefresne
2017/01/05 12:14:02
Please move this to be a real free function in the
liaoyuke
2017/01/05 17:43:12
Done.
| |
| 512 [](const SourceFile& lhs, const SourceFile& rhs) { | |
| 513 if (lhs.GetName() < rhs.GetName()) | |
| 514 return true; | |
| 515 else if (lhs.GetName() > rhs.GetName()) | |
| 516 return false; | |
| 517 else | |
| 518 return lhs.value() < rhs.value(); | |
| 519 }); | |
| 520 MapXCTestFileToApplicationTargets(xctest_application_targets, | |
| 521 xctest_file_lists, | |
| 522 &xctest_file_to_application_targets); | |
| 523 | |
| 524 // Add xctest files to the "Compiler Sources" of corresponding xctest native | |
| 525 // targets. | |
| 526 SourceDir source_dir("//"); | |
| 527 for (const auto& item : xctest_file_to_application_targets) { | |
| 528 const SourceFile& source = item.first; | |
| 529 for (const Target* xctest_application_target : item.second) { | |
| 530 std::string navigator_path = | |
| 531 kXCTestFileReferenceFolder + source.GetName(); | |
| 532 std::string source_path = RebasePath(source.value(), source_dir, | |
| 533 build_settings->root_path_utf8()); | |
| 534 PBXNativeTarget* xctest_module_native_target = | |
| 535 xctest_application_to_module_native_target[xctest_application_target]; | |
| 536 | |
| 537 // Test files need to be known to Xcode for proper indexing and for | |
| 538 // discovery of tests function for XCTest, but the compilation is done | |
| 539 // via ninja and thus must prevent Xcode from compiling the files by | |
| 540 // adding '-help' as per file compiler flag. | |
| 541 main_project->AddSourceFile(navigator_path, source_path, | |
| 542 CompilerFlags::HELP, | |
| 543 xctest_module_native_target); | |
| 544 } | |
| 545 } | |
| 546 | |
| 467 projects_.push_back(std::move(main_project)); | 547 projects_.push_back(std::move(main_project)); |
| 468 } | 548 } |
| 469 | 549 |
| 470 void XcodeWriter::CreateSourcesProject( | 550 void XcodeWriter::CreateSourcesProject( |
| 471 const std::vector<const Target*>& targets, | 551 const std::vector<const Target*>& targets, |
| 472 const SourceDir& root_build_dir, | 552 const SourceDir& root_build_dir, |
| 473 const PBXAttributes& attributes, | 553 const PBXAttributes& attributes, |
| 474 const std::string& source_path, | 554 const std::string& source_path, |
| 475 const std::string& absolute_source_path, | 555 const std::string& absolute_source_path, |
| 476 const std::string& config_name, | 556 const std::string& config_name, |
| (...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 573 for (auto* object : pair.second) { | 653 for (auto* object : pair.second) { |
| 574 object->Print(out, 2); | 654 object->Print(out, 2); |
| 575 } | 655 } |
| 576 out << "/* End " << ToString(pair.first) << " section */\n"; | 656 out << "/* End " << ToString(pair.first) << " section */\n"; |
| 577 } | 657 } |
| 578 | 658 |
| 579 out << "\t};\n" | 659 out << "\t};\n" |
| 580 << "\trootObject = " << project->Reference() << ";\n" | 660 << "\trootObject = " << project->Reference() << ";\n" |
| 581 << "}\n"; | 661 << "}\n"; |
| 582 } | 662 } |
| OLD | NEW |