Index: tools/gn/command_gyp.cc |
diff --git a/tools/gn/command_gyp.cc b/tools/gn/command_gyp.cc |
index 02ea51c154a1382d90ffbcbde45eecabe5e16768..ff6a5c3875960a8f22e460e3d3dab06e06b0224b 100644 |
--- a/tools/gn/command_gyp.cc |
+++ b/tools/gn/command_gyp.cc |
@@ -11,6 +11,7 @@ |
#include "base/environment.h" |
#include "base/strings/string_number_conversions.h" |
#include "base/timer/elapsed_timer.h" |
+#include "build/build_config.h" |
#include "tools/gn/build_settings.h" |
#include "tools/gn/commands.h" |
#include "tools/gn/err.h" |
@@ -35,6 +36,45 @@ typedef std::map<SourceFile, std::vector<TargetGroup> > GroupedTargetsMap; |
typedef std::map<std::string, std::string> StringStringMap; |
typedef std::vector<const BuilderRecord*> RecordVector; |
+struct Setups { |
+ Setups() |
+ : debug(NULL), |
+ release(NULL), |
+ host_debug(NULL), |
+ host_release(NULL), |
+ debug64(NULL), |
+ release64(NULL), |
+ xcode_debug(NULL), |
+ xcode_release(NULL), |
+ xcode_host_debug(NULL), |
+ xcode_host_release(NULL) { |
+ } |
+ |
+ Setup* debug; |
+ DependentSetup* release; |
+ DependentSetup* host_debug; |
+ DependentSetup* host_release; |
+ DependentSetup* debug64; |
+ DependentSetup* release64; |
+ DependentSetup* xcode_debug; |
+ DependentSetup* xcode_release; |
+ DependentSetup* xcode_host_debug; |
+ DependentSetup* xcode_host_release; |
+}; |
+ |
+struct TargetVectors { |
+ RecordVector debug; |
+ RecordVector release; |
+ RecordVector host_debug; |
+ RecordVector host_release; |
+ RecordVector debug64; |
+ RecordVector release64; |
+ RecordVector xcode_debug; |
+ RecordVector xcode_release; |
+ RecordVector xcode_host_debug; |
+ RecordVector xcode_host_release; |
+}; |
+ |
// This function appends a suffix to the given source directory name. We append |
// a suffix to the last directory component rather than adding a new level so |
// that the relative location of the files don't change (i.e. a file |
@@ -44,6 +84,33 @@ SourceDir AppendDirSuffix(const SourceDir& base, const std::string& suffix) { |
return SourceDir(DirectoryWithNoLastSlash(base) + suffix + "/"); |
} |
+// We need a "host" build when targeting a device (iOS, Android, ChromeOS). The |
+// host build will correspond to the the system doing the building. |
+bool NeedsHostBuild(CommonSetup* setup) { |
+ Args& args = setup->build_settings().build_args(); |
+ const Value* os_override = args.GetArgOverride("os"); |
+ if (!os_override) |
+ return false; // Target OS is the default, which is always the host. |
+ if (os_override->type() != Value::STRING) |
+ return false; // Build will likely fail later. |
+ return os_override->string_value() == "android" || |
+ os_override->string_value() == "ios" || |
+ os_override->string_value() == "chromeos"; |
+} |
+ |
+void SetupHostBuildParams(CommonSetup* setup) { |
+ // Re-override the target OS to the default of the current system. |
+#if defined(OS_WIN) |
+ const char kDefaultOs[] = "win"; |
+#elif defined(OS_MACOSX) |
+ const char kDefaultOs[] = "mac"; |
+#elif defined(OS_LINUX) |
+ const char kDefaultOs[] = "linux"; |
+#endif |
+ setup->build_settings().build_args().AddArgOverride( |
+ "os", Value(NULL, kDefaultOs)); |
+} |
+ |
std::vector<const BuilderRecord*> GetAllResolvedTargetRecords( |
const Builder* builder) { |
std::vector<const BuilderRecord*> all = builder->GetAllRecords(); |
@@ -58,6 +125,16 @@ std::vector<const BuilderRecord*> GetAllResolvedTargetRecords( |
return result; |
} |
+void CorrelateRecordVector(const RecordVector& records, |
+ CorrelatedTargetsMap* correlated, |
+ const BuilderRecord* TargetGroup::* record_ptr) { |
+ for (size_t i = 0; i < records.size(); i++) { |
+ const BuilderRecord* record = records[i]; |
+ (*correlated)[record->label().GetWithNoToolchain()].*record_ptr = record; |
+ } |
+} |
+ |
+ |
// Groups targets sharing the same label between debug and release. |
// |
// We strip the toolchain label because the 64-bit and 32-bit builds, for |
@@ -68,47 +145,43 @@ std::vector<const BuilderRecord*> GetAllResolvedTargetRecords( |
// the 32-vs-64-bit case and the default-toolchain-vs-not case. When we find |
// a target not using hte default toolchain, we should probably just shell |
// out to ninja. |
-void CorrelateTargets(const RecordVector& debug_targets, |
- const RecordVector& release_targets, |
- const RecordVector& host_debug_targets, |
- const RecordVector& host_release_targets, |
- const RecordVector& debug64_targets, |
- const RecordVector& release64_targets, |
+void CorrelateTargets(const TargetVectors& targets, |
CorrelatedTargetsMap* correlated) { |
// Normal. |
- for (size_t i = 0; i < debug_targets.size(); i++) { |
- const BuilderRecord* record = debug_targets[i]; |
- (*correlated)[record->label().GetWithNoToolchain()].debug = record; |
- } |
- for (size_t i = 0; i < release_targets.size(); i++) { |
- const BuilderRecord* record = release_targets[i]; |
- (*correlated)[record->label().GetWithNoToolchain()].release = record; |
- } |
- |
- // Host build. |
- for (size_t i = 0; i < host_debug_targets.size(); i++) { |
- const BuilderRecord* record = host_debug_targets[i]; |
- (*correlated)[record->label().GetWithNoToolchain()].host_debug = record; |
- } |
- for (size_t i = 0; i < host_release_targets.size(); i++) { |
- const BuilderRecord* record = host_release_targets[i]; |
- (*correlated)[record->label().GetWithNoToolchain()].host_release = record; |
- } |
+ CorrelateRecordVector( |
+ targets.debug, correlated, &TargetGroup::debug); |
+ CorrelateRecordVector( |
+ targets.release, correlated, &TargetGroup::release); |
// Host build. |
- for (size_t i = 0; i < debug64_targets.size(); i++) { |
- const BuilderRecord* record = debug64_targets[i]; |
- (*correlated)[record->label().GetWithNoToolchain()].debug64 = record; |
- } |
- for (size_t i = 0; i < release64_targets.size(); i++) { |
- const BuilderRecord* record = release64_targets[i]; |
- (*correlated)[record->label().GetWithNoToolchain()].release64 = record; |
- } |
+ CorrelateRecordVector( |
+ targets.host_debug, correlated, &TargetGroup::host_debug); |
+ CorrelateRecordVector( |
+ targets.host_release, correlated, &TargetGroup::host_release); |
+ |
+ // 64-bit build. |
+ CorrelateRecordVector( |
+ targets.debug64, correlated, &TargetGroup::debug64); |
+ CorrelateRecordVector( |
+ targets.release64, correlated, &TargetGroup::release64); |
+ |
+ // XCode build. |
+ CorrelateRecordVector( |
+ targets.xcode_debug, correlated, &TargetGroup::xcode_debug); |
+ CorrelateRecordVector( |
+ targets.xcode_release, correlated, &TargetGroup::xcode_release); |
+ CorrelateRecordVector( |
+ targets.xcode_host_debug, correlated, &TargetGroup::xcode_host_debug); |
+ CorrelateRecordVector( |
+ targets.xcode_host_release, correlated, &TargetGroup::xcode_host_release); |
} |
// Verifies that both debug and release variants match. They can differ only |
// by flags. |
bool EnsureTargetsMatch(const TargetGroup& group, Err* err) { |
+ if (!group.debug && !group.release) |
+ return true; |
+ |
// Check that both debug and release made this target. |
if (!group.debug || !group.release) { |
const BuilderRecord* non_null_one = |
@@ -171,45 +244,46 @@ bool EnsureTargetsMatch(const TargetGroup& group, Err* err) { |
} |
// Returns the (number of targets, number of GYP files). |
-std::pair<int, int> WriteGypFiles(CommonSetup* debug_setup, |
- CommonSetup* release_setup, |
- CommonSetup* host_debug_setup, |
- CommonSetup* host_release_setup, |
- CommonSetup* debug64_setup, |
- CommonSetup* release64_setup, |
- Err* err) { |
+std::pair<int, int> WriteGypFiles(Setups& setups, Err* err) { |
+ TargetVectors targets; |
+ |
// Group all targets by output GYP file name. |
- std::vector<const BuilderRecord*> debug_targets = |
- GetAllResolvedTargetRecords(debug_setup->builder()); |
- std::vector<const BuilderRecord*> release_targets = |
- GetAllResolvedTargetRecords(release_setup->builder()); |
+ targets.debug = GetAllResolvedTargetRecords(setups.debug->builder()); |
+ targets.release = GetAllResolvedTargetRecords(setups.release->builder()); |
// Host build is optional. |
- std::vector<const BuilderRecord*> host_debug_targets; |
- std::vector<const BuilderRecord*> host_release_targets; |
- if (host_debug_setup && host_release_setup) { |
- host_debug_targets = GetAllResolvedTargetRecords( |
- host_debug_setup->builder()); |
- host_release_targets = GetAllResolvedTargetRecords( |
- host_release_setup->builder()); |
+ if (setups.host_debug && setups.host_release) { |
+ targets.host_debug = |
+ GetAllResolvedTargetRecords(setups.host_debug->builder()); |
+ targets.host_release = |
+ GetAllResolvedTargetRecords(setups.host_release->builder()); |
} |
// 64-bit build is optional. |
- std::vector<const BuilderRecord*> debug64_targets; |
- std::vector<const BuilderRecord*> release64_targets; |
- if (debug64_setup && release64_setup) { |
- debug64_targets = GetAllResolvedTargetRecords( |
- debug64_setup->builder()); |
- release64_targets = GetAllResolvedTargetRecords( |
- release64_setup->builder()); |
+ if (setups.debug64 && setups.release64) { |
+ targets.debug64 = |
+ GetAllResolvedTargetRecords(setups.debug64->builder()); |
+ targets.release64 = |
+ GetAllResolvedTargetRecords(setups.release64->builder()); |
+ } |
+ |
+ // Xcode build is optional. |
+ if (setups.xcode_debug && setups.xcode_release) { |
+ targets.xcode_debug = |
+ GetAllResolvedTargetRecords(setups.xcode_debug->builder()); |
+ targets.xcode_release = |
+ GetAllResolvedTargetRecords(setups.xcode_release->builder()); |
+ } |
+ if (setups.xcode_host_debug && setups.xcode_host_release) { |
+ targets.xcode_host_debug = |
+ GetAllResolvedTargetRecords(setups.xcode_host_debug->builder()); |
+ targets.xcode_host_release = |
+ GetAllResolvedTargetRecords(setups.xcode_host_release->builder()); |
} |
// Match up the debug and release version of each target by label. |
CorrelatedTargetsMap correlated; |
- CorrelateTargets(debug_targets, release_targets, |
- host_debug_targets, host_release_targets, |
- debug64_targets, release64_targets, |
- &correlated); |
+ CorrelateTargets(targets, &correlated); |
GypHelper helper; |
GroupedTargetsMap grouped_targets; |
@@ -217,11 +291,11 @@ std::pair<int, int> WriteGypFiles(CommonSetup* debug_setup, |
for (CorrelatedTargetsMap::iterator i = correlated.begin(); |
i != correlated.end(); ++i) { |
const TargetGroup& group = i->second; |
- if (!group.debug->should_generate()) |
+ if (!group.get()->should_generate()) |
continue; // Skip non-generated ones. |
- if (group.debug->item()->AsTarget()->external()) |
+ if (group.get()->item()->AsTarget()->external()) |
continue; // Skip external ones. |
- if (group.debug->item()->AsTarget()->gyp_file().is_null()) |
+ if (group.get()->item()->AsTarget()->gyp_file().is_null()) |
continue; // Skip ones without GYP files. |
if (!EnsureTargetsMatch(group, err)) |
@@ -238,7 +312,7 @@ std::pair<int, int> WriteGypFiles(CommonSetup* debug_setup, |
// Extract the toolchain for the debug targets. |
const Toolchain* debug_toolchain = NULL; |
if (!grouped_targets.empty()) { |
- debug_toolchain = debug_setup->builder()->GetToolchain( |
+ debug_toolchain = setups.debug->builder()->GetToolchain( |
grouped_targets.begin()->second[0].debug->item()->settings()-> |
default_toolchain_label()); |
} |
@@ -327,79 +401,128 @@ const char kGyp_Help[] = |
int RunGyp(const std::vector<std::string>& args) { |
base::ElapsedTimer timer; |
+ Setups setups; |
// Deliberately leaked to avoid expensive process teardown. |
- Setup* setup_debug = new Setup; |
- if (!setup_debug->DoSetup()) |
+ setups.debug = new Setup; |
+ if (!setups.debug->DoSetup()) |
return 1; |
const char kIsDebug[] = "is_debug"; |
- SourceDir base_build_dir = setup_debug->build_settings().build_dir(); |
- setup_debug->build_settings().SetBuildDir( |
+ SourceDir base_build_dir = setups.debug->build_settings().build_dir(); |
+ setups.debug->build_settings().SetBuildDir( |
AppendDirSuffix(base_build_dir, ".Debug")); |
// Make a release build based on the debug one. We use a new directory for |
// the build output so that they don't stomp on each other. |
- DependentSetup* setup_release = new DependentSetup(setup_debug); |
- setup_release->build_settings().build_args().AddArgOverride( |
+ setups.release = new DependentSetup(setups.debug); |
+ setups.release->build_settings().build_args().AddArgOverride( |
kIsDebug, Value(NULL, false)); |
- setup_release->build_settings().SetBuildDir( |
+ setups.release->build_settings().SetBuildDir( |
AppendDirSuffix(base_build_dir, ".Release")); |
// Host build. |
- DependentSetup* setup_host_debug = NULL; |
- DependentSetup* setup_host_release = NULL; |
- // TODO(brettw) hook up host build. |
+ if (NeedsHostBuild(setups.debug)) { |
+ setups.host_debug = new DependentSetup(setups.debug); |
+ setups.host_debug->build_settings().SetBuildDir( |
+ AppendDirSuffix(base_build_dir, ".HostDebug")); |
+ SetupHostBuildParams(setups.host_debug); |
+ |
+ setups.host_release = new DependentSetup(setups.release); |
+ setups.host_release->build_settings().SetBuildDir( |
+ AppendDirSuffix(base_build_dir, ".HostRelease")); |
+ SetupHostBuildParams(setups.host_release); |
+ } |
// 64-bit build (Windows only). |
- DependentSetup* setup_debug64 = NULL; |
- DependentSetup* setup_release64 = NULL; |
#if defined(OS_WIN) |
static const char kForceWin64[] = "force_win64"; |
- setup_debug64 = new DependentSetup(setup_debug); |
- setup_debug64->build_settings().build_args().AddArgOverride( |
+ setups.debug64 = new DependentSetup(setups.debug); |
+ setups.debug64->build_settings().build_args().AddArgOverride( |
kForceWin64, Value(NULL, true)); |
- setup_debug64->build_settings().SetBuildDir( |
+ setups.debug64->build_settings().SetBuildDir( |
AppendDirSuffix(base_build_dir, ".Debug64")); |
- setup_release64 = new DependentSetup(setup_release); |
- setup_release64->build_settings().build_args().AddArgOverride( |
+ setups.release64 = new DependentSetup(setups.release); |
+ setups.release64->build_settings().build_args().AddArgOverride( |
kForceWin64, Value(NULL, true)); |
- setup_release64->build_settings().SetBuildDir( |
+ setups.release64->build_settings().SetBuildDir( |
AppendDirSuffix(base_build_dir, ".Release64")); |
#endif |
+ // XCode build (Mac only). |
+#if defined(OS_MACOSX) |
+ static const char kGypXCode[] = "is_gyp_xcode_generator"; |
+ setups.xcode_debug = new DependentSetup(setups.debug); |
+ setups.xcode_debug->build_settings().build_args().AddArgOverride( |
+ kGypXCode, Value(NULL, true)); |
+ setups.xcode_debug->build_settings().SetBuildDir( |
+ AppendDirSuffix(base_build_dir, ".XCodeDebug")); |
+ |
+ setups.xcode_release = new DependentSetup(setups.release); |
+ setups.xcode_release->build_settings().build_args().AddArgOverride( |
+ kGypXCode, Value(NULL, true)); |
+ setups.xcode_release->build_settings().SetBuildDir( |
+ AppendDirSuffix(base_build_dir, ".XCodeRelease")); |
+ |
+ if (NeedsHostBuild(setups.debug)) { |
+ setups.xcode_host_debug = new DependentSetup(setups.xcode_debug); |
+ setups.xcode_host_debug->build_settings().SetBuildDir( |
+ AppendDirSuffix(base_build_dir, ".XCodeHostDebug")); |
+ SetupHostBuildParams(setups.xcode_host_debug); |
+ |
+ setups.xcode_host_release = new DependentSetup(setups.xcode_release); |
+ setups.xcode_host_release->build_settings().SetBuildDir( |
+ AppendDirSuffix(base_build_dir, ".XCodeHostRelease")); |
+ SetupHostBuildParams(setups.xcode_host_release); |
+ } |
+#endif |
+ |
// Run all the builds in parellel. |
- setup_release->RunPreMessageLoop(); |
- if (setup_host_debug && setup_host_release) { |
- setup_host_debug->RunPreMessageLoop(); |
- setup_host_release->RunPreMessageLoop(); |
+ setups.release->RunPreMessageLoop(); |
+ if (setups.host_debug && setups.host_release) { |
+ setups.host_debug->RunPreMessageLoop(); |
+ setups.host_release->RunPreMessageLoop(); |
+ } |
+ if (setups.debug64 && setups.release64) { |
+ setups.debug64->RunPreMessageLoop(); |
+ setups.release64->RunPreMessageLoop(); |
+ } |
+ if (setups.xcode_debug && setups.xcode_release) { |
+ setups.xcode_debug->RunPreMessageLoop(); |
+ setups.xcode_release->RunPreMessageLoop(); |
} |
- if (setup_debug64 && setup_release64) { |
- setup_debug64->RunPreMessageLoop(); |
- setup_release64->RunPreMessageLoop(); |
+ if (setups.xcode_host_debug && setups.xcode_host_release) { |
+ setups.xcode_host_debug->RunPreMessageLoop(); |
+ setups.xcode_host_release->RunPreMessageLoop(); |
} |
- if (!setup_debug->Run()) |
+ if (!setups.debug->Run()) |
return 1; |
- if (!setup_release->RunPostMessageLoop()) |
+ if (!setups.release->RunPostMessageLoop()) |
+ return 1; |
+ if (setups.host_debug && !setups.host_debug->RunPostMessageLoop()) |
+ return 1; |
+ if (setups.host_release && !setups.host_release->RunPostMessageLoop()) |
+ return 1; |
+ if (setups.debug64 && !setups.debug64->RunPostMessageLoop()) |
+ return 1; |
+ if (setups.release64 && !setups.release64->RunPostMessageLoop()) |
return 1; |
- if (setup_host_debug && !setup_host_debug->RunPostMessageLoop()) |
+ if (setups.xcode_debug && !setups.xcode_debug->RunPostMessageLoop()) |
return 1; |
- if (setup_host_release && !setup_host_release->RunPostMessageLoop()) |
+ if (setups.xcode_release && !setups.xcode_release->RunPostMessageLoop()) |
return 1; |
- if (setup_debug64 && !setup_debug64->RunPostMessageLoop()) |
+ if (setups.xcode_host_debug && |
+ !setups.xcode_host_debug->RunPostMessageLoop()) |
return 1; |
- if (setup_release64 && !setup_release64->RunPostMessageLoop()) |
+ if (setups.xcode_host_release && |
+ !setups.xcode_host_release->RunPostMessageLoop()) |
return 1; |
Err err; |
- std::pair<int, int> counts = |
- WriteGypFiles(setup_debug, setup_release, |
- setup_host_debug, setup_host_release, |
- setup_debug64, setup_release64, |
- &err); |
+ std::pair<int, int> counts = WriteGypFiles(setups, &err); |
if (err.has_error()) { |
err.PrintToStdout(); |
return 1; |
@@ -414,7 +537,7 @@ int RunGyp(const std::vector<std::string>& args) { |
base::IntToString(counts.first) + " targets to " + |
base::IntToString(counts.second) + " GYP files read from " + |
base::IntToString( |
- setup_debug->scheduler().input_file_manager()->GetInputFileCount()) |
+ setups.debug->scheduler().input_file_manager()->GetInputFileCount()) |
+ " GN files in " + |
base::IntToString(elapsed_time.InMilliseconds()) + "ms\n"; |