Index: tools/gn/xcode_writer.cc |
diff --git a/tools/gn/xcode_writer.cc b/tools/gn/xcode_writer.cc |
index 5030b5abbb4e9f6947f0d7e708b174cc83c709da..242f0b0ae601aaff19d1f001650815a4d613f7b1 100644 |
--- a/tools/gn/xcode_writer.cc |
+++ b/tools/gn/xcode_writer.cc |
@@ -32,10 +32,16 @@ |
namespace { |
using TargetToFileList = std::unordered_map<const Target*, Target::FileList>; |
+using TargetToNativeTarget = |
+ std::unordered_map<const Target*, PBXNativeTarget*>; |
+using FileToTargets = std::map<SourceFile, |
+ std::vector<const Target*>, |
+ bool (*)(const SourceFile&, const SourceFile&)>; |
const char kEarlGreyFileNameIdentifier[] = "egtest.mm"; |
const char kXCTestFileNameIdentifier[] = "xctest.mm"; |
const char kXCTestModuleTargetNamePostfix[] = "_module"; |
+const char kXCTestFileReferenceFolder[] = "xctests/"; |
struct SafeEnvironmentVariableInfo { |
const char* name; |
@@ -47,6 +53,15 @@ SafeEnvironmentVariableInfo kSafeEnvironmentVariables[] = { |
{"USER", true}, {"TMPDIR", false}, |
}; |
+bool CompareSourceFiles(const SourceFile& lhs, const SourceFile& rhs) { |
+ if (lhs.GetName() < rhs.GetName()) |
+ return true; |
+ else if (lhs.GetName() > rhs.GetName()) |
+ return false; |
+ else |
+ return lhs.value() < rhs.value(); |
+} |
+ |
XcodeWriter::TargetOsType GetTargetOs(const Args& args) { |
const Value* target_os_value = args.GetArgOverride(variables::kTargetOs); |
if (target_os_value) { |
@@ -193,6 +208,31 @@ void FindXCTestFilesForTargets( |
} |
} |
+// Maps each xctest file to a list of xctest application targets that contains |
+// the file. |
+void MapXCTestFileToApplicationTargets( |
+ const std::vector<const Target*>& xctest_application_targets, |
+ const std::vector<Target::FileList>& xctest_file_lists, |
+ FileToTargets* xctest_file_to_application_targets) { |
+ DCHECK_EQ(xctest_application_targets.size(), xctest_file_lists.size()); |
+ |
+ for (size_t i = 0; i < xctest_application_targets.size(); ++i) { |
+ const Target* xctest_application_target = xctest_application_targets[i]; |
+ DCHECK(IsApplicationTarget(xctest_application_target)); |
+ |
+ for (const SourceFile& source : xctest_file_lists[i]) { |
+ auto iter = xctest_file_to_application_targets->find(source); |
+ if (iter == xctest_file_to_application_targets->end()) { |
+ iter = |
+ xctest_file_to_application_targets |
+ ->insert(std::make_pair(source, std::vector<const Target*>())) |
+ .first; |
+ } |
+ iter->second.push_back(xctest_application_target); |
+ } |
+ } |
+} |
+ |
class CollectPBXObjectsPerClassHelper : public PBXObjectVisitor { |
public: |
CollectPBXObjectsPerClassHelper() {} |
@@ -417,6 +457,8 @@ void XcodeWriter::CreateProductsProject( |
main_project->AddAggregateTarget( |
"All", GetBuildScript(root_target, ninja_extra_args, env.get())); |
+ TargetToNativeTarget xctest_application_to_module_native_target; |
+ |
for (const Target* target : targets) { |
switch (target->output_type()) { |
case Target::EXECUTABLE: |
@@ -447,7 +489,7 @@ void XcodeWriter::CreateProductsProject( |
extra_attributes["DEBUG_INFORMATION_FORMAT"] = "dwarf"; |
} |
- main_project->AddNativeTarget( |
+ PBXNativeTarget* native_target = main_project->AddNativeTarget( |
target->label().name(), std::string(), |
RebasePath(target->bundle_data() |
.GetBundleRootDirOutput(target->settings()) |
@@ -456,6 +498,17 @@ void XcodeWriter::CreateProductsProject( |
target->bundle_data().product_type(), |
GetBuildScript(target->label().name(), ninja_extra_args, env.get()), |
extra_attributes); |
+ |
+ if (!IsXCTestModuleTarget(target)) |
+ continue; |
+ |
+ // Populate |xctest_application_to_module_native_target| for XCTest |
+ // module targets. |
+ const Target* application_target = |
+ FindXCTestApplicationTarget(target, xctest_application_targets); |
+ xctest_application_to_module_native_target.insert( |
+ std::make_pair(application_target, native_target)); |
+ |
break; |
} |
@@ -464,6 +517,34 @@ void XcodeWriter::CreateProductsProject( |
} |
} |
+ FileToTargets xctest_file_to_application_targets(CompareSourceFiles); |
+ MapXCTestFileToApplicationTargets(xctest_application_targets, |
+ xctest_file_lists, |
+ &xctest_file_to_application_targets); |
+ |
+ // Add xctest files to the "Compiler Sources" of corresponding xctest native |
+ // targets. |
+ SourceDir source_dir("//"); |
+ for (const auto& item : xctest_file_to_application_targets) { |
+ const SourceFile& source = item.first; |
+ for (const Target* xctest_application_target : item.second) { |
+ std::string navigator_path = |
+ kXCTestFileReferenceFolder + source.GetName(); |
+ std::string source_path = RebasePath(source.value(), source_dir, |
+ build_settings->root_path_utf8()); |
+ PBXNativeTarget* xctest_module_native_target = |
+ xctest_application_to_module_native_target[xctest_application_target]; |
+ |
+ // Test files need to be known to Xcode for proper indexing and for |
+ // discovery of tests function for XCTest, but the compilation is done |
+ // via ninja and thus must prevent Xcode from compiling the files by |
+ // adding '-help' as per file compiler flag. |
+ main_project->AddSourceFile(navigator_path, source_path, |
+ CompilerFlags::HELP, |
+ xctest_module_native_target); |
+ } |
+ } |
+ |
projects_.push_back(std::move(main_project)); |
} |