| Index: tools/gn/xcode_writer.cc
|
| diff --git a/tools/gn/xcode_writer.cc b/tools/gn/xcode_writer.cc
|
| index 07b50e4b8a2898846e717c305145e04e9f450c3d..f243c88096e0a13db5a635711bf5e737a19226bf 100644
|
| --- a/tools/gn/xcode_writer.cc
|
| +++ b/tools/gn/xcode_writer.cc
|
| @@ -31,6 +31,12 @@
|
|
|
| namespace {
|
|
|
| +using TargetToFileList = std::unordered_map<const Target*, Target::FileList>;
|
| +
|
| +const char kEarlGreyFileNameIdentifier[] = "egtest.mm";
|
| +const char kXCTestFileNameIdentifier[] = "xctest.mm";
|
| +const char kXCTestModuleTargetNamePostfix[] = "_module";
|
| +
|
| struct SafeEnvironmentVariableInfo {
|
| const char* name;
|
| bool capture_at_generation;
|
| @@ -86,6 +92,107 @@ std::string GetBuildScript(const std::string& target_name,
|
| return script.str();
|
| }
|
|
|
| +bool IsApplicationTarget(const Target* target) {
|
| + return target->output_type() == Target::CREATE_BUNDLE &&
|
| + target->bundle_data().product_type() ==
|
| + "com.apple.product-type.application";
|
| +}
|
| +
|
| +bool IsXCTestModuleTarget(const Target* target) {
|
| + return target->output_type() == Target::CREATE_BUNDLE &&
|
| + target->bundle_data().product_type() ==
|
| + "com.apple.product-type.bundle.unit-test" &&
|
| + base::EndsWith(target->label().name(), kXCTestModuleTargetNamePostfix,
|
| + base::CompareCase::SENSITIVE);
|
| +}
|
| +
|
| +const Target* FindXCTestApplicationTarget(
|
| + const Target* xctest_module_target,
|
| + const std::vector<const Target*>& targets) {
|
| + DCHECK(IsXCTestModuleTarget(xctest_module_target));
|
| + DCHECK(base::EndsWith(xctest_module_target->label().name(),
|
| + kXCTestModuleTargetNamePostfix,
|
| + base::CompareCase::SENSITIVE));
|
| + std::string application_target_name =
|
| + xctest_module_target->label().name().substr(
|
| + 0, xctest_module_target->label().name().size() -
|
| + strlen(kXCTestModuleTargetNamePostfix));
|
| + for (const Target* target : targets) {
|
| + if (target->label().name() == application_target_name) {
|
| + return target;
|
| + }
|
| + }
|
| + NOTREACHED();
|
| + return nullptr;
|
| +}
|
| +
|
| +// Returns the corresponding application targets given XCTest module targets.
|
| +void FindXCTestApplicationTargets(
|
| + const std::vector<const Target*>& xctest_module_targets,
|
| + const std::vector<const Target*>& targets,
|
| + std::vector<const Target*>* xctest_application_targets) {
|
| + for (const Target* xctest_module_target : xctest_module_targets) {
|
| + xctest_application_targets->push_back(
|
| + FindXCTestApplicationTarget(xctest_module_target, targets));
|
| + }
|
| +}
|
| +
|
| +// Searches the list of xctest files recursively under |target|.
|
| +void SearchXCTestFiles(const Target* target,
|
| + TargetToFileList* xctest_files_per_target) {
|
| + // Early return if already visited and processed.
|
| + if (xctest_files_per_target->find(target) != xctest_files_per_target->end())
|
| + return;
|
| +
|
| + Target::FileList xctest_files;
|
| + for (const SourceFile& file : target->sources()) {
|
| + if (base::EndsWith(file.GetName(), kEarlGreyFileNameIdentifier,
|
| + base::CompareCase::SENSITIVE) ||
|
| + base::EndsWith(file.GetName(), kXCTestFileNameIdentifier,
|
| + base::CompareCase::SENSITIVE)) {
|
| + xctest_files.push_back(file);
|
| + }
|
| + }
|
| +
|
| + // Call recursively on public and private deps.
|
| + for (const auto& target : target->public_deps()) {
|
| + SearchXCTestFiles(target.ptr, xctest_files_per_target);
|
| + const Target::FileList& deps_xctest_files =
|
| + (*xctest_files_per_target)[target.ptr];
|
| + xctest_files.insert(xctest_files.end(), deps_xctest_files.begin(),
|
| + deps_xctest_files.end());
|
| + }
|
| +
|
| + for (const auto& target : target->private_deps()) {
|
| + SearchXCTestFiles(target.ptr, xctest_files_per_target);
|
| + const Target::FileList& deps_xctest_files =
|
| + (*xctest_files_per_target)[target.ptr];
|
| + xctest_files.insert(xctest_files.end(), deps_xctest_files.begin(),
|
| + deps_xctest_files.end());
|
| + }
|
| +
|
| + // Sort xctest_files to remove duplicates.
|
| + std::sort(xctest_files.begin(), xctest_files.end());
|
| + xctest_files.erase(std::unique(xctest_files.begin(), xctest_files.end()),
|
| + xctest_files.end());
|
| +
|
| + xctest_files_per_target->insert(std::make_pair(target, xctest_files));
|
| +}
|
| +
|
| +// Finds the list of xctest files recursively under each of the application
|
| +// targets.
|
| +void FindXCTestFilesForTargets(
|
| + const std::vector<const Target*>& application_targets,
|
| + std::vector<Target::FileList>* file_lists) {
|
| + TargetToFileList xctest_files_per_target;
|
| +
|
| + for (const Target* target : application_targets) {
|
| + DCHECK(IsApplicationTarget(target));
|
| + SearchXCTestFiles(target, &xctest_files_per_target);
|
| + file_lists->push_back(xctest_files_per_target[target]);
|
| + }
|
| +}
|
| +
|
| class CollectPBXObjectsPerClassHelper : public PBXObjectVisitor {
|
| public:
|
| CollectPBXObjectsPerClassHelper() {}
|
| @@ -266,6 +373,18 @@ bool XcodeWriter::FilterTargets(const BuildSettings* build_settings,
|
| return true;
|
| }
|
|
|
| +// static
|
| +void XcodeWriter::FilterXCTestModuleTargets(
|
| + const std::vector<const Target*>& targets,
|
| + std::vector<const Target*>* xctest_module_targets) {
|
| + for (const Target* target : targets) {
|
| + if (!IsXCTestModuleTarget(target))
|
| + continue;
|
| +
|
| + xctest_module_targets->push_back(target);
|
| + }
|
| +}
|
| +
|
| void XcodeWriter::CreateProductsProject(
|
| const std::vector<const Target*>& targets,
|
| const PBXAttributes& attributes,
|
| @@ -278,6 +397,20 @@ void XcodeWriter::CreateProductsProject(
|
| std::unique_ptr<PBXProject> main_project(
|
| new PBXProject("products", config_name, source_path, attributes));
|
|
|
| + // Filter xctest module and application targets and find list of xctest files
|
| + // recursively under them.
|
| + std::vector<const Target*> xctest_module_targets;
|
| + FilterXCTestModuleTargets(targets, &xctest_module_targets);
|
| +
|
| + std::vector<const Target*> xctest_application_targets;
|
| + FindXCTestApplicationTargets(xctest_module_targets, targets,
|
| + &xctest_application_targets);
|
| + DCHECK_EQ(xctest_module_targets.size(), xctest_application_targets.size());
|
| +
|
| + std::vector<Target::FileList> xctest_file_lists;
|
| + FindXCTestFilesForTargets(xctest_application_targets, &xctest_file_lists);
|
| + DCHECK_EQ(xctest_application_targets.size(), xctest_file_lists.size());
|
| +
|
| std::string build_path;
|
| std::unique_ptr<base::Environment> env(base::Environment::Create());
|
|
|
|
|