Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2760)

Unified Diff: tools/gn/xcode_object.cc

Issue 1827103005: [GN] Add support for generating Xcode projects. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Improve comment about "assert(product_type != "")" Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « tools/gn/xcode_object.h ('k') | tools/gn/xcode_writer.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: tools/gn/xcode_object.cc
diff --git a/tools/gn/xcode_object.cc b/tools/gn/xcode_object.cc
new file mode 100644
index 0000000000000000000000000000000000000000..bc8994409fe71ca5a429cf728ba7e611bb1d8e87
--- /dev/null
+++ b/tools/gn/xcode_object.cc
@@ -0,0 +1,858 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "tools/gn/xcode_object.h"
+
+#include <iomanip>
+#include <sstream>
+#include <utility>
+
+#include "base/files/file_path.h"
+#include "base/logging.h"
+#include "base/memory/ptr_util.h"
+#include "base/strings/string_util.h"
+
+// Helper methods -------------------------------------------------------------
+
+namespace {
+struct IndentRules {
+ bool one_line;
+ unsigned level;
+};
+
+std::vector<std::unique_ptr<PBXObject>> EmptyPBXObjectVector() {
+ return std::vector<std::unique_ptr<PBXObject>>();
+}
+
+bool CharNeedEscaping(char c) {
+ if (base::IsAsciiAlpha(c) || base::IsAsciiDigit(c))
+ return false;
+ if (c == '$' || c == '.' || c == '/' || c == '_')
+ return false;
+ return true;
+}
+
+bool StringNeedEscaping(const std::string& string) {
+ if (string.empty())
+ return true;
+ if (string.find("___") != std::string::npos)
+ return true;
+
+ for (char c : string) {
+ if (CharNeedEscaping(c))
+ return true;
+ }
+ return false;
+}
+
+std::string EncodeString(const std::string& string) {
+ if (!StringNeedEscaping(string))
+ return string;
+
+ std::stringstream buffer;
+ buffer << '"';
+ for (char c : string) {
+ if (c <= 31) {
+ switch (c) {
+ case '\a':
+ buffer << "\\a";
+ break;
+ case '\b':
+ buffer << "\\b";
+ break;
+ case '\t':
+ buffer << "\\t";
+ break;
+ case '\n':
+ case '\r':
+ buffer << "\\n";
+ break;
+ case '\v':
+ buffer << "\\v";
+ break;
+ case '\f':
+ buffer << "\\f";
+ break;
+ default:
+ buffer << std::hex << std::setw(4) << std::left << "\\U"
+ << static_cast<unsigned>(c);
+ break;
+ }
+ } else {
+ if (c == '"' || c == '\\')
+ buffer << '\\';
+ buffer << c;
+ }
+ }
+ buffer << '"';
+ return buffer.str();
+}
+
+const char* GetSourceType(const base::FilePath::StringType& ext) {
+ std::map<base::FilePath::StringType, const char*> extension_map = {
+ {FILE_PATH_LITERAL(".a"), "archive.ar"},
+ {FILE_PATH_LITERAL(".app"), "wrapper.application"},
+ {FILE_PATH_LITERAL(".bdic"), "file"},
+ {FILE_PATH_LITERAL(".bundle"), "wrapper.cfbundle"},
+ {FILE_PATH_LITERAL(".c"), "sourcecode.c.c"},
+ {FILE_PATH_LITERAL(".cc"), "sourcecode.cpp.cpp"},
+ {FILE_PATH_LITERAL(".cpp"), "sourcecode.cpp.cpp"},
+ {FILE_PATH_LITERAL(".css"), "text.css"},
+ {FILE_PATH_LITERAL(".cxx"), "sourcecode.cpp.cpp"},
+ {FILE_PATH_LITERAL(".dart"), "sourcecode"},
+ {FILE_PATH_LITERAL(".dylib"), "compiled.mach-o.dylib"},
+ {FILE_PATH_LITERAL(".framework"), "wrapper.framework"},
+ {FILE_PATH_LITERAL(".h"), "sourcecode.c.h"},
+ {FILE_PATH_LITERAL(".hxx"), "sourcecode.cpp.h"},
+ {FILE_PATH_LITERAL(".icns"), "image.icns"},
+ {FILE_PATH_LITERAL(".java"), "sourcecode.java"},
+ {FILE_PATH_LITERAL(".js"), "sourcecode.javascript"},
+ {FILE_PATH_LITERAL(".kext"), "wrapper.kext"},
+ {FILE_PATH_LITERAL(".m"), "sourcecode.c.objc"},
+ {FILE_PATH_LITERAL(".mm"), "sourcecode.cpp.objcpp"},
+ {FILE_PATH_LITERAL(".nib"), "wrapper.nib"},
+ {FILE_PATH_LITERAL(".o"), "compiled.mach-o.objfile"},
+ {FILE_PATH_LITERAL(".pdf"), "image.pdf"},
+ {FILE_PATH_LITERAL(".pl"), "text.script.perl"},
+ {FILE_PATH_LITERAL(".plist"), "text.plist.xml"},
+ {FILE_PATH_LITERAL(".pm"), "text.script.perl"},
+ {FILE_PATH_LITERAL(".png"), "image.png"},
+ {FILE_PATH_LITERAL(".py"), "text.script.python"},
+ {FILE_PATH_LITERAL(".r"), "sourcecode.rez"},
+ {FILE_PATH_LITERAL(".rez"), "sourcecode.rez"},
+ {FILE_PATH_LITERAL(".s"), "sourcecode.asm"},
+ {FILE_PATH_LITERAL(".storyboard"), "file.storyboard"},
+ {FILE_PATH_LITERAL(".strings"), "text.plist.strings"},
+ {FILE_PATH_LITERAL(".swift"), "sourcecode.swift"},
+ {FILE_PATH_LITERAL(".ttf"), "file"},
+ {FILE_PATH_LITERAL(".xcassets"), "folder.assetcatalog"},
+ {FILE_PATH_LITERAL(".xcconfig"), "text.xcconfig"},
+ {FILE_PATH_LITERAL(".xcdatamodel"), "wrapper.xcdatamodel"},
+ {FILE_PATH_LITERAL(".xcdatamodeld"), "wrapper.xcdatamodeld"},
+ {FILE_PATH_LITERAL(".xib"), "file.xib"},
+ {FILE_PATH_LITERAL(".y"), "sourcecode.yacc"},
+ };
+
+ const auto& iter = extension_map.find(ext);
+ if (iter != extension_map.end()) {
+ return iter->second;
+ }
+
+ return "text";
+}
+
+bool HasExplicitFileType(const base::FilePath::StringType& ext) {
+ return ext == FILE_PATH_LITERAL(".dart");
+}
+
+bool IsSourceFileForIndexing(const base::FilePath::StringType& ext) {
+ return ext == FILE_PATH_LITERAL(".c") || ext == FILE_PATH_LITERAL(".cc") ||
+ ext == FILE_PATH_LITERAL(".cpp") || ext == FILE_PATH_LITERAL(".cxx") ||
+ ext == FILE_PATH_LITERAL(".m") || ext == FILE_PATH_LITERAL(".mm");
+}
+
+void PrintValue(std::ostream& out, IndentRules rules, unsigned value) {
+ out << value;
+}
+
+void PrintValue(std::ostream& out, IndentRules rules, const char* value) {
+ out << EncodeString(value);
+}
+
+void PrintValue(std::ostream& out,
+ IndentRules rules,
+ const std::string& value) {
+ out << EncodeString(value);
+}
+
+void PrintValue(std::ostream& out, IndentRules rules, const PBXObject* value) {
+ out << value->Reference();
+}
+
+template <typename ObjectClass>
+void PrintValue(std::ostream& out,
+ IndentRules rules,
+ const std::unique_ptr<ObjectClass>& value) {
+ PrintValue(out, rules, value.get());
+}
+
+template <typename ValueType>
+void PrintValue(std::ostream& out,
+ IndentRules rules,
+ const std::vector<ValueType>& values) {
+ IndentRules sub_rule{rules.one_line, rules.level + 1};
+ out << "(" << (rules.one_line ? " " : "\n");
+ for (const auto& value : values) {
+ if (!sub_rule.one_line)
+ out << std::string(sub_rule.level, '\t');
+
+ PrintValue(out, sub_rule, value);
+ out << "," << (rules.one_line ? " " : "\n");
+ }
+
+ if (!rules.one_line && rules.level)
+ out << std::string(rules.level, '\t');
+ out << ")";
+}
+
+template <typename ValueType>
+void PrintValue(std::ostream& out,
+ IndentRules rules,
+ const std::map<std::string, ValueType>& values) {
+ IndentRules sub_rule{rules.one_line, rules.level + 1};
+ out << "{" << (rules.one_line ? " " : "\n");
+ for (const auto& pair : values) {
+ if (!sub_rule.one_line)
+ out << std::string(sub_rule.level, '\t');
+
+ out << pair.first << " = ";
+ PrintValue(out, sub_rule, pair.second);
+ out << ";" << (rules.one_line ? " " : "\n");
+ }
+
+ if (!rules.one_line && rules.level)
+ out << std::string(rules.level, '\t');
+ out << "}";
+}
+
+template <typename ValueType>
+void PrintProperty(std::ostream& out,
+ IndentRules rules,
+ const char* name,
+ ValueType&& value) {
+ if (!rules.one_line && rules.level)
+ out << std::string(rules.level, '\t');
+
+ out << name << " = ";
+ PrintValue(out, rules, std::forward<ValueType>(value));
+ out << ";" << (rules.one_line ? " " : "\n");
+}
+} // namespace
+
+// PBXObjectClass -------------------------------------------------------------
+
+const char* ToString(PBXObjectClass cls) {
+ switch (cls) {
+ case PBXAggregateTargetClass:
+ return "PBXAggregateTarget";
+ case PBXBuildFileClass:
+ return "PBXBuildFile";
+ case PBXFileReferenceClass:
+ return "PBXFileReference";
+ case PBXFrameworksBuildPhaseClass:
+ return "PBXFrameworksBuildPhase";
+ case PBXGroupClass:
+ return "PBXGroup";
+ case PBXNativeTargetClass:
+ return "PBXNativeTarget";
+ case PBXProjectClass:
+ return "PBXProject";
+ case PBXShellScriptBuildPhaseClass:
+ return "PBXShellScriptBuildPhase";
+ case PBXSourcesBuildPhaseClass:
+ return "PBXSourcesBuildPhase";
+ case XCBuildConfigurationClass:
+ return "XCBuildConfiguration";
+ case XCConfigurationListClass:
+ return "XCConfigurationList";
+ }
+ NOTREACHED();
+ return nullptr;
+}
+
+// PBXObjectVisitor -----------------------------------------------------------
+
+PBXObjectVisitor::PBXObjectVisitor() {}
+
+PBXObjectVisitor::~PBXObjectVisitor() {}
+
+// PBXObject ------------------------------------------------------------------
+
+PBXObject::PBXObject() {}
+
+PBXObject::~PBXObject() {}
+
+void PBXObject::SetId(const std::string& id) {
+ DCHECK(id_.empty());
+ DCHECK(!id.empty());
+ id_.assign(id);
+}
+
+std::string PBXObject::Reference() const {
+ std::string comment = Comment();
+ if (comment.empty())
+ return id_;
+
+ return id_ + " /* " + comment + " */";
+}
+
+std::string PBXObject::Comment() const {
+ return Name();
+}
+
+void PBXObject::Visit(PBXObjectVisitor& visitor) {
+ visitor.Visit(this);
+}
+
+// PBXBuildPhase --------------------------------------------------------------
+
+PBXBuildPhase::PBXBuildPhase() {}
+
+PBXBuildPhase::~PBXBuildPhase() {}
+
+// PBXTarget ------------------------------------------------------------------
+
+PBXTarget::PBXTarget(const std::string& name,
+ const std::string& shell_script,
+ const std::string& config_name,
+ const PBXAttributes& attributes)
+ : configurations_(new XCConfigurationList(config_name, attributes, this)),
+ name_(name) {
+ if (!shell_script.empty()) {
+ build_phases_.push_back(
+ base::WrapUnique(new PBXShellScriptBuildPhase(name, shell_script)));
+ }
+}
+
+PBXTarget::~PBXTarget() {}
+
+std::string PBXTarget::Name() const {
+ return name_;
+}
+
+void PBXTarget::Visit(PBXObjectVisitor& visitor) {
+ PBXObject::Visit(visitor);
+ configurations_->Visit(visitor);
+ for (const auto& build_phase : build_phases_) {
+ build_phase->Visit(visitor);
+ }
+}
+
+// PBXAggregateTarget ---------------------------------------------------------
+
+PBXAggregateTarget::PBXAggregateTarget(const std::string& name,
+ const std::string& shell_script,
+ const std::string& config_name,
+ const PBXAttributes& attributes)
+ : PBXTarget(name, shell_script, config_name, attributes) {}
+
+PBXAggregateTarget::~PBXAggregateTarget() {}
+
+PBXObjectClass PBXAggregateTarget::Class() const {
+ return PBXAggregateTargetClass;
+}
+
+void PBXAggregateTarget::Print(std::ostream& out, unsigned indent) const {
+ const std::string indent_str(indent, '\t');
+ const IndentRules rules = {false, indent + 1};
+ out << indent_str << Reference() << " = {\n";
+ PrintProperty(out, rules, "isa", ToString(Class()));
+ PrintProperty(out, rules, "buildConfigurationList", configurations_);
+ PrintProperty(out, rules, "buildPhases", build_phases_);
+ PrintProperty(out, rules, "dependencies", EmptyPBXObjectVector());
+ PrintProperty(out, rules, "name", name_);
+ PrintProperty(out, rules, "productName", name_);
+ out << indent_str << "};\n";
+}
+
+// PBXBuildFile ---------------------------------------------------------------
+
+PBXBuildFile::PBXBuildFile(const PBXFileReference* file_reference,
+ const PBXSourcesBuildPhase* build_phase)
+ : file_reference_(file_reference), build_phase_(build_phase) {
+ DCHECK(file_reference_);
+ DCHECK(build_phase_);
+}
+
+PBXBuildFile::~PBXBuildFile() {}
+
+PBXObjectClass PBXBuildFile::Class() const {
+ return PBXBuildFileClass;
+}
+
+std::string PBXBuildFile::Name() const {
+ return file_reference_->Name() + " in " + build_phase_->Name();
+}
+
+void PBXBuildFile::Print(std::ostream& out, unsigned indent) const {
+ const std::string indent_str(indent, '\t');
+ const IndentRules rules = {true, 0};
+ out << indent_str << Reference() << " = {";
+ PrintProperty(out, rules, "isa", ToString(Class()));
+ PrintProperty(out, rules, "fileRef", file_reference_);
+ out << "};\n";
+}
+
+// PBXFileReference -----------------------------------------------------------
+
+PBXFileReference::PBXFileReference(const std::string& name,
+ const std::string& path,
+ const std::string& type)
+ : name_(name), path_(path), type_(type) {}
+
+PBXFileReference::~PBXFileReference() {}
+
+PBXObjectClass PBXFileReference::Class() const {
+ return PBXFileReferenceClass;
+}
+
+std::string PBXFileReference::Name() const {
+ return path_;
+}
+
+void PBXFileReference::Print(std::ostream& out, unsigned indent) const {
+ const std::string indent_str(indent, '\t');
+ const IndentRules rules = {true, 0};
+ out << indent_str << Reference() << " = {";
+ PrintProperty(out, rules, "isa", ToString(Class()));
+
+ if (!type_.empty()) {
+ PrintProperty(out, rules, "explicitFileType", type_);
+ PrintProperty(out, rules, "includeInIndex", 0u);
+ } else {
+ const base::FilePath::StringType ext =
+ base::FilePath::FromUTF8Unsafe(path_).Extension();
+
+ if (HasExplicitFileType(ext))
+ PrintProperty(out, rules, "explicitFileType", GetSourceType(ext));
+ else
+ PrintProperty(out, rules, "lastKnownFileType", GetSourceType(ext));
+ }
+
+ if (name_ != path_ && !name_.empty())
+ PrintProperty(out, rules, "name", name_);
+
+ PrintProperty(out, rules, "path", path_);
+ PrintProperty(out, rules, "sourceTree",
+ type_.empty() ? "<group>" : "BUILT_PRODUCTS_DIR");
+ out << "};\n";
+}
+
+// PBXFrameworksBuildPhase ----------------------------------------------------
+
+PBXFrameworksBuildPhase::PBXFrameworksBuildPhase() {}
+
+PBXFrameworksBuildPhase::~PBXFrameworksBuildPhase() {}
+
+PBXObjectClass PBXFrameworksBuildPhase::Class() const {
+ return PBXFrameworksBuildPhaseClass;
+}
+
+std::string PBXFrameworksBuildPhase::Name() const {
+ return "Frameworks";
+}
+
+void PBXFrameworksBuildPhase::Print(std::ostream& out, unsigned indent) const {
+ const std::string indent_str(indent, '\t');
+ const IndentRules rules = {false, indent + 1};
+ out << indent_str << Reference() << " = {\n";
+ PrintProperty(out, rules, "isa", ToString(Class()));
+ PrintProperty(out, rules, "buildActionMask", 0x7fffffffu);
+ PrintProperty(out, rules, "files", EmptyPBXObjectVector());
+ PrintProperty(out, rules, "runOnlyForDeploymentPostprocessing", 0u);
+ out << indent_str << "};\n";
+}
+
+// PBXGroup -------------------------------------------------------------------
+
+PBXGroup::PBXGroup(const std::string& path, const std::string& name)
+ : name_(name), path_(path) {}
+
+PBXGroup::~PBXGroup() {}
+
+PBXObject* PBXGroup::AddChild(std::unique_ptr<PBXObject> child) {
+ DCHECK(child);
+ children_.push_back(std::move(child));
+ return children_.back().get();
+}
+
+PBXFileReference* PBXGroup::AddSourceFile(const std::string& source_path) {
+ DCHECK(!source_path.empty());
+ std::string::size_type sep = source_path.find("/");
+ if (sep == std::string::npos) {
+ children_.push_back(base::WrapUnique(
+ new PBXFileReference(std::string(), source_path, std::string())));
+ return static_cast<PBXFileReference*>(children_.back().get());
+ }
+
+ PBXGroup* group = nullptr;
+ base::StringPiece component(source_path.data(), sep);
+ for (const auto& child : children_) {
+ if (child->Class() != PBXGroupClass)
+ continue;
+
+ PBXGroup* child_as_group = static_cast<PBXGroup*>(child.get());
+ if (child_as_group->path_ == component) {
+ group = child_as_group;
+ break;
+ }
+ }
+
+ if (!group) {
+ children_.push_back(base::WrapUnique(new PBXGroup(component.as_string())));
+ group = static_cast<PBXGroup*>(children_.back().get());
+ }
+
+ DCHECK(group);
+ DCHECK(group->path_ == component);
+ return group->AddSourceFile(source_path.substr(sep + 1));
+}
+
+PBXObjectClass PBXGroup::Class() const {
+ return PBXGroupClass;
+}
+
+std::string PBXGroup::Name() const {
+ if (!name_.empty())
+ return name_;
+ if (!path_.empty())
+ return path_;
+ return std::string();
+}
+
+void PBXGroup::Visit(PBXObjectVisitor& visitor) {
+ PBXObject::Visit(visitor);
+ for (const auto& child : children_) {
+ child->Visit(visitor);
+ }
+}
+
+void PBXGroup::Print(std::ostream& out, unsigned indent) const {
+ const std::string indent_str(indent, '\t');
+ const IndentRules rules = {false, indent + 1};
+ out << indent_str << Reference() << " = {\n";
+ PrintProperty(out, rules, "isa", ToString(Class()));
+ PrintProperty(out, rules, "children", children_);
+ if (!name_.empty())
+ PrintProperty(out, rules, "name", name_);
+ if (!path_.empty())
+ PrintProperty(out, rules, "path", path_);
+ PrintProperty(out, rules, "sourceTree", "<group>");
+ out << indent_str << "};\n";
+}
+
+// PBXNativeTarget ------------------------------------------------------------
+
+PBXNativeTarget::PBXNativeTarget(const std::string& name,
+ const std::string& shell_script,
+ const std::string& config_name,
+ const PBXAttributes& attributes,
+ const std::string& product_type,
+ const PBXFileReference* product_reference)
+ : PBXTarget(name, shell_script, config_name, attributes),
+ product_reference_(product_reference),
+ product_type_(product_type) {
+ DCHECK(product_reference_);
+ build_phases_.push_back(base::WrapUnique(new PBXSourcesBuildPhase));
+ source_build_phase_ =
+ static_cast<PBXSourcesBuildPhase*>(build_phases_.back().get());
+
+ build_phases_.push_back(base::WrapUnique(new PBXFrameworksBuildPhase));
+}
+
+PBXNativeTarget::~PBXNativeTarget() {}
+
+void PBXNativeTarget::AddFileForIndexing(
+ const PBXFileReference* file_reference) {
+ DCHECK(file_reference);
+ source_build_phase_->AddBuildFile(
+ base::WrapUnique(new PBXBuildFile(file_reference, source_build_phase_)));
+}
+
+PBXObjectClass PBXNativeTarget::Class() const {
+ return PBXNativeTargetClass;
+}
+
+void PBXNativeTarget::Print(std::ostream& out, unsigned indent) const {
+ const std::string indent_str(indent, '\t');
+ const IndentRules rules = {false, indent + 1};
+ out << indent_str << Reference() << " = {\n";
+ PrintProperty(out, rules, "isa", ToString(Class()));
+ PrintProperty(out, rules, "buildConfigurationList", configurations_);
+ PrintProperty(out, rules, "buildPhases", build_phases_);
+ PrintProperty(out, rules, "buildRules", EmptyPBXObjectVector());
+ PrintProperty(out, rules, "dependencies", EmptyPBXObjectVector());
+ PrintProperty(out, rules, "name", name_);
+ PrintProperty(out, rules, "productName", name_);
+ PrintProperty(out, rules, "productReference", product_reference_);
+ PrintProperty(out, rules, "productType", product_type_);
+ out << indent_str << "};\n";
+}
+
+// PBXProject -----------------------------------------------------------------
+
+PBXProject::PBXProject(const std::string& name,
+ const std::string& config_name,
+ const std::string& source_path,
+ const PBXAttributes& attributes)
+ : name_(name), config_name_(config_name), target_for_indexing_(nullptr) {
+ attributes_["BuildIndependentTargetsInParallel"] = "YES";
+
+ main_group_.reset(new PBXGroup);
+ sources_ = static_cast<PBXGroup*>(main_group_->AddChild(
+ base::WrapUnique(new PBXGroup(source_path, "Source"))));
+ products_ = static_cast<PBXGroup*>(main_group_->AddChild(
+ base::WrapUnique(new PBXGroup(std::string(), "Product"))));
+ main_group_->AddChild(base::WrapUnique(new PBXGroup(std::string(), "Build")));
+
+ configurations_.reset(new XCConfigurationList(config_name, attributes, this));
+}
+
+PBXProject::~PBXProject() {}
+
+void PBXProject::AddSourceFile(const std::string& source_path) {
+ PBXFileReference* file_reference = sources_->AddSourceFile(source_path);
+ const base::FilePath::StringType ext =
+ base::FilePath::FromUTF8Unsafe(source_path).Extension();
+ if (!IsSourceFileForIndexing(ext))
+ return;
+
+ if (!target_for_indexing_) {
+ PBXAttributes attributes;
+ attributes["EXECUTABLE_PREFIX"] = "";
+ attributes["HEADER_SEARCH_PATHS"] = sources_->path();
+ attributes["PRODUCT_NAME"] = name_;
+
+ PBXFileReference* product_reference = static_cast<PBXFileReference*>(
+ products_->AddChild(base::WrapUnique(new PBXFileReference(
+ std::string(), name_, "compiled.mach-o.executable"))));
+
+ const char product_type[] = "com.apple.product-type.tool";
+ targets_.push_back(base::WrapUnique(
+ new PBXNativeTarget(name_, std::string(), config_name_, attributes,
+ product_type, product_reference)));
+ target_for_indexing_ = static_cast<PBXNativeTarget*>(targets_.back().get());
+ }
+
+ DCHECK(target_for_indexing_);
+ target_for_indexing_->AddFileForIndexing(file_reference);
+}
+
+void PBXProject::AddAggregateTarget(const std::string& name,
+ const std::string& shell_script) {
+ PBXAttributes attributes;
+ attributes["CODE_SIGNING_REQUIRED"] = "NO";
+ attributes["CONFIGURATION_BUILD_DIR"] = ".";
+ attributes["PRODUCT_NAME"] = name;
+
+ targets_.push_back(base::WrapUnique(
+ new PBXAggregateTarget(name, shell_script, config_name_, attributes)));
+}
+
+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 base::FilePath::StringType ext =
+ base::FilePath::FromUTF8Unsafe(output_name).Extension();
+
+ PBXFileReference* product = static_cast<PBXFileReference*>(
+ products_->AddChild(base::WrapUnique(new PBXFileReference(
+ name, output_name, type.empty() ? GetSourceType(ext) : type))));
+
+ PBXAttributes attributes;
+ attributes["CODE_SIGNING_REQUIRED"] = "NO";
+ attributes["CONFIGURATION_BUILD_DIR"] = ".";
+ attributes["PRODUCT_NAME"] = name;
+
+ targets_.push_back(base::WrapUnique(new PBXNativeTarget(
+ name, shell_script, config_name_, attributes, output_type, product)));
+}
+
+void PBXProject::SetProjectDirPath(const std::string& project_dir_path) {
+ DCHECK(!project_dir_path.empty());
+ project_dir_path_.assign(project_dir_path);
+}
+
+void PBXProject::SetProjectRoot(const std::string& project_root) {
+ DCHECK(!project_root.empty());
+ project_root_.assign(project_root);
+}
+
+void PBXProject::AddTarget(std::unique_ptr<PBXTarget> target) {
+ DCHECK(target);
+ targets_.push_back(std::move(target));
+}
+
+PBXObjectClass PBXProject::Class() const {
+ return PBXProjectClass;
+}
+
+std::string PBXProject::Name() const {
+ return name_;
+}
+
+std::string PBXProject::Comment() const {
+ return "Project object";
+}
+
+void PBXProject::Visit(PBXObjectVisitor& visitor) {
+ PBXObject::Visit(visitor);
+ configurations_->Visit(visitor);
+ main_group_->Visit(visitor);
+ for (const auto& target : targets_) {
+ target->Visit(visitor);
+ }
+}
+
+void PBXProject::Print(std::ostream& out, unsigned indent) const {
+ const std::string indent_str(indent, '\t');
+ const IndentRules rules = {false, indent + 1};
+ out << indent_str << Reference() << " = {\n";
+ PrintProperty(out, rules, "isa", ToString(Class()));
+ PrintProperty(out, rules, "attributes", attributes_);
+ PrintProperty(out, rules, "buildConfigurationList", configurations_);
+ PrintProperty(out, rules, "compatibilityVersion", "Xcode 3.2");
+ PrintProperty(out, rules, "developmentRegion", "English");
+ PrintProperty(out, rules, "hasScannedForEncodings", 1u);
+ PrintProperty(out, rules, "knownRegions", std::vector<std::string>({"en"}));
+ PrintProperty(out, rules, "mainGroup", main_group_);
+ PrintProperty(out, rules, "projectDirPath", project_dir_path_);
+ PrintProperty(out, rules, "projectRoot", project_root_);
+ PrintProperty(out, rules, "targets", targets_);
+ out << indent_str << "};\n";
+}
+
+// PBXShellScriptBuildPhase ---------------------------------------------------
+
+PBXShellScriptBuildPhase::PBXShellScriptBuildPhase(
+ const std::string& name,
+ const std::string& shell_script)
+ : name_("Action \"Compile and copy " + name + " via ninja\""),
+ shell_script_(shell_script) {}
+
+PBXShellScriptBuildPhase::~PBXShellScriptBuildPhase() {}
+
+PBXObjectClass PBXShellScriptBuildPhase::Class() const {
+ return PBXShellScriptBuildPhaseClass;
+}
+
+std::string PBXShellScriptBuildPhase::Name() const {
+ return name_;
+}
+
+void PBXShellScriptBuildPhase::Print(std::ostream& out, unsigned indent) const {
+ const std::string indent_str(indent, '\t');
+ const IndentRules rules = {false, indent + 1};
+ out << indent_str << Reference() << " = {\n";
+ PrintProperty(out, rules, "isa", ToString(Class()));
+ PrintProperty(out, rules, "buildActionMask", 0x7fffffffu);
+ PrintProperty(out, rules, "files", EmptyPBXObjectVector());
+ PrintProperty(out, rules, "inputPaths", EmptyPBXObjectVector());
+ PrintProperty(out, rules, "name", name_);
+ PrintProperty(out, rules, "outputPaths", EmptyPBXObjectVector());
+ PrintProperty(out, rules, "runOnlyForDeploymentPostprocessing", 0u);
+ PrintProperty(out, rules, "shellPath", "/bin/sh");
+ PrintProperty(out, rules, "shellScript", shell_script_);
+ PrintProperty(out, rules, "showEnvVarsInLog", 0u);
+ out << indent_str << "};\n";
+}
+
+// PBXSourcesBuildPhase -------------------------------------------------------
+
+PBXSourcesBuildPhase::PBXSourcesBuildPhase() {}
+
+PBXSourcesBuildPhase::~PBXSourcesBuildPhase() {}
+
+void PBXSourcesBuildPhase::AddBuildFile(
+ std::unique_ptr<PBXBuildFile> build_file) {
+ files_.push_back(std::move(build_file));
+}
+
+PBXObjectClass PBXSourcesBuildPhase::Class() const {
+ return PBXSourcesBuildPhaseClass;
+}
+
+std::string PBXSourcesBuildPhase::Name() const {
+ return "Sources";
+}
+
+void PBXSourcesBuildPhase::Visit(PBXObjectVisitor& visitor) {
+ PBXBuildPhase::Visit(visitor);
+ for (const auto& file : files_) {
+ file->Visit(visitor);
+ }
+}
+
+void PBXSourcesBuildPhase::Print(std::ostream& out, unsigned indent) const {
+ const std::string indent_str(indent, '\t');
+ const IndentRules rules = {false, indent + 1};
+ out << indent_str << Reference() << " = {\n";
+ PrintProperty(out, rules, "isa", ToString(Class()));
+ PrintProperty(out, rules, "buildActionMask", 0x7fffffffu);
+ PrintProperty(out, rules, "files", files_);
+ PrintProperty(out, rules, "runOnlyForDeploymentPostprocessing", 0u);
+ out << indent_str << "};\n";
+}
+
+// XCBuildConfiguration -------------------------------------------------------
+
+XCBuildConfiguration::XCBuildConfiguration(const std::string& name,
+ const PBXAttributes& attributes)
+ : attributes_(attributes), name_(name) {}
+
+XCBuildConfiguration::~XCBuildConfiguration() {}
+
+PBXObjectClass XCBuildConfiguration::Class() const {
+ return XCBuildConfigurationClass;
+}
+
+std::string XCBuildConfiguration::Name() const {
+ return name_;
+}
+
+void XCBuildConfiguration::Print(std::ostream& out, unsigned indent) const {
+ const std::string indent_str(indent, '\t');
+ const IndentRules rules = {false, indent + 1};
+ out << indent_str << Reference() << " = {\n";
+ PrintProperty(out, rules, "isa", ToString(Class()));
+ PrintProperty(out, rules, "buildSettings", attributes_);
+ PrintProperty(out, rules, "name", name_);
+ out << indent_str << "};\n";
+}
+
+// XCConfigurationList --------------------------------------------------------
+
+XCConfigurationList::XCConfigurationList(const std::string& name,
+ const PBXAttributes& attributes,
+ const PBXObject* owner_reference)
+ : owner_reference_(owner_reference) {
+ DCHECK(owner_reference_);
+ configurations_.push_back(
+ base::WrapUnique(new XCBuildConfiguration(name, attributes)));
+}
+
+XCConfigurationList::~XCConfigurationList() {}
+
+PBXObjectClass XCConfigurationList::Class() const {
+ return XCConfigurationListClass;
+}
+
+std::string XCConfigurationList::Name() const {
+ std::stringstream buffer;
+ buffer << "Build configuration list for "
+ << ToString(owner_reference_->Class()) << " \""
+ << owner_reference_->Name() << "\"";
+ return buffer.str();
+}
+
+void XCConfigurationList::Visit(PBXObjectVisitor& visitor) {
+ PBXObject::Visit(visitor);
+ for (const auto& configuration : configurations_) {
+ configuration->Visit(visitor);
+ }
+}
+
+void XCConfigurationList::Print(std::ostream& out, unsigned indent) const {
+ const std::string indent_str(indent, '\t');
+ const IndentRules rules = {false, indent + 1};
+ out << indent_str << Reference() << " = {\n";
+ PrintProperty(out, rules, "isa", ToString(Class()));
+ PrintProperty(out, rules, "buildConfigurations", configurations_);
+ PrintProperty(out, rules, "defaultConfigurationIsVisible", 1u);
+ PrintProperty(out, rules, "defaultConfigurationName",
+ configurations_[0]->Name());
+ out << indent_str << "};\n";
+}
« no previous file with comments | « tools/gn/xcode_object.h ('k') | tools/gn/xcode_writer.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698