Fix generation of target in Xcode project when using output_name. Target generating an application bundle whose name is different from the target name needs to set productName and PRODUCT_NAME to the base name of the application bundle (without .app) and set the name to the target name otherwise Xcode refuses to launch the application. BUG=297668 Review-Url: https://codereview.chromium.org/2005483002 Cr-Original-Commit-Position: refs/heads/master@{#395143} Cr-Mirrored-From: https://chromium.googlesource.com/chromium/src Cr-Mirrored-Commit: 4db57d47a591423e7ecaf1bc965d35f094250e35
diff --git a/tools/gn/xcode_object.cc b/tools/gn/xcode_object.cc index bc89944..3e9dd2c 100644 --- a/tools/gn/xcode_object.cc +++ b/tools/gn/xcode_object.cc
@@ -8,10 +8,11 @@ #include <sstream> #include <utility> -#include "base/files/file_path.h" #include "base/logging.h" +#include "base/macros.h" #include "base/memory/ptr_util.h" #include "base/strings/string_util.h" +#include "tools/gn/filesystem_utils.h" // Helper methods ------------------------------------------------------------- @@ -89,67 +90,71 @@ 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"}, - }; +struct SourceTypeForExt { + const char* ext; + const char* source_type; +}; - const auto& iter = extension_map.find(ext); - if (iter != extension_map.end()) { - return iter->second; +const SourceTypeForExt kSourceTypeForExt[] = { + {".a", "archive.ar"}, + {".app", "wrapper.application"}, + {".bdic", "file"}, + {".bundle", "wrapper.cfbundle"}, + {".c", "sourcecode.c.c"}, + {".cc", "sourcecode.cpp.cpp"}, + {".cpp", "sourcecode.cpp.cpp"}, + {".css", "text.css"}, + {".cxx", "sourcecode.cpp.cpp"}, + {".dart", "sourcecode"}, + {".dylib", "compiled.mach-o.dylib"}, + {".framework", "wrapper.framework"}, + {".h", "sourcecode.c.h"}, + {".hxx", "sourcecode.cpp.h"}, + {".icns", "image.icns"}, + {".java", "sourcecode.java"}, + {".js", "sourcecode.javascript"}, + {".kext", "wrapper.kext"}, + {".m", "sourcecode.c.objc"}, + {".mm", "sourcecode.cpp.objcpp"}, + {".nib", "wrapper.nib"}, + {".o", "compiled.mach-o.objfile"}, + {".pdf", "image.pdf"}, + {".pl", "text.script.perl"}, + {".plist", "text.plist.xml"}, + {".pm", "text.script.perl"}, + {".png", "image.png"}, + {".py", "text.script.python"}, + {".r", "sourcecode.rez"}, + {".rez", "sourcecode.rez"}, + {".s", "sourcecode.asm"}, + {".storyboard", "file.storyboard"}, + {".strings", "text.plist.strings"}, + {".swift", "sourcecode.swift"}, + {".ttf", "file"}, + {".xcassets", "folder.assetcatalog"}, + {".xcconfig", "text.xcconfig"}, + {".xcdatamodel", "wrapper.xcdatamodel"}, + {".xcdatamodeld", "wrapper.xcdatamodeld"}, + {".xib", "file.xib"}, + {".y", "sourcecode.yacc"}, +}; + +const char* GetSourceType(const base::StringPiece& ext) { + for (size_t i = 0; i < arraysize(kSourceTypeForExt); ++i) { + if (kSourceTypeForExt[i].ext == ext) + return kSourceTypeForExt[i].source_type; } return "text"; } -bool HasExplicitFileType(const base::FilePath::StringType& ext) { - return ext == FILE_PATH_LITERAL(".dart"); +bool HasExplicitFileType(const base::StringPiece& ext) { + return ext == ".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"); +bool IsSourceFileForIndexing(const base::StringPiece& ext) { + return ext == ".c" || ext == ".cc" || ext == ".cpp" || ext == ".cxx" || + ext == ".m" || ext == ".mm"; } void PrintValue(std::ostream& out, IndentRules rules, unsigned value) { @@ -411,9 +416,7 @@ PrintProperty(out, rules, "explicitFileType", type_); PrintProperty(out, rules, "includeInIndex", 0u); } else { - const base::FilePath::StringType ext = - base::FilePath::FromUTF8Unsafe(path_).Extension(); - + base::StringPiece ext = FindExtension(&path_); if (HasExplicitFileType(ext)) PrintProperty(out, rules, "explicitFileType", GetSourceType(ext)); else @@ -539,10 +542,12 @@ const std::string& config_name, const PBXAttributes& attributes, const std::string& product_type, + const std::string& product_name, const PBXFileReference* product_reference) : PBXTarget(name, shell_script, config_name, attributes), product_reference_(product_reference), - product_type_(product_type) { + product_type_(product_type), + product_name_(product_name) { DCHECK(product_reference_); build_phases_.push_back(base::WrapUnique(new PBXSourcesBuildPhase)); source_build_phase_ = @@ -574,7 +579,7 @@ PrintProperty(out, rules, "buildRules", EmptyPBXObjectVector()); PrintProperty(out, rules, "dependencies", EmptyPBXObjectVector()); PrintProperty(out, rules, "name", name_); - PrintProperty(out, rules, "productName", name_); + PrintProperty(out, rules, "productName", product_name_); PrintProperty(out, rules, "productReference", product_reference_); PrintProperty(out, rules, "productType", product_type_); out << indent_str << "};\n"; @@ -603,8 +608,7 @@ 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(); + base::StringPiece ext = FindExtension(&source_path); if (!IsSourceFileForIndexing(ext)) return; @@ -621,7 +625,7 @@ 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))); + product_type, name_, product_reference))); target_for_indexing_ = static_cast<PBXNativeTarget*>(targets_.back().get()); } @@ -645,20 +649,25 @@ 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(); + base::StringPiece ext = FindExtension(&output_name); + PBXFileReference* product = + static_cast<PBXFileReference*>(products_->AddChild(base::WrapUnique( + new PBXFileReference(std::string(), output_name, + type.empty() ? GetSourceType(ext) : type)))); - PBXFileReference* product = static_cast<PBXFileReference*>( - products_->AddChild(base::WrapUnique(new PBXFileReference( - name, output_name, type.empty() ? GetSourceType(ext) : type)))); + size_t ext_offset = FindExtensionOffset(output_name); + std::string product_name = ext_offset != std::string::npos + ? output_name.substr(0, ext_offset - 1) + : output_name; PBXAttributes attributes; attributes["CODE_SIGNING_REQUIRED"] = "NO"; attributes["CONFIGURATION_BUILD_DIR"] = "."; - attributes["PRODUCT_NAME"] = name; + attributes["PRODUCT_NAME"] = product_name; - targets_.push_back(base::WrapUnique(new PBXNativeTarget( - name, shell_script, config_name_, attributes, output_type, product))); + targets_.push_back(base::WrapUnique( + new PBXNativeTarget(name, shell_script, config_name_, attributes, + output_type, product_name, product))); } void PBXProject::SetProjectDirPath(const std::string& project_dir_path) {
diff --git a/tools/gn/xcode_object.h b/tools/gn/xcode_object.h index 25f2415..2ad43cc 100644 --- a/tools/gn/xcode_object.h +++ b/tools/gn/xcode_object.h
@@ -243,6 +243,7 @@ const std::string& config_name, const PBXAttributes& attributes, const std::string& product_type, + const std::string& product_name, const PBXFileReference* product_reference); ~PBXNativeTarget() override; @@ -255,6 +256,7 @@ private: const PBXFileReference* product_reference_; std::string product_type_; + std::string product_name_; DISALLOW_COPY_AND_ASSIGN(PBXNativeTarget); };
diff --git a/tools/gn/xcode_writer.cc b/tools/gn/xcode_writer.cc index 4168f7f..10624fa 100644 --- a/tools/gn/xcode_writer.cc +++ b/tools/gn/xcode_writer.cc
@@ -189,7 +189,7 @@ XcodeWriter workspace(workspace_name); workspace.CreateProductsProject(targets, attributes, source_path, config_name, root_target_name, ninja_extra_args, - target_os); + build_settings, target_os); workspace.CreateSourcesProject(all_targets, build_settings->build_dir(), attributes, source_path, config_name, @@ -266,6 +266,7 @@ const std::string& config_name, const std::string& root_target, const std::string& ninja_extra_args, + const BuildSettings* build_settings, TargetOsType target_os) { std::unique_ptr<PBXProject> main_project( new PBXProject("products", config_name, source_path, attributes)); @@ -298,10 +299,10 @@ main_project->AddNativeTarget( target->label().name(), std::string(), - target->bundle_data() - .GetBundleRootDirOutput(target->settings()) - .Resolve(base::FilePath()) - .AsUTF8Unsafe(), + RebasePath(target->bundle_data() + .GetBundleRootDirOutput(target->settings()) + .value(), + build_settings->build_dir()), target->bundle_data().product_type(), GetBuildScript(target->label().name(), build_path, ninja_extra_args)); @@ -347,9 +348,10 @@ std::sort(sources.begin(), sources.end()); sources.erase(std::unique(sources.begin(), sources.end()), sources.end()); + SourceDir source_dir("//"); for (const SourceFile& source : sources) { - base::FilePath source_path = source.Resolve(base::FilePath()); - sources_for_indexing->AddSourceFile(source_path.AsUTF8Unsafe()); + std::string source_file = RebasePath(source.value(), source_dir); + sources_for_indexing->AddSourceFile(source_file); } projects_.push_back(std::move(sources_for_indexing));
diff --git a/tools/gn/xcode_writer.h b/tools/gn/xcode_writer.h index dd162c6..8c4e304 100644 --- a/tools/gn/xcode_writer.h +++ b/tools/gn/xcode_writer.h
@@ -22,6 +22,10 @@ using PBXAttributes = std::map<std::string, std::string>; class PBXProject; +namespace base { +class FilePath; +} + class XcodeWriter { public: enum TargetOsType { @@ -69,6 +73,7 @@ const std::string& config_name, const std::string& root_target, const std::string& ninja_extra_args, + const BuildSettings* build_settings, TargetOsType target_os); // Generates the "sources.xcodeproj" project that reference all source