Index: tools/gn/xcode_writer.cc |
diff --git a/tools/gn/xcode_writer.cc b/tools/gn/xcode_writer.cc |
index 6e5042865aa1dc746382e68c191f76d33edb9dd1..0e3dfda5f11c16a76d6637323d879e077f0fd5ae 100644 |
--- a/tools/gn/xcode_writer.cc |
+++ b/tools/gn/xcode_writer.cc |
@@ -31,6 +31,11 @@ |
namespace { |
+const char kXCTestTargetNamePostfix[] = "_module"; |
+const char kEarlGreyFileNameIdentifier[] = "egtest.mm"; |
+ |
+typedef std::unordered_map<const Target*, Target::FileList> TargetToFileList; |
sdefresne
2016/12/14 13:00:03
nit: it is recommend to use "using" instead of "ty
liaoyuke
2016/12/15 00:03:11
Done.
|
+ |
struct SafeEnvironmentVariableInfo { |
const char* name; |
bool capture_at_generation; |
@@ -87,6 +92,92 @@ std::string GetBuildScript(const std::string& target_name, |
return script.str(); |
} |
+// Append |file_list_extra| to |file_list_base| and remove duplicate elements. |
+void AppendAndRemoveDuplicates(Target::FileList* file_list_base, |
+ const Target::FileList& file_list_extra) { |
+ file_list_base->insert(file_list_base->end(), file_list_extra.begin(), |
+ file_list_extra.end()); |
+ std::sort(file_list_base->begin(), file_list_base->end()); |
+ file_list_base->erase( |
+ std::unique(file_list_base->begin(), file_list_base->end()), |
+ file_list_base->end()); |
+} |
+ |
+// Find the list of earl grey files recursively under |target|. |
+void GetEarlGreyFiles(const Target* target, |
+ TargetToFileList* eg_files_per_target) { |
+ // Early return if already visited and processed. |
+ if (eg_files_per_target->find(target) != eg_files_per_target->end()) { |
sdefresne
2016/12/14 13:00:03
No braces here (since there are not used in the re
liaoyuke
2016/12/15 00:03:11
Done.
|
+ return; |
+ } |
+ |
+ Target::FileList eg_files; |
+ for (const SourceFile& file : target->sources()) { |
+ if (base::EndsWith(file.GetName(), kEarlGreyFileNameIdentifier, |
+ base::CompareCase::SENSITIVE)) { |
+ eg_files.push_back(file); |
+ } |
+ } |
+ |
+ // Call recursively on public and private deps. |
+ for (const auto& target : target->public_deps()) { |
+ GetEarlGreyFiles(target.ptr, eg_files_per_target); |
+ Target::FileList deps_eg_files = eg_files_per_target->at(target.ptr); |
+ if (!deps_eg_files.empty()) { |
sdefresne
2016/12/14 13:00:02
No braces here.
liaoyuke
2016/12/15 00:03:11
Done.
|
+ AppendAndRemoveDuplicates(&eg_files, deps_eg_files); |
sdefresne
2016/12/14 13:00:03
I think it would be better to just add everything
liaoyuke
2016/12/15 00:03:11
Done.
|
+ } |
+ } |
+ |
+ for (const auto& target : target->private_deps()) { |
+ GetEarlGreyFiles(target.ptr, eg_files_per_target); |
+ Target::FileList deps_eg_files = eg_files_per_target->at(target.ptr); |
+ if (!deps_eg_files.empty()) { |
+ AppendAndRemoveDuplicates(&eg_files, deps_eg_files); |
+ } |
+ } |
+ |
+ // Sort eg_files to remove duplicates. |
+ std::sort(eg_files.begin(), eg_files.end()); |
+ eg_files.erase(std::unique(eg_files.begin(), eg_files.end()), eg_files.end()); |
+ |
+ eg_files_per_target->insert(std::make_pair(target, eg_files)); |
+} |
+ |
+// Find the list of earl grey files recursively under each of the application |
sdefresne
2016/12/14 13:00:02
nit: Find -> Finds
liaoyuke
2016/12/15 00:03:11
Done.
|
+// and xctest bundle pair. |
+void GetEarlGreyFilesForAll( |
sdefresne
2016/12/14 13:00:02
I'm not sure we need to check source file in xctes
liaoyuke
2016/12/15 00:03:11
You are right, I have double-checked, there is no
|
+ const std::vector<const Target*>& xctest_targets, |
+ const std::vector<const Target*>& application_targets, |
+ std::vector<Target::FileList>* file_lists) { |
sdefresne
2016/12/14 13:00:03
DCHECK_EQ(xctest_targets.size(), application_targe
liaoyuke
2016/12/15 00:03:11
Acknowledged.
|
+ TargetToFileList eg_files_per_target; |
+ |
+ for (size_t i = 0; i < xctest_targets.size(); ++i) { |
+ GetEarlGreyFiles(xctest_targets[i], &eg_files_per_target); |
+ GetEarlGreyFiles(application_targets[i], &eg_files_per_target); |
+ |
+ Target::FileList eg_files; |
+ AppendAndRemoveDuplicates(&eg_files, |
+ eg_files_per_target.at(xctest_targets[i])); |
+ AppendAndRemoveDuplicates(&eg_files, |
+ eg_files_per_target.at(application_targets[i])); |
+ file_lists->push_back(eg_files); |
+ } |
+} |
+ |
+// Returns the corresponding application target given a XCTest target. Returns |
sdefresne
2016/12/14 13:00:03
I would change this function to DCHECK if it does
liaoyuke
2016/12/15 00:03:11
Thank you for the note. I will this logic when I w
liaoyuke
2016/12/15 00:03:11
Acknowledged.
|
+// NULL if not found. |
+const Target* FindApplicationTarget(const Target* xctest_target, |
+ const std::vector<const Target*>& targets) { |
+ for (const Target* target : targets) { |
+ if ((target->label().name() + kXCTestTargetNamePostfix) |
+ .compare(xctest_target->label().name()) == 0) { |
+ return target; |
+ } |
+ } |
+ |
+ return NULL; |
+} |
+ |
class CollectPBXObjectsPerClassHelper : public PBXObjectVisitor { |
public: |
CollectPBXObjectsPerClassHelper() {} |
@@ -267,6 +358,27 @@ bool XcodeWriter::FilterTargets(const BuildSettings* build_settings, |
return true; |
} |
+// static |
+void XcodeWriter::FilterXCTestTargets( |
+ const std::vector<const Target*>& targets, |
+ std::vector<const Target*>* xctest_targets, |
+ std::vector<const Target*>* application_targets) { |
+ // Filter out all targets of type CREATE_BUNDLE and whose bundle_data has |
+ // product_type: "com.apple.product-type.bundle.unit-test". |
+ for (const Target* target : targets) { |
+ if (target->output_type() != Target::CREATE_BUNDLE) { |
sdefresne
2016/12/14 13:00:02
nit: I would use an helper method IsXCTestTarget h
|
+ continue; |
+ } |
+ if (target->bundle_data().product_type().compare( |
+ "com.apple.product-type.bundle.unit-test") == 0) { |
+ xctest_targets->push_back(target); |
+ const Target* application_target = FindApplicationTarget(target, targets); |
+ DCHECK(application_target); |
+ application_targets->push_back(application_target); |
+ } |
+ } |
+} |
+ |
void XcodeWriter::CreateProductsProject( |
const std::vector<const Target*>& targets, |
const PBXAttributes& attributes, |
@@ -279,6 +391,16 @@ void XcodeWriter::CreateProductsProject( |
std::unique_ptr<PBXProject> main_project( |
new PBXProject("products", config_name, source_path, attributes)); |
+ // Filter XCTest targets and their corresponding application targets and find |
+ // list of earl grey test files recursively under the pairs. |
+ std::vector<const Target*> xctest_targets; |
+ std::vector<const Target*> application_targets; |
+ std::vector<Target::FileList> earl_grey_file_lists; |
+ XcodeWriter::FilterXCTestTargets(targets, &xctest_targets, |
+ &application_targets); |
+ GetEarlGreyFilesForAll(xctest_targets, application_targets, |
+ &earl_grey_file_lists); |
+ |
std::string build_path; |
std::unique_ptr<base::Environment> env(base::Environment::Create()); |