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

Unified Diff: tools/gn/xcode_writer.cc

Issue 2057873002: [GN] Export include directories, defines and dialects to Xcode projects Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Remove preprocessor defines on individual files Created 4 years, 6 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_writer.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: tools/gn/xcode_writer.cc
diff --git a/tools/gn/xcode_writer.cc b/tools/gn/xcode_writer.cc
index 10624fa180d54a5d1df9067d8ca04ea720d5bb2d..e2f10b0ba6d7ef65e54341ad9afa1ebe84bccd21 100644
--- a/tools/gn/xcode_writer.cc
+++ b/tools/gn/xcode_writer.cc
@@ -20,6 +20,7 @@
#include "tools/gn/build_settings.h"
#include "tools/gn/builder.h"
#include "tools/gn/commands.h"
+#include "tools/gn/config_values_extractors.h"
#include "tools/gn/deps_iterator.h"
#include "tools/gn/filesystem_utils.h"
#include "tools/gn/settings.h"
@@ -153,12 +154,13 @@ bool XcodeWriter::RunAndWriteFiles(const std::string& workspace_name,
PBXAttributes attributes;
switch (target_os) {
case XcodeWriter::WRITER_TARGET_OS_IOS:
- attributes["SDKROOT"] = "iphoneos";
- attributes["TARGETED_DEVICE_FAMILY"] = "1,2";
+ attributes.insert(std::make_pair("SDKROOT", "iphoneos"));
+ attributes.insert(std::make_pair("TARGETED_DEVICE_FAMILY", "1,2"));
break;
case XcodeWriter::WRITER_TARGET_OS_MACOS:
- attributes["ARCHS"] = GetArchs(build_settings->build_args());
- attributes["SDKROOT"] = "macosx10.11";
+ attributes.insert(std::make_pair("SDKROOT", "macosx10.11"));
+ attributes.insert(
+ std::make_pair("ARCHS", GetArchs(build_settings->build_args())));
break;
}
@@ -316,6 +318,178 @@ void XcodeWriter::CreateProductsProject(
projects_.push_back(std::move(main_project));
}
+namespace {
+
+template <typename T>
+void SortAndRemoveDuplicates(std::vector<T>& vec) {
+ std::sort(vec.begin(), vec.end());
+ vec.erase(std::unique(vec.begin(), vec.end()), vec.end());
+}
+
+template <typename T>
+std::vector<T> IntersectSortedVectors(const std::vector<T>& vec,
+ const std::vector<T>& vec2) {
+ std::vector<T> intersection;
+ std::set_intersection(vec.begin(), vec.end(), vec2.begin(), vec2.end(),
+ std::back_inserter(intersection));
+ return intersection;
+}
+
+template <typename T>
+std::vector<T> ExcludeSortedVectors(const std::vector<T>& from,
+ const std::vector<T>& what) {
+ std::vector<T> difference;
+ std::set_difference(from.begin(), from.end(), what.begin(), what.end(),
+ std::back_inserter(difference));
+ return difference;
+}
+
+// Extracts dialect from flags, will not replace altrady extracted value
+void ExtractDialect(std::string& res,
+ const std::vector<std::string>& flags,
+ bool cc) {
+ for (const auto& flag : flags) {
+ if (res.empty() && flag.compare(0, 5, "-std=") == 0) {
+ res = flag;
+ }
+ if (!res.empty()) {
+ break;
+ }
+ }
+
+ // we're looking for c++ dialect, it must have + in name
+ if (cc && res.find('+') == std::string::npos)
+ res.clear();
+
+ // we're looking for c dialect, it must not have + in name
+ if (!cc && res.find('+') != std::string::npos)
+ res.clear();
+}
+
+void PrepareBuildAttributes(const std::vector<const Target*>& indexed_targets,
+ const SourceDir& root_build_dir,
+ std::map<SourceFile, std::string>& cflags,
+ PBXAttributes& attributes) {
+ // these will be specified at xcode target level and apply to all files
+ std::vector<SourceDir> common_includes;
+ std::vector<std::string> common_defines;
+
+ // gather common includes and defines
+ for (const auto* target : indexed_targets) {
+ std::vector<SourceDir> target_includes;
+ std::vector<std::string> target_defines;
+
+ for (ConfigValuesIterator it(target); !it.done(); it.Next()) {
+ target_includes.insert(target_includes.end(),
+ it.cur().include_dirs().begin(),
+ it.cur().include_dirs().end());
+ target_defines.insert(target_defines.end(), it.cur().defines().begin(),
+ it.cur().defines().end());
+ }
+ SortAndRemoveDuplicates(target_includes);
+ SortAndRemoveDuplicates(target_defines);
+
+ if (target == indexed_targets.front()) {
+ common_includes = std::move(target_includes);
+ common_defines = std::move(target_defines);
+ } else {
+ if (common_includes.empty() && common_defines.empty())
+ break;
+ common_includes =
+ IntersectSortedVectors(common_includes, target_includes);
+ common_defines = IntersectSortedVectors(common_defines, target_defines);
+ }
+ }
+
+ // gather specific cflags for individual files
+ for (const auto* target : indexed_targets) {
+ // only add taget includes to specific files; ignore target specific defines
+ // because they prevent using precompiled headers during indexing
+ std::vector<SourceDir> target_includes;
+
+ std::string target_dialect_c;
+ std::string target_dialect_cc;
+ std::string target_dialect_objc;
+ std::string target_dialect_objcc;
+
+ for (ConfigValuesIterator it(target); !it.done(); it.Next()) {
+ target_includes.insert(target_includes.end(),
+ it.cur().include_dirs().begin(),
+ it.cur().include_dirs().end());
+
+ ExtractDialect(target_dialect_c, it.cur().cflags_c(), false);
+ ExtractDialect(target_dialect_c, it.cur().cflags(), false);
+ ExtractDialect(target_dialect_cc, it.cur().cflags_cc(), true);
+ ExtractDialect(target_dialect_cc, it.cur().cflags(), true);
+ ExtractDialect(target_dialect_objc, it.cur().cflags_objc(), false);
+ ExtractDialect(target_dialect_objc, it.cur().cflags(), false);
+ ExtractDialect(target_dialect_objcc, it.cur().cflags_objcc(), true);
+ ExtractDialect(target_dialect_objcc, it.cur().cflags(), true);
+ }
+ SortAndRemoveDuplicates(target_includes);
+
+ std::string target_cflags;
+
+ // includes specific for this target
+ target_includes = ExcludeSortedVectors(target_includes, common_includes);
+ for (const auto& include : target_includes) {
+ std::string rebased = include.is_system_absolute()
+ ? include.value()
+ : RebasePath(include.value(), root_build_dir);
+ target_cflags += " -I";
+ target_cflags += rebased;
+ }
+
+ if (!target_cflags.empty()) // remove leading space
+ target_cflags = target_cflags.substr(1);
+
+ // for each file set target specific cflags and language dialect
+ // according to file type
+ for (const SourceFile& source : target->sources()) {
+ std::string file_cflags = target_cflags;
+ std::string file_dialect;
+ const auto& ext = FindExtension(&source.value());
+ if (ext == "c")
+ file_dialect = target_dialect_c;
+ else if (ext == "cc" || ext == "cpp" || ext == "cxx")
+ file_dialect = target_dialect_cc;
+ else if (ext == "m")
+ file_dialect = target_dialect_objc;
+ else if (ext == "mm")
+ file_dialect = target_dialect_objcc;
+
+ if (!file_cflags.empty() && !file_dialect.empty())
+ file_cflags += " ";
+ file_cflags += file_dialect;
+
+ cflags[source] = file_cflags;
+ }
+ }
+
+ // HEADERMAP breaks indexing if there are multiple files with same name
+ // in different folders; It also means that header lookup during indexing
+ // works differently than during build, which is not desired
+ attributes.erase("USE_HEADERMAP");
+ attributes.insert(std::make_pair("USE_HEADERMAP", "NO"));
+
+ if (!common_includes.empty()) {
+ for (const auto& include : common_includes) {
+ std::string rebased = include.is_system_absolute()
+ ? include.value()
+ : RebasePath(include.value(), root_build_dir);
+ attributes.insert(std::make_pair("HEADER_SEARCH_PATHS", rebased));
+ }
+ }
+
+ if (!common_defines.empty()) {
+ for (const auto& define : common_defines) {
+ attributes.insert(std::make_pair("GCC_PREPROCESSOR_DEFINITIONS", define));
+ }
+ }
+}
+
+} // namespace
+
void XcodeWriter::CreateSourcesProject(
const std::vector<const Target*>& targets,
const SourceDir& root_build_dir,
@@ -324,6 +498,8 @@ void XcodeWriter::CreateSourcesProject(
const std::string& config_name,
TargetOsType target_os) {
std::vector<SourceFile> sources;
+ std::vector<const Target*> indexed_targets;
+
for (const Target* target : targets) {
if (!target->settings()->is_default())
continue;
@@ -336,22 +512,31 @@ void XcodeWriter::CreateSourcesProject(
continue;
sources.push_back(source);
+
+ if (PBXProject::SourceFileShouldBeIndexed(source.value()) &&
+ (indexed_targets.empty() || indexed_targets.back() != target)) {
+ indexed_targets.push_back(target);
+ }
}
}
+ std::map<SourceFile, std::string> cflags;
+ PBXAttributes updated_attributes(attributes);
+ PrepareBuildAttributes(indexed_targets, root_build_dir, cflags,
+ updated_attributes);
+
std::unique_ptr<PBXProject> sources_for_indexing(
- new PBXProject("sources", config_name, source_path, attributes));
+ new PBXProject("sources", config_name, source_path, updated_attributes));
// Sort sources to ensure determinisn of the project file generation and
// remove duplicate reference to the source files (can happen due to the
// bundle_data targets).
- std::sort(sources.begin(), sources.end());
- sources.erase(std::unique(sources.begin(), sources.end()), sources.end());
+ SortAndRemoveDuplicates(sources);
SourceDir source_dir("//");
for (const SourceFile& source : sources) {
std::string source_file = RebasePath(source.value(), source_dir);
- sources_for_indexing->AddSourceFile(source_file);
+ sources_for_indexing->AddSourceFile(source_file, cflags[source]);
}
projects_.push_back(std::move(sources_for_indexing));
« no previous file with comments | « tools/gn/xcode_writer.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698