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 |