Add flag to include additional files in the generated Xcode project The chromium developer have found it useful to add `*.md` files to Xcode project so that they can be edited from Xcode. Add an option to gn Xcode project generator to include them (to remove the need to use a post-processing of the project in Chromium). Bug: none Change-Id: I0ac0eb6529735292b592cff4654259a2b1a61ff9 Reviewed-on: https://gn-review.googlesource.com/c/gn/+/14160 Reviewed-by: Takuto Ikuta <tikuta@google.com> Commit-Queue: Sylvain Defresne <sdefresne@chromium.org>
diff --git a/docs/reference.md b/docs/reference.md index 084398d..ef9a324 100644 --- a/docs/reference.md +++ b/docs/reference.md
@@ -845,6 +845,17 @@ One useful value is to use Xcode variables such as '${CONFIGURATION}' or '${EFFECTIVE_PLATFORM}'. + --xcode-additional-files-patterns=<pattern_list> + If present, must be a list of semicolon-separated file patterns. It + will be used to add all files matching the pattern located in the + source tree to the project. It can be used to add, e.g. documentation + files to the project to allow easily edit them. + + --xcode-additional-files-roots=<path_list> + If present, must be a list of semicolon-separated paths. It will be used + as roots when looking for additional files to add. If ommitted, defaults + to "//". + --ninja-executable=<string> Can be used to specify the ninja executable to use when building.
diff --git a/src/gn/command_gen.cc b/src/gn/command_gen.cc index fb68cf2..5c6cc14 100644 --- a/src/gn/command_gen.cc +++ b/src/gn/command_gen.cc
@@ -58,6 +58,9 @@ const char kSwitchXcodeBuildsystemValueNew[] = "new"; const char kSwitchXcodeConfigurations[] = "xcode-configs"; const char kSwitchXcodeConfigurationBuildPath[] = "xcode-config-build-dir"; +const char kSwitchXcodeAdditionalFilesPatterns[] = + "xcode-additional-files-patterns"; +const char kSwitchXcodeAdditionalFilesRoots[] = "xcode-additional-files-roots"; const char kSwitchJsonFileName[] = "json-file-name"; const char kSwitchJsonIdeScript[] = "json-ide-script"; const char kSwitchJsonIdeScriptArgs[] = "json-ide-script-args"; @@ -261,6 +264,8 @@ command_line->GetSwitchValueASCII(kSwitchFilters), command_line->GetSwitchValueASCII(kSwitchXcodeConfigurations), command_line->GetSwitchValuePath(kSwitchXcodeConfigurationBuildPath), + command_line->GetSwitchValueNative(kSwitchXcodeAdditionalFilesPatterns), + command_line->GetSwitchValueNative(kSwitchXcodeAdditionalFilesRoots), XcodeBuildSystem::kLegacy, }; @@ -537,6 +542,17 @@ One useful value is to use Xcode variables such as '${CONFIGURATION}' or '${EFFECTIVE_PLATFORM}'. + --xcode-additional-files-patterns=<pattern_list> + If present, must be a list of semicolon-separated file patterns. It + will be used to add all files matching the pattern located in the + source tree to the project. It can be used to add, e.g. documentation + files to the project to allow easily edit them. + + --xcode-additional-files-roots=<path_list> + If present, must be a list of semicolon-separated paths. It will be used + as roots when looking for additional files to add. If ommitted, defaults + to "//". + --ninja-executable=<string> Can be used to specify the ninja executable to use when building.
diff --git a/src/gn/xcode_object.cc b/src/gn/xcode_object.cc index ab357bb..4399c55 100644 --- a/src/gn/xcode_object.cc +++ b/src/gn/xcode_object.cc
@@ -116,6 +116,7 @@ {"js", "sourcecode.javascript"}, {"kext", "wrapper.kext"}, {"m", "sourcecode.c.objc"}, + {"md", "net.daringfireball.markdown"}, {"mm", "sourcecode.cpp.objcpp"}, {"nib", "wrapper.nib"}, {"o", "compiled.mach-o.objfile"},
diff --git a/src/gn/xcode_writer.cc b/src/gn/xcode_writer.cc index 0ec1fa8..8216aa4 100644 --- a/src/gn/xcode_writer.cc +++ b/src/gn/xcode_writer.cc
@@ -15,6 +15,7 @@ #include <utility> #include "base/environment.h" +#include "base/files/file_enumerator.h" #include "base/logging.h" #include "base/sha1.h" #include "base/stl_util.h" @@ -195,6 +196,49 @@ dependent_pbxtarget->AddDependency(std::move(dependency)); } +// Returns a SourceFile for absolute path `file_path` below `//`. +SourceFile FilePathToSourceFile(const BuildSettings* build_settings, + const base::FilePath& file_path) { + const std::string file_path_utf8 = FilePathToUTF8(file_path); + return SourceFile("//" + file_path_utf8.substr( + build_settings->root_path_utf8().size() + 1)); +} + +// Returns the list of patterns to use when looking for additional files +// from `options`. +std::vector<base::FilePath::StringType> GetAdditionalFilesPatterns( + const XcodeWriter::Options& options) { + return base::SplitString(options.additional_files_patterns, + FILE_PATH_LITERAL(";"), base::TRIM_WHITESPACE, + base::SPLIT_WANT_ALL); +} + +// Returns the list of roots to use when looking for additional files +// from `options`. +std::vector<base::FilePath> GetAdditionalFilesRoots( + const BuildSettings* build_settings, + const XcodeWriter::Options& options) { + if (options.additional_files_roots.empty()) { + return {build_settings->root_path()}; + } + + const std::vector<base::FilePath::StringType> roots = + base::SplitString(options.additional_files_roots, FILE_PATH_LITERAL(";"), + base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); + + std::vector<base::FilePath> root_paths; + for (const base::FilePath::StringType& root : roots) { + const std::string rebased_root = + RebasePath(FilePathToUTF8(root), SourceDir("//"), + build_settings->root_path_utf8()); + + root_paths.push_back( + build_settings->root_path().Append(UTF8ToFilePath(rebased_root))); + } + + return root_paths; +} + // Helper class to resolve list of XCTest files per target. // // Uses a cache of file found per intermediate targets to reduce the need @@ -639,14 +683,34 @@ if (!build_settings_->root_path().IsParent(path)) continue; - const std::string as8bit = path.As8Bit(); - const SourceFile source( - "//" + as8bit.substr(build_settings_->root_path().value().size() + 1)); - + const SourceFile source = FilePathToSourceFile(build_settings_, path); if (ShouldIncludeFileInProject(source)) sources.insert(source); } + // Add any files from --xcode-additional-files-patterns, using the root + // listed in --xcode-additional-files-roots. + if (!options_.additional_files_patterns.empty()) { + const std::vector<base::FilePath::StringType> patterns = + GetAdditionalFilesPatterns(options_); + const std::vector<base::FilePath> roots = + GetAdditionalFilesRoots(build_settings_, options_); + + for (const base::FilePath& root : roots) { + for (const base::FilePath::StringType& pattern : patterns) { + base::FileEnumerator it(root, /*recursive*/ true, + base::FileEnumerator::FILES, pattern, + base::FileEnumerator::FolderSearchPolicy::ALL); + + for (base::FilePath path = it.Next(); !path.empty(); path = it.Next()) { + const SourceFile source = FilePathToSourceFile(build_settings_, path); + if (ShouldIncludeFileInProject(source)) + sources.insert(source); + } + } + } + } + // Sort files to ensure deterministic generation of the project file (and // nicely sorted file list in Xcode). std::vector<SourceFile> sorted_sources(sources.begin(), sources.end());
diff --git a/src/gn/xcode_writer.h b/src/gn/xcode_writer.h index 7edd674..9c960e5 100644 --- a/src/gn/xcode_writer.h +++ b/src/gn/xcode_writer.h
@@ -56,6 +56,18 @@ // as the project directory. base::FilePath configuration_build_dir; + // If specified, should be a semicolon-separated list of file patterns. + // It will be used to add files to the project that are not referenced + // from the BUILD.gn files. This is usually used to add documentation + // files. + base::FilePath::StringType additional_files_patterns; + + // If specified, should be a semicolon-separated list of file roots. + // It will be used to add files to the project that are not referenced + // from the BUILD.gn files. This is usually used to add documentation + // files. + base::FilePath::StringType additional_files_roots; + // Control which version of the build system should be used for the // generated Xcode project. XcodeBuildSystem build_system = XcodeBuildSystem::kLegacy;