Commit 4ce240b3 authored by liaoyuke's avatar liaoyuke Committed by Commit bot

Associate xctest files with corresponding xctest targets.

Previously, our generated Xcode project has the issue that Xcode couldn't find
our xctests. And to fix it, one must find the list of xctest files under each of
the application targets and then associate them with the corresponding xctest
target.

This CL associates xctest files with xctest targets and because our compilation
is done via ninja, it also adds '-help' as per file compiler flags to each
xctest file reference to prevent Xcode from trying to compile the xctest files.

BUG=614818

Review-Url: https://codereview.chromium.org/2616773003
Cr-Commit-Position: refs/heads/master@{#442120}
parent c725a146
......@@ -487,6 +487,19 @@ PBXFileReference* PBXGroup::AddSourceFile(const std::string& navigator_path,
DCHECK(!source_path.empty());
std::string::size_type sep = navigator_path.find("/");
if (sep == std::string::npos) {
// Prevent same file reference being created and added multiple times.
for (const auto& child : children_) {
if (child->Class() != PBXFileReferenceClass)
continue;
PBXFileReference* child_as_file_reference =
static_cast<PBXFileReference*>(child.get());
if (child_as_file_reference->Name() == navigator_path &&
child_as_file_reference->path() == source_path) {
return child_as_file_reference;
}
}
children_.push_back(base::MakeUnique<PBXFileReference>(
navigator_path, source_path, std::string()));
return static_cast<PBXFileReference*>(children_.back().get());
......@@ -675,12 +688,13 @@ void PBXProject::AddIndexingTarget() {
target_for_indexing_ = static_cast<PBXNativeTarget*>(targets_.back().get());
}
void PBXProject::AddNativeTarget(const std::string& name,
const std::string& type,
const std::string& output_name,
const std::string& output_type,
const std::string& shell_script,
const PBXAttributes& extra_attributes) {
PBXNativeTarget* PBXProject::AddNativeTarget(
const std::string& name,
const std::string& type,
const std::string& output_name,
const std::string& output_type,
const std::string& shell_script,
const PBXAttributes& extra_attributes) {
base::StringPiece ext = FindExtension(&output_name);
PBXFileReference* product = static_cast<PBXFileReference*>(
products_->AddChild(base::MakeUnique<PBXFileReference>(
......@@ -700,6 +714,7 @@ void PBXProject::AddNativeTarget(const std::string& name,
targets_.push_back(base::MakeUnique<PBXNativeTarget>(
name, shell_script, config_name_, attributes, output_type, product_name,
product));
return static_cast<PBXNativeTarget*>(targets_.back().get());
}
void PBXProject::SetProjectDirPath(const std::string& project_dir_path) {
......
......@@ -190,6 +190,8 @@ class PBXFileReference : public PBXObject {
std::string Name() const override;
void Print(std::ostream& out, unsigned indent) const override;
const std::string& path() const { return path_; }
private:
std::string name_;
std::string path_;
......@@ -293,12 +295,13 @@ class PBXProject : public PBXObject {
void AddAggregateTarget(const std::string& name,
const std::string& shell_script);
void AddIndexingTarget();
void AddNativeTarget(const std::string& name,
const std::string& type,
const std::string& output_name,
const std::string& output_type,
const std::string& shell_script,
const PBXAttributes& extra_attributes = PBXAttributes());
PBXNativeTarget* AddNativeTarget(
const std::string& name,
const std::string& type,
const std::string& output_name,
const std::string& output_type,
const std::string& shell_script,
const PBXAttributes& extra_attributes = PBXAttributes());
void SetProjectDirPath(const std::string& project_dir_path);
void SetProjectRoot(const std::string& project_root);
......
......@@ -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));
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment