summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorbrettw@chromium.org <brettw@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-08-05 23:08:12 +0000
committerbrettw@chromium.org <brettw@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-08-05 23:08:12 +0000
commit8338eeabe776455a934ccf099cac7bd87fa57588 (patch)
treeb8ff2a372e01ceb2ec26395d33734fd233d999af
parent5c4ef464378a201b7350df1df46a60efba66bb15 (diff)
downloadchromium_src-8338eeabe776455a934ccf099cac7bd87fa57588.zip
chromium_src-8338eeabe776455a934ccf099cac7bd87fa57588.tar.gz
chromium_src-8338eeabe776455a934ccf099cac7bd87fa57588.tar.bz2
Hook up better describing, work on Mac build.
This expands the "desc" command to list includes, defined, and flags. It will now optionally annotate the source of the configs producting this list. I folded the old "tree" and "deps" subcommands into the new expanded desc command. This works on the Mac build. Some more Mac flags are set in the environment and I added Mac extensions to some of the lists. It does not yet completely work, however. This adds a lot of Mac/GCC stuff to the current build. I tracked back the current set of defines that the GYP build sets, and set them in the GN build. BUG= R=scottmg@chromium.org Review URL: https://codereview.chromium.org/21636002 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@215722 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--tools/gn/command_desc.cc394
-rw-r--r--tools/gn/commands.cc59
-rw-r--r--tools/gn/commands.h23
-rw-r--r--tools/gn/config.cc2
-rw-r--r--tools/gn/config_values_extractors.h17
-rw-r--r--tools/gn/filesystem_utils.cc18
-rw-r--r--tools/gn/gn_main.cc8
-rw-r--r--tools/gn/item_tree.h2
-rw-r--r--tools/gn/ninja_helper.cc32
-rw-r--r--tools/gn/ninja_target_writer.cc10
-rw-r--r--tools/gn/secondary/build/config/BUILD.gn4
-rw-r--r--tools/gn/secondary/build/config/BUILDCONFIG.gn13
-rw-r--r--tools/gn/secondary/build/config/compiler/BUILD.gn376
-rw-r--r--tools/gn/secondary/build/config/mac/BUILD.gn74
-rw-r--r--tools/gn/settings.cc13
-rw-r--r--tools/gn/settings.h1
-rw-r--r--tools/gn/toolchain.cc6
-rw-r--r--tools/gn/toolchain.h4
-rw-r--r--tools/gn/toolchain_manager.cc21
19 files changed, 743 insertions, 334 deletions
diff --git a/tools/gn/command_desc.cc b/tools/gn/command_desc.cc
index ca28962..1aeb2be 100644
--- a/tools/gn/command_desc.cc
+++ b/tools/gn/command_desc.cc
@@ -4,9 +4,12 @@
#include <algorithm>
#include <set>
+#include <sstream>
+#include "base/command_line.h"
#include "tools/gn/commands.h"
#include "tools/gn/config.h"
+#include "tools/gn/config_values_extractors.h"
#include "tools/gn/item.h"
#include "tools/gn/item_node.h"
#include "tools/gn/label.h"
@@ -24,56 +27,6 @@ struct CompareTargetLabel {
}
};
-const Target* GetTargetForDesc(const std::vector<std::string>& args) {
- // Deliberately leaked to avoid expensive process teardown.
- Setup* setup = new Setup;
- if (!setup->DoSetup())
- return NULL;
-
- // FIXME(brettw): set the output dir to be a sandbox one to avoid polluting
- // the real output dir with files written by the build scripts.
-
- // Do the actual load. This will also write out the target ninja files.
- if (!setup->Run())
- return NULL;
-
- // Need to resolve the label after we know the default toolchain.
- // TODO(brettw) find the current directory and resolve the input label
- // relative to that.
- Label default_toolchain = setup->build_settings().toolchain_manager()
- .GetDefaultToolchainUnlocked();
- Value arg_value(NULL, args[0]);
- Err err;
- Label label = Label::Resolve(SourceDir(), default_toolchain, arg_value, &err);
- if (err.has_error()) {
- err.PrintToStdout();
- return NULL;
- }
-
- ItemNode* node;
- {
- base::AutoLock lock(setup->build_settings().item_tree().lock());
- node = setup->build_settings().item_tree().GetExistingNodeLocked(label);
- }
- if (!node) {
- Err(Location(), "",
- "I don't know about this \"" + label.GetUserVisibleName(false) +
- "\"").PrintToStdout();
- return NULL;
- }
-
- const Target* target = node->item()->AsTarget();
- if (!target) {
- Err(Location(), "Not a target.",
- "The \"" + label.GetUserVisibleName(false) + "\" thing\n"
- "is not a target. Somebody should probably implement this command for "
- "other\nitem types.");
- return NULL;
- }
-
- return target;
-}
-
void RecursiveCollectDeps(const Target* target, std::set<Label>* result) {
if (result->find(target->label()) != result->end())
return; // Already did this target.
@@ -99,6 +52,153 @@ void RecursivePrintDeps(const Target* target,
}
}
+void PrintDeps(const Target* target, bool display_header) {
+ Label toolchain_label = target->label().GetToolchainLabel();
+
+ // Tree mode is separate.
+ if (CommandLine::ForCurrentProcess()->HasSwitch("tree")) {
+ if (display_header)
+ OutputString("\nDependency tree:\n");
+ RecursivePrintDeps(target, toolchain_label, 1);
+ return;
+ }
+
+ // Collect the deps to display.
+ std::vector<Label> deps;
+ if (CommandLine::ForCurrentProcess()->HasSwitch("all")) {
+ if (display_header)
+ OutputString("\nAll recursive dependencies:\n");
+
+ std::set<Label> all_deps;
+ RecursiveCollectDeps(target, &all_deps);
+ for (std::set<Label>::iterator i = all_deps.begin();
+ i != all_deps.end(); ++i)
+ deps.push_back(*i);
+ } else {
+ if (display_header) {
+ OutputString("\nDirect dependencies "
+ "(try also \"--all\" and \"--tree\"):\n");
+ }
+
+ const std::vector<const Target*>& target_deps = target->deps();
+ for (size_t i = 0; i < target_deps.size(); i++)
+ deps.push_back(target_deps[i]->label());
+ }
+
+ std::sort(deps.begin(), deps.end());
+ for (size_t i = 0; i < deps.size(); i++)
+ OutputString(" " + deps[i].GetUserVisibleName(toolchain_label) + "\n");
+}
+
+void PrintConfigs(const Target* target, bool display_header) {
+ // Configs (don't sort since the order determines how things are processed).
+ if (display_header)
+ OutputString("\nConfigs (in order applying):\n");
+
+ Label toolchain_label = target->label().GetToolchainLabel();
+ const std::vector<const Config*>& configs = target->configs();
+ for (size_t i = 0; i < configs.size(); i++) {
+ OutputString(" " +
+ configs[i]->label().GetUserVisibleName(toolchain_label) + "\n");
+ }
+}
+
+void PrintSources(const Target* target, bool display_header) {
+ if (display_header)
+ OutputString("\nSources:\n");
+
+ Target::FileList sources = target->sources();
+ std::sort(sources.begin(), sources.end());
+ for (size_t i = 0; i < sources.size(); i++)
+ OutputString(" " + sources[i].value() + "\n");
+}
+
+// Attempts to attribute the gen dependency of the given target to some source
+// code and outputs the string to the output stream.
+//
+// The attribution of the source of the dependencies is stored in the ItemNode
+// which is the parallel structure to the target dependency map, so we have
+// to jump through a few loops to find everything.
+void OutputSourceOfDep(const Target* target,
+ const Label& dep_label,
+ std::ostream& out) {
+ ItemTree& item_tree = target->settings()->build_settings()->item_tree();
+ base::AutoLock lock(item_tree.lock());
+
+ ItemNode* target_node = item_tree.GetExistingNodeLocked(target->label());
+ CHECK(target_node);
+ ItemNode* dep_node = item_tree.GetExistingNodeLocked(dep_label);
+ CHECK(dep_node);
+
+ const ItemNode::ItemNodeMap& direct_deps = target_node->direct_dependencies();
+ ItemNode::ItemNodeMap::const_iterator found = direct_deps.find(dep_node);
+ if (found == direct_deps.end())
+ return;
+
+ const Location& location = found->second.begin();
+ out << " (Added by " + location.file()->name().value() << ":"
+ << location.line_number() << ")\n";
+}
+
+// Templatized writer for writing out different config value types.
+template<typename T> struct DescValueWriter {};
+template<> struct DescValueWriter<std::string> {
+ void operator()(const std::string& str, std::ostream& out) const {
+ out << " " << str << "\n";
+ }
+};
+template<> struct DescValueWriter<SourceFile> {
+ void operator()(const SourceFile& file, std::ostream& out) const {
+ out << " " << file.value() << "\n";
+ }
+};
+template<> struct DescValueWriter<SourceDir> {
+ void operator()(const SourceDir& dir, std::ostream& out) const {
+ out << " " << dir.value() << "\n";
+ }
+};
+
+// Writes a given config value type to the string, optionally with attribution.
+// This should match RecursiveTargetConfigToStream in the order it traverses.
+template<typename T> void OutputRecursiveTargetConfig(
+ const Target* target,
+ const char* header_name,
+ const std::vector<T>& (ConfigValues::* getter)() const) {
+ bool display_blame = CommandLine::ForCurrentProcess()->HasSwitch("blame");
+
+ DescValueWriter<T> writer;
+ std::ostringstream out;
+
+ // First write the values from the config itself.
+ if (!(target->config_values().*getter)().empty()) {
+ if (display_blame)
+ out << " From " << target->label().GetUserVisibleName(false) << "\n";
+ ConfigValuesToStream(target->config_values(), getter, writer, out);
+ }
+
+ // TODO(brettw) annotate where forced config includes came from!
+
+ // Then write the configs in order.
+ for (size_t i = 0; i < target->configs().size(); i++) {
+ const Config* config = target->configs()[i];
+ const ConfigValues& values = config->config_values();
+
+ if (!(values.*getter)().empty()) {
+ if (display_blame) {
+ out << " From " << config->label().GetUserVisibleName(false) << "\n";
+ OutputSourceOfDep(target, config->label(), out);
+ }
+ ConfigValuesToStream(values, getter, writer, out);
+ }
+ }
+
+ std::string out_str = out.str();
+ if (!out_str.empty()) {
+ OutputString(std::string(header_name) + "\n");
+ OutputString(out_str);
+ }
+}
+
} // namespace
// desc ------------------------------------------------------------------------
@@ -107,18 +207,63 @@ const char kDesc[] = "desc";
const char kDesc_HelpShort[] =
"desc: Show lots of insightful information about a target.";
const char kDesc_Help[] =
- "gn desc <target label>\n"
- " Displays all recursive dependencies for a given labeled target.\n"
+ "gn desc <target label> [<what to show>] [--blame] [--all | --tree]\n"
+ " Displays information about a given labeled target.\n"
+ "\n"
+ "Possibilities for <what to show>:\n"
+ " (If unspecified an overall summary will be displayed.)\n"
"\n"
- " See \"gn help\" for the common command-line switches.\n"
+ " sources\n"
+ " Source files.\n"
+ "\n"
+ " configs\n"
+ " Shows configs applied to the given target, sorted in the order\n"
+ " they're specified. This includes both configs specified in the\n"
+ " \"configs\" variable, as well as configs pushed onto this target\n"
+ " via dependencies specifying \"all\" or \"direct\" dependent\n"
+ " configs.\n"
+ "\n"
+ " deps [--all | --tree]\n"
+ " Show immediate (or, when \"--all\" or \"--tree\" is specified,\n"
+ " recursive) dependencies of the given target. \"--tree\" shows them\n"
+ " in a tree format. Otherwise, they will be sorted alphabetically.\n"
+ "\n"
+ " defines [--blame]\n"
+ " includes [--blame]\n"
+ " cflags [--blame]\n"
+ " cflags_cc [--blame]\n"
+ " cflags_cxx [--blame]\n"
+ " ldflags [--blame]\n"
+ " Shows the given values taken from the target and all configs\n"
+ " applying. See \"--blame\" below.\n"
+ "\n"
+ " --blame\n"
+ " Used with any value specified by a config, this will name\n"
+ " the config that specified the value.\n"
+ "\n"
+ "Note:\n"
+ " This command will show the full name of directories and source files,\n"
+ " but when directories and source paths are written to the build file,\n"
+ " they will be adjusted to be relative to the build directory. So the\n"
+ " values for paths displayed by this command won't match (but should\n"
+ " mean the same thing.\n"
"\n"
"Examples:\n"
- " gn desc //base:base\n";
+ " gn desc //base:base\n"
+ " Summarizes the given target.\n"
+ "\n"
+ " gn desc :base_unittests deps --tree\n"
+ " Shows a dependency tree of the \"base_unittests\" project in\n"
+ " the current directory.\n"
+ "\n"
+ " gn desc //base defines --blame\n"
+ " Shows defines set for the //base:base target, annotated by where\n"
+ " each one was set from.\n";
int RunDesc(const std::vector<std::string>& args) {
- if (args.size() != 1) {
+ if (args.size() != 1 && args.size() != 2) {
Err(Location(), "You're holding it wrong.",
- "Usage: \"gn desc <target_name>\"").PrintToStdout();
+ "Usage: \"gn desc <target_name> <what to display>\"").PrintToStdout();
return 1;
}
@@ -126,6 +271,38 @@ int RunDesc(const std::vector<std::string>& args) {
if (!target)
return 1;
+#define CONFIG_VALUE_HANDLER(name) \
+ } else if (what == #name) { \
+ OutputRecursiveTargetConfig(target, #name, &ConfigValues::name);
+
+ if (args.size() == 2) {
+ // User specified one thing to display.
+ const std::string& what = args[1];
+ if (what == "configs") {
+ PrintConfigs(target, false);
+ } else if (what == "sources") {
+ PrintSources(target, false);
+ } else if (what == "deps") {
+ PrintDeps(target, false);
+
+ CONFIG_VALUE_HANDLER(defines)
+ CONFIG_VALUE_HANDLER(includes)
+ CONFIG_VALUE_HANDLER(cflags)
+ CONFIG_VALUE_HANDLER(cflags_c)
+ CONFIG_VALUE_HANDLER(cflags_cc)
+ CONFIG_VALUE_HANDLER(ldflags)
+
+ } else {
+ OutputString("Don't know how to display \"" + what + "\".\n");
+ return 1;
+ }
+
+#undef CONFIG_VALUE_HANDLER
+ return 0;
+ }
+
+ // Display summary.
+
// Generally we only want to display toolchains on labels when the toolchain
// is different than the default one for this target (which we always print
// in the header).
@@ -141,105 +318,12 @@ int RunDesc(const std::vector<std::string>& args) {
OutputString(std::string(
std::max(title_target.size(), title_toolchain.size()), '=') + "\n");
- OutputString("Sources:\n");
- const Target::FileList& sources = target->sources();
- for (size_t i = 0; i < sources.size(); i++)
- OutputString(" " + sources[i].value() + "\n");
-
- // Configs (don't sort since the order determines how things are processed).
- OutputString("\nConfigs:\n");
- const std::vector<const Config*>& configs = target->configs();
- for (size_t i = 0; i < configs.size(); i++) {
- OutputString(" " +
- configs[i]->label().GetUserVisibleName(target_toolchain) + "\n");
- }
-
- // Deps. Sorted for convenience. Sort the labels rather than the strings so
- // that "//foo:bar" comes before "//foo/third_party:bar".
- OutputString("\nDirect dependencies:\n"
- "(Use \"gn deps\" or \"gn tree\" to display recursive deps.)\n");
- const std::vector<const Target*>& deps = target->deps();
- std::vector<Label> sorted_deps;
- for (size_t i = 0; i < deps.size(); i++)
- sorted_deps.push_back(deps[i]->label());
- std::sort(sorted_deps.begin(), sorted_deps.end());
- for (size_t i = 0; i < sorted_deps.size(); i++) {
- OutputString(" " + sorted_deps[i].GetUserVisibleName(target_toolchain) +
- "\n");
- }
- return 0;
-}
-
-// deps ------------------------------------------------------------------------
-
-const char kDeps[] = "deps";
-const char kDeps_HelpShort[] =
- "deps: Show all recursive dependencies of a target.";
-const char kDeps_Help[] =
- "gn deps <target label>\n"
- " Displays all recursive dependencies for a given labeled target.\n"
- "\n"
- " See \"gn help\" for the common command-line switches.\n"
- "\n"
- "Examples:\n"
- " gn deps //base:base\n";
-
-int RunDeps(const std::vector<std::string>& args) {
- if (args.size() != 1) {
- Err(Location(), "You're holding it wrong.",
- "Usage: \"gn deps <target_name>\"").PrintToStdout();
- return 1;
- }
-
- const Target* target = GetTargetForDesc(args);
- if (!target)
- return 1;
-
- // Generally we only want to display toolchains on labels when the toolchain
- // is different than the default one for this target (which we always print
- // in the header).
- Label target_toolchain = target->label().GetToolchainLabel();
-
- std::set<Label> all_deps;
- RecursiveCollectDeps(target, &all_deps);
-
- OutputString("Recursive dependencies of " +
- target->label().GetUserVisibleName(true) + "\n",
- DECORATION_YELLOW);
-
- for (std::set<Label>::iterator i = all_deps.begin();
- i != all_deps.end(); ++i)
- OutputString(" " + i->GetUserVisibleName(target_toolchain) + "\n");
- return 0;
-}
-
-// tree ------------------------------------------------------------------------
-
-const char kTree[] = "tree";
-const char kTree_HelpShort[] =
- "tree: Show dependency tree for a target.";
-const char kTree_Help[] =
- "gn tree <target label>\n"
- " Displays a dependecy tree for the given labeled target.\n"
- "\n"
- " See \"gn help\" for the common command-line switches.\n"
- "\n"
- "Examples:\n"
- " gn tree //base:base\n";
-
-int RunTree(const std::vector<std::string>& args) {
- if (args.size() != 1) {
- Err(Location(), "You're holding it wrong.",
- "Usage: \"gn tree <target_name>\"").PrintToStdout();
- return 1;
- }
-
- const Target* target = GetTargetForDesc(args);
- if (!target)
- return 1;
-
- OutputString(target->label().GetUserVisibleName(false) + "\n");
- RecursivePrintDeps(target, target->label().GetToolchainLabel(), 1);
+ PrintSources(target, true);
+ PrintConfigs(target, true);
+ OutputString("\n (Use \"gn desc <label> <thing you want to see>\" to show "
+ "the actual values\n applied by the different configs. "
+ "See \"gn help desc\" for more.)\n");
+ PrintDeps(target, true);
return 0;
}
diff --git a/tools/gn/commands.cc b/tools/gn/commands.cc
index fc0bec1..cfa55cb 100644
--- a/tools/gn/commands.cc
+++ b/tools/gn/commands.cc
@@ -4,6 +4,13 @@
#include "tools/gn/commands.h"
+#include "tools/gn/item.h"
+#include "tools/gn/item_node.h"
+#include "tools/gn/label.h"
+#include "tools/gn/setup.h"
+#include "tools/gn/standard_out.h"
+#include "tools/gn/target.h"
+
namespace commands {
CommandInfo::CommandInfo()
@@ -28,15 +35,63 @@ const CommandInfoMap& GetCommands() {
k##cmd##_Help, \
&Run##cmd);
- INSERT_COMMAND(Deps)
INSERT_COMMAND(Desc)
INSERT_COMMAND(Gen)
INSERT_COMMAND(Help)
- INSERT_COMMAND(Tree)
#undef INSERT_COMMAND
}
return info_map;
}
+const Target* GetTargetForDesc(const std::vector<std::string>& args) {
+ // Deliberately leaked to avoid expensive process teardown.
+ Setup* setup = new Setup;
+ if (!setup->DoSetup())
+ return NULL;
+
+ // FIXME(brettw): set the output dir to be a sandbox one to avoid polluting
+ // the real output dir with files written by the build scripts.
+
+ // Do the actual load. This will also write out the target ninja files.
+ if (!setup->Run())
+ return NULL;
+
+ // Need to resolve the label after we know the default toolchain.
+ // TODO(brettw) find the current directory and resolve the input label
+ // relative to that.
+ Label default_toolchain = setup->build_settings().toolchain_manager()
+ .GetDefaultToolchainUnlocked();
+ Value arg_value(NULL, args[0]);
+ Err err;
+ Label label = Label::Resolve(SourceDir(), default_toolchain, arg_value, &err);
+ if (err.has_error()) {
+ err.PrintToStdout();
+ return NULL;
+ }
+
+ ItemNode* node;
+ {
+ base::AutoLock lock(setup->build_settings().item_tree().lock());
+ node = setup->build_settings().item_tree().GetExistingNodeLocked(label);
+ }
+ if (!node) {
+ Err(Location(), "",
+ "I don't know about this \"" + label.GetUserVisibleName(false) +
+ "\"").PrintToStdout();
+ return NULL;
+ }
+
+ const Target* target = node->item()->AsTarget();
+ if (!target) {
+ Err(Location(), "Not a target.",
+ "The \"" + label.GetUserVisibleName(false) + "\" thing\n"
+ "is not a target. Somebody should probably implement this command for "
+ "other\nitem types.");
+ return NULL;
+ }
+
+ return target;
+}
+
} // namespace commands
diff --git a/tools/gn/commands.h b/tools/gn/commands.h
index c767742..1a30389 100644
--- a/tools/gn/commands.h
+++ b/tools/gn/commands.h
@@ -11,17 +11,14 @@
#include "base/strings/string_piece.h"
+class Target;
+
// Each "Run" command returns the value we should return from main().
namespace commands {
typedef int (*CommandRunner)(const std::vector<std::string>&);
-extern const char kDeps[];
-extern const char kDeps_HelpShort[];
-extern const char kDeps_Help[];
-int RunDeps(const std::vector<std::string>& args);
-
extern const char kDesc[];
extern const char kDesc_HelpShort[];
extern const char kDesc_Help[];
@@ -37,11 +34,6 @@ extern const char kHelp_HelpShort[];
extern const char kHelp_Help[];
int RunHelp(const std::vector<std::string>& args);
-extern const char kTree[];
-extern const char kTree_HelpShort[];
-extern const char kTree_Help[];
-int RunTree(const std::vector<std::string>& args);
-
// -----------------------------------------------------------------------------
struct CommandInfo {
@@ -59,6 +51,17 @@ typedef std::map<base::StringPiece, CommandInfo> CommandInfoMap;
const CommandInfoMap& GetCommands();
+// Helper functions for some commands ------------------------------------------
+
+// Runs a build for the given command line, returning the target identified by
+// the first non-switch command line parameter.
+//
+// Note that a lot of memory is leaked to avoid proper teardown under the
+// assumption that you will only run this once and exit.
+//
+// On failure, prints an error message and returns NULL.
+const Target* GetTargetForDesc(const std::vector<std::string>& args);
+
} // namespace commands
#endif // TOOLS_GN_COMMANDS_H_
diff --git a/tools/gn/config.cc b/tools/gn/config.cc
index 80de2a0..6edba24 100644
--- a/tools/gn/config.cc
+++ b/tools/gn/config.cc
@@ -71,7 +71,7 @@ Config* Config::GetConfig(const Settings* settings,
// Keep a record of the guy asking us for this dependency. We know if
// somebody is adding a dependency, that guy it himself not resolved.
- if (dep_from && node->state() != ItemNode::RESOLVED) {
+ if (dep_from) {
if (!tree->GetExistingNodeLocked(dep_from->label())->AddDependency(
settings->build_settings(), specified_from_here, node, err))
return NULL;
diff --git a/tools/gn/config_values_extractors.h b/tools/gn/config_values_extractors.h
index 0eaa2c9..4698f8c 100644
--- a/tools/gn/config_values_extractors.h
+++ b/tools/gn/config_values_extractors.h
@@ -24,21 +24,26 @@ inline void ConfigValuesToStream(
writer(v[i], out);
};
+// Writes a given config value that applies to a given target. This collects
+// all values from the target itself and all configs that apply, and writes
+// then in order.
template<typename T, class Writer>
inline void RecursiveTargetConfigToStream(
const Target* target,
const std::vector<T>& (ConfigValues::* getter)() const,
const Writer& writer,
std::ostream& out) {
- // Write all configs in reverse order (to get oldest first, which will look
- // more normal in the output).
- for (int i = static_cast<int>(target->configs().size() - 1); i >= 0; i--) {
+ // Note: if you make any changes to this, also change the writer in the
+ // implementation of the "desc" command.
+
+ // First write the values from the config itself.
+ ConfigValuesToStream(target->config_values(), getter, writer, out);
+
+ // Then write the configs in order.
+ for (size_t i = 0; i < target->configs().size(); i++) {
ConfigValuesToStream(target->configs()[i]->config_values(), getter,
writer, out);
}
-
- // Last write from the config from the Target itself, if any.
- ConfigValuesToStream(target->config_values(), getter, writer, out);
}
// Writes the values out as strings with no transformation.
diff --git a/tools/gn/filesystem_utils.cc b/tools/gn/filesystem_utils.cc
index 625a358..a108959 100644
--- a/tools/gn/filesystem_utils.cc
+++ b/tools/gn/filesystem_utils.cc
@@ -100,6 +100,24 @@ SourceFileType GetSourceFileType(const SourceFile& file,
const char* GetExtensionForOutputType(Target::OutputType type,
Settings::TargetOS os) {
switch (os) {
+ case Settings::MAC:
+ switch (type) {
+ case Target::NONE:
+ NOTREACHED();
+ return "";
+ case Target::EXECUTABLE:
+ return "";
+ case Target::SHARED_LIBRARY:
+ return "dylib";
+ case Target::STATIC_LIBRARY:
+ return "a";
+ case Target::LOADABLE_MODULE:
+ return "dylib"; // TODO(brettw) what's this?
+ default:
+ NOTREACHED();
+ }
+ break;
+
case Settings::WIN:
switch (type) {
case Target::NONE:
diff --git a/tools/gn/gn_main.cc b/tools/gn/gn_main.cc
index 5fa1e00..c0300ca 100644
--- a/tools/gn/gn_main.cc
+++ b/tools/gn/gn_main.cc
@@ -29,10 +29,14 @@ int main(int argc, char** argv) {
base::AtExitManager at_exit;
CommandLine::Init(argc, argv);
- std::vector<std::string> args = GetArgs(*CommandLine::ForCurrentProcess());
+ const CommandLine& cmdline = *CommandLine::ForCurrentProcess();
+ std::vector<std::string> args = GetArgs(cmdline);
std::string command;
- if (args.empty()) {
+ if (cmdline.HasSwitch("help")) {
+ // Make "--help" default to help command.
+ command = commands::kHelp;
+ } else if (args.empty()) {
command = commands::kGen;
} else {
command = args[0];
diff --git a/tools/gn/item_tree.h b/tools/gn/item_tree.h
index 9f3835f..4a8f9fb 100644
--- a/tools/gn/item_tree.h
+++ b/tools/gn/item_tree.h
@@ -43,7 +43,7 @@ class ItemTree {
~ItemTree();
// This lock must be held when calling the "Locked" functions below.
- base::Lock& lock() { return lock_; }
+ base::Lock& lock() const { return lock_; }
// Returns NULL if the item is not found.
//
diff --git a/tools/gn/ninja_helper.cc b/tools/gn/ninja_helper.cc
index c27c0e4..65e06c0 100644
--- a/tools/gn/ninja_helper.cc
+++ b/tools/gn/ninja_helper.cc
@@ -114,6 +114,14 @@ OutputFile NinjaHelper::GetTargetOutputFile(const Target* target) const {
return ret;
}
+ // This is prepended to the output file name.
+ const char* prefix;
+ if (target->settings()->IsWin()) {
+ prefix = "";
+ } else {
+ prefix = "lib";
+ }
+
const char* extension;
if (target->output_type() == Target::NONE ||
target->output_type() == Target::COPY_FILES ||
@@ -136,20 +144,26 @@ OutputFile NinjaHelper::GetTargetOutputFile(const Target* target) const {
target->output_type() == Target::STATIC_LIBRARY)) ||
(target->settings()->IsWin() &&
target->output_type() == Target::SHARED_LIBRARY)) {
- // Generate a name like "<toolchain>/<name>.<extension>".
+ // Generate a name like "<toolchain>/<prefix><name>.<extension>".
+ ret.value().append(prefix);
ret.value().append(target->label().name());
- ret.value().push_back('.');
- ret.value().append(extension);
+ if (extension[0]) {
+ ret.value().push_back('.');
+ ret.value().append(extension);
+ }
return ret;
}
// Libraries go into the library subdirectory like
- // "<toolchain>/lib/<name>.<extension>".
+ // "<toolchain>/lib/<prefix><name>.<extension>".
if (target->output_type() == Target::SHARED_LIBRARY) {
ret.value().append(kLibDirWithSlash);
+ ret.value().append(prefix);
ret.value().append(target->label().name());
- ret.value().push_back('.');
- ret.value().append(extension);
+ if (extension[0]) {
+ ret.value().push_back('.');
+ ret.value().append(extension);
+ }
return ret;
}
@@ -159,7 +173,9 @@ OutputFile NinjaHelper::GetTargetOutputFile(const Target* target) const {
AppendStringPiece(&ret.value(),
target->label().dir().SourceAbsoluteWithOneSlash());
ret.value().append(target->label().name());
- ret.value().push_back('.');
- ret.value().append(extension);
+ if (extension[0]) {
+ ret.value().push_back('.');
+ ret.value().append(extension);
+ }
return ret;
}
diff --git a/tools/gn/ninja_target_writer.cc b/tools/gn/ninja_target_writer.cc
index d7fede9..d226e2b 100644
--- a/tools/gn/ninja_target_writer.cc
+++ b/tools/gn/ninja_target_writer.cc
@@ -77,7 +77,9 @@ NinjaTargetWriter::~NinjaTargetWriter() {
}
void NinjaTargetWriter::Run() {
- out_ << "arch = environment.x86\n";
+ // TODO(brettw) have a better way to do the environment setup on Windows.
+ if (target_->settings()->IsWin())
+ out_ << "arch = environment.x86\n";
if (target_->output_type() == Target::COPY_FILES) {
WriteCopyRules();
@@ -418,10 +420,10 @@ void NinjaTargetWriter::WriteLinkerStuff(
// Linker flags, append manifest flag on Windows to reference our file.
out_ << "ldflags =";
RecursiveTargetConfigStringsToStream(target_, &ConfigValues::ldflags, out_);
- if (settings_->IsWin())
+ // HACK ERASEME BRETTW FIXME
+ if (settings_->IsWin()) {
out_ << " /MANIFEST /ManifestFile:";
path_output_.WriteFile(out_, windows_manifest);
- { // HACK ERASEME BRETTW FIXME
out_ << " /DEBUG /MACHINE:X86 /LIBPATH:\"C:\\Program Files (x86)\\Windows Kits\\8.0\\Lib\\win8\\um\\x86\" /DELAYLOAD:dbghelp.dll /DELAYLOAD:dwmapi.dll /DELAYLOAD:shell32.dll /DELAYLOAD:uxtheme.dll /safeseh /dynamicbase /ignore:4199 /ignore:4221 /nxcompat /SUBSYSTEM:CONSOLE /INCREMENTAL /FIXED:NO /DYNAMICBASE:NO wininet.lib dnsapi.lib version.lib msimg32.lib ws2_32.lib usp10.lib psapi.lib dbghelp.lib winmm.lib shlwapi.lib kernel32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib user32.lib uuid.lib odbc32.lib odbccp32.lib delayimp.lib /NXCOMPAT";
}
out_ << std::endl;
@@ -441,7 +443,7 @@ void NinjaTargetWriter::WriteLinkerStuff(
if (settings_->IsWin()) {
internal_output_file = OutputFile(target_->label().name() + ".dll");
} else {
- NOTREACHED(); // TODO(brettw) write this.
+ internal_output_file = external_output_file;
}
} else {
internal_output_file = external_output_file;
diff --git a/tools/gn/secondary/build/config/BUILD.gn b/tools/gn/secondary/build/config/BUILD.gn
index 74c57af..94cb397 100644
--- a/tools/gn/secondary/build/config/BUILD.gn
+++ b/tools/gn/secondary/build/config/BUILD.gn
@@ -1,8 +1,4 @@
config("my_msvs") {
- includes = [ "../.." ]
- cflags = [
- "/Od", "/WX", "/Zi", "/Gy", "/GS", "/RTC1", "/EHsc",
- ]
defines = [
"CHROMIUM_BUILD",
"TOOLKIT_VIEWS=1",
diff --git a/tools/gn/secondary/build/config/BUILDCONFIG.gn b/tools/gn/secondary/build/config/BUILDCONFIG.gn
index 0245597..555a924 100644
--- a/tools/gn/secondary/build/config/BUILDCONFIG.gn
+++ b/tools/gn/secondary/build/config/BUILDCONFIG.gn
@@ -13,9 +13,11 @@
# Use "is_*" names for intrinsic platform descriptions and build modes, and
# "use_*" names for optional features libraries, and configurations.
declare_args() {
+ is_android = 0
is_component_build = 1
is_chromeos = 0
is_debug = 1
+ is_ios = 0
use_ash = 0
use_aura = 0
use_ozone = 0
@@ -151,19 +153,24 @@ if (is_component_build) {
native_compiler_configs = [
"//build/config:my_msvs", # TODO(brettw) eraseme
+ "//build/config/compiler:compiler",
"//build/config/compiler:chromium_code",
- "//build/config/compiler:disable_annoying_warnings",
+ "//build/config/compiler:default_warnings",
"//build/config/compiler:no_rtti",
"//build/config/compiler:runtime_library",
]
if (is_win) {
native_compiler_configs += "//build/config/win:sdk"
+} else if (is_mac) {
+ # TODO(brettw) this should be in an if (is_clang) block instead but I haven't
+ # written an is_clang flag yet.
+ native_compiler_configs += "//build/config/clang:find_bad_constructs"
}
if (is_debug) {
native_compiler_configs += "//build/config:debug"
} else {
- native_compiler_configs += "//build/config::release"
+ native_compiler_configs += "//build/config:release"
}
set_defaults("executable") {
@@ -184,4 +191,6 @@ set_defaults("shared_library") {
if (is_win) {
set_default_toolchain("//build/config/win:32")
+} else if (is_mac) {
+ set_default_toolchain("//build/config/mac:clang")
}
diff --git a/tools/gn/secondary/build/config/compiler/BUILD.gn b/tools/gn/secondary/build/config/compiler/BUILD.gn
index 0487828..43bee6e 100644
--- a/tools/gn/secondary/build/config/compiler/BUILD.gn
+++ b/tools/gn/secondary/build/config/compiler/BUILD.gn
@@ -1,134 +1,242 @@
-# Copyright (c) 2013 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.
-
-# runtime_library -------------------------------------------------------------
-#
-# Sets the runtime library and associated options.
-#
-# We don't bother making multiple versions that are toggle-able since there
-# is more than one axis of control (which makes it complicated) and there's
-# no practical reason for anybody to change this since the CRT must agree.
-
-config("runtime_library") {
- if (is_component_build) {
- # Component mode: dynamic CRT.
- defines = [ "COMPONENT_BUILD" ]
- if (is_win) {
- # Since the library is shared, it requires exceptions or will give errors
- # about things not matching, so keep exceptions on.
- if (is_debug) {
- cflags = [ "/MDd" ]
- } else {
- cflags = [ "/MD" ]
- }
- }
- } else {
- # Static CRT.
- if (is_win) {
- # We don't use exceptions, and when we link statically we can just get
- # rid of them entirely.
- defines = [ "_HAS_EXCEPTIONS=0" ]
- if (is_debug) {
- cflags = [ "/MTd" ]
- } else {
- cflags = [ "/MT" ]
- }
- }
- }
-
- if (is_win) {
- defines += [
- "__STD_C",
- "__STDC_CONSTANT_MACROS",
- "__STDC_FORMAT_MACROS",
- "_CRT_RAND_S",
- "_CRT_SECURE_NO_DEPRECATE",
- "_SCL_SECURE_NO_DEPRECATE",
- "_UNICODE",
- "UNICODE",
- ]
- }
-}
-
-# chromium_code ---------------------------------------------------------------
-#
-# Toggles between higher and lower warnings for code that is (or isn't)
-# part of Chromium.
-
-config("chromium_code") {
- if (is_win) {
- cflags = [
- "/W4", # Warning level 4.
- ]
- }
-}
-config("no_chromium_code") {
- if (is_win) {
- cflags = [
- "/W3", # Warning level 3.
- "/wd4800", # Disable warning when forcing value to bool.
- ]
- defines = [
- "_CRT_NONSTDC_NO_WARNINGS",
- "_CRT_NONSTDC_NO_DEPRECATE",
- ]
- }
-}
-
-# rtti ------------------------------------------------------------------------
-#
-# Allows turning Run-Time Type Identification on or off.
-
-config("rtti") {
- if (is_win) {
- cflags = [ "/GR" ]
- }
-}
-config("no_rtti") {
- if (is_win) {
- cflags = [ "/GR-" ]
- }
-}
-
-# Warnings ---------------------------------------------------------------------
-
-config("disable_annoying_warnings") {
- if (is_win) {
- # Please keep ordered and add names if you add more.
- cflags = [
- "/wd4018", # Comparing signed and unsigned values.
- "/wd4100", # Unreferenced formal function parameter.
- "/wd4121", # Alignment of a member was sensitive to packing.
- "/wd4125", # Decimal digit terminates octal escape sequence.
- "/wd4127", # Conditional expression is constant.
- "/wd4130", # Logical operation on address of string constant.
- # TODO(brettw) is this necessary? If so, it should probably be on whoever
- # is silly enough to be doing this rather than globally.
- #"/wd4131", # Function uses old-style declarator.
- "/wd4189", # A variable was declared and initialized but never used.
- "/wd4201", # Nonstandard extension used: nameless struct/union.
- "/wd4238", # Nonstandard extension used: class rvalue used as lvalue.
- "/wd4244", # Conversion: possible loss of data.
- "/wd4245", # Conversion: signed/unsigned mismatch,
- "/wd4251", # Class needs to have dll-interface.
- "/wd4310", # Cast truncates constant value.
- "/wd4351", # Elements of array will be default initialized.
- "/wd4355", # 'this' used in base member initializer list.
- "/wd4396", # Inline friend template thing.
- "/wd4428", # Universal character name encountered in source.
- "/wd4481", # Nonstandard extension: override specifier.
- "/wd4503", # Decorated name length exceeded, name was truncated.
- "/wd4505", # Unreferenced local function has been removed.
- "/wd4510", # Default constructor could not be generated.
- "/wd4512", # Assignment operator could not be generated.
- "/wd4530", # Exception handler used, but unwind semantics not enabled.
- "/wd4610", # Class can never be instantiated, constructor required.
- "/wd4611", # C++ object destruction and 'catch'.
- "/wd4701", # Potentially uninitialized local variable name used.
- "/wd4702", # Unreachable code.
- "/wd4706", # Assignment within conditional expression.
- "/wd4819", # Character not in the current code page.
- ]
- }
-}
+# Copyright (c) 2013 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.
+
+# Base compiler configuration.
+config("compiler") {
+ includes = [ "//" ]
+ if (is_win) {
+ cflags = [
+ # TODO(brettw) these probably need to be refactored.
+ "/Od", "/WX", "/Zi", "/Gy", "/GS", "/RTC1", "/EHsc",
+ ]
+ } else {
+ cflags = [
+ # TODO(brettw) obviously this needs to be parameterized.
+ "-arch i386",
+
+ # See http://crbug.com/32204
+ "-fno-strict-aliasing",
+
+ "-fno-threadsafe-statics",
+ "-fstack-protector-all",
+ "-fvisibility-hidden",
+ "-fvisibility-inlines-hidden",
+ ]
+ # !!! Please keep additions sorted alphabetically.
+
+ # TODO(brettw) these should be clang-only.
+ # if (is_clang) {
+ cflags += [
+ "-fcolor-diagnostics",
+ ]
+ #}
+
+ cflags_c = [
+ "-std=c99",
+ ]
+
+ cflags_cc = [
+ "-fno-exceptions",
+ "-std=gnu++11",
+ ]
+ }
+
+ if (is_mac) {
+ cflags += [
+ # Set which SDK to use.
+ # TODO(brettw) this needs to be configurable somehow.
+ "-isysroot", "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.7.sdk",
+
+ "-mmacosx-version-min=10.6",
+ ]
+ }
+}
+
+# runtime_library -------------------------------------------------------------
+#
+# Sets the runtime library and associated options.
+#
+# We don't bother making multiple versions that are toggle-able since there
+# is more than one axis of control (which makes it complicated) and there's
+# no practical reason for anybody to change this since the CRT must agree.
+
+config("runtime_library") {
+ if (is_component_build) {
+ # Component mode: dynamic CRT.
+ defines = [ "COMPONENT_BUILD" ]
+ if (is_win) {
+ # Since the library is shared, it requires exceptions or will give errors
+ # about things not matching, so keep exceptions on.
+ if (is_debug) {
+ cflags = [ "/MDd" ]
+ } else {
+ cflags = [ "/MD" ]
+ }
+ }
+ } else {
+ # Static CRT.
+ if (is_win) {
+ # We don't use exceptions, and when we link statically we can just get
+ # rid of them entirely.
+ defines = [ "_HAS_EXCEPTIONS=0" ]
+ if (is_debug) {
+ cflags = [ "/MTd" ]
+ } else {
+ cflags = [ "/MT" ]
+ }
+ }
+ }
+
+ if (is_win) {
+ defines += [
+ "__STD_C",
+ "__STDC_CONSTANT_MACROS",
+ "__STDC_FORMAT_MACROS",
+ "_CRT_RAND_S",
+ "_CRT_SECURE_NO_DEPRECATE",
+ "_SCL_SECURE_NO_DEPRECATE",
+ "_UNICODE",
+ "UNICODE",
+ ]
+ }
+}
+
+# chromium_code ---------------------------------------------------------------
+#
+# Toggles between higher and lower warnings for code that is (or isn't)
+# part of Chromium.
+
+config("chromium_code") {
+ if (is_win) {
+ cflags = [
+ "/W4", # Warning level 4.
+ ]
+ } else if (is_mac) {
+ cflags = [
+ "-Werror",
+ "-Wextra",
+ ]
+ }
+}
+config("no_chromium_code") {
+ if (is_win) {
+ cflags = [
+ "/W3", # Warning level 3.
+ "/wd4800", # Disable warning when forcing value to bool.
+ ]
+ defines = [
+ "_CRT_NONSTDC_NO_WARNINGS",
+ "_CRT_NONSTDC_NO_DEPRECATE",
+ ]
+ }
+}
+
+# rtti ------------------------------------------------------------------------
+#
+# Allows turning Run-Time Type Identification on or off.
+
+config("rtti") {
+ if (is_win) {
+ cflags_cc = [ "/GR" ]
+ }
+}
+config("no_rtti") {
+ if (is_win) {
+ cflags_cc = [ "/GR-" ]
+ } else {
+ cflags_cc = [ "-fno-rtti" ]
+ }
+}
+
+# Warnings ---------------------------------------------------------------------
+
+config("default_warnings") {
+ if (is_win) {
+ # Please keep ordered and add names if you add more.
+ cflags = [
+ "/wd4018", # Comparing signed and unsigned values.
+ "/wd4100", # Unreferenced formal function parameter.
+ "/wd4121", # Alignment of a member was sensitive to packing.
+ "/wd4125", # Decimal digit terminates octal escape sequence.
+ "/wd4127", # Conditional expression is constant.
+ "/wd4130", # Logical operation on address of string constant.
+ # TODO(brettw) is this necessary? If so, it should probably be on whoever
+ # is silly enough to be doing this rather than globally.
+ #"/wd4131", # Function uses old-style declarator.
+ "/wd4189", # A variable was declared and initialized but never used.
+ "/wd4201", # Nonstandard extension used: nameless struct/union.
+ "/wd4238", # Nonstandard extension used: class rvalue used as lvalue.
+ "/wd4244", # Conversion: possible loss of data.
+ "/wd4245", # Conversion: signed/unsigned mismatch,
+ "/wd4251", # Class needs to have dll-interface.
+ "/wd4310", # Cast truncates constant value.
+ "/wd4351", # Elements of array will be default initialized.
+ "/wd4355", # 'this' used in base member initializer list.
+ "/wd4396", # Inline friend template thing.
+ "/wd4428", # Universal character name encountered in source.
+ "/wd4481", # Nonstandard extension: override specifier.
+ "/wd4503", # Decorated name length exceeded, name was truncated.
+ "/wd4505", # Unreferenced local function has been removed.
+ "/wd4510", # Default constructor could not be generated.
+ "/wd4512", # Assignment operator could not be generated.
+ "/wd4530", # Exception handler used, but unwind semantics not enabled.
+ "/wd4610", # Class can never be instantiated, constructor required.
+ "/wd4611", # C++ object destruction and 'catch'.
+ "/wd4701", # Potentially uninitialized local variable name used.
+ "/wd4702", # Unreachable code.
+ "/wd4706", # Assignment within conditional expression.
+ "/wd4819", # Character not in the current code page.
+ ]
+ }
+
+ # TODO(brettw) this should probably be if(clang).
+ if (is_mac) {
+ cflags = [
+ # Warn for weird old-style text after an #endif.
+ "-Wendif-labels",
+
+ "-Wnewline-eof",
+
+ # Don't warn about the "struct foo f = {0};" initialization pattern.
+ "-Wno-missing-field-initializers",
+
+ # Don't warn about unused function parameters.
+ "-Wno-unused-parameter",
+ ]
+
+ # TODO(brettw) Ones below here should be clang-only when we have a flag
+ # for it.
+ #if (is_clang) {
+ cflags += [
+ "-Wheader-hygiene",
+
+ # This warns on using ints as initializers for floats in
+ # initializer lists (e.g. |int a = f(); CGSize s = { a, a };|),
+ # which happens in several places in chrome code. Not sure if
+ # this is worth fixing.
+ "-Wno-c++11-narrowing",
+
+ # Don't die on dtoa code that uses a char as an array index.
+ # This is required solely for base/third_party/dmg_fp/dtoa.cc.
+ # TODO(brettw) move this to that project then!
+ "-Wno-char-subscripts",
+
+ # Warns on switches on enums that cover all enum values but
+ # also contain a default: branch. Chrome is full of that.
+ "-Wno-covered-switch-default",
+
+ # Clang considers the `register` keyword as deprecated, but e.g.
+ # code generated by flex (used in angle) contains that keyword.
+ # http://crbug.com/255186
+ "-Wno-deprecated-register",
+
+ # Clang spots more unused functions.
+ "-Wno-unused-function",
+
+ # Warns when a const char[] is converted to bool.
+ "-Wstring-conversion",
+ ]
+ #} #is_clang
+ }
+}
diff --git a/tools/gn/secondary/build/config/mac/BUILD.gn b/tools/gn/secondary/build/config/mac/BUILD.gn
new file mode 100644
index 0000000..7e13aed
--- /dev/null
+++ b/tools/gn/secondary/build/config/mac/BUILD.gn
@@ -0,0 +1,74 @@
+# Copyright (c) 2013 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.
+
+cc = "../../third_party/llvm-build/Release+Asserts/bin/clang"
+cxx = "../../third_party/llvm-build/Release+Asserts/bin/clang++"
+
+toolchain("clang") {
+ tool("cc") {
+ command = "$cc -MMD -MF \$out.d \$defines \$includes \$cflags \$cflags_c \$cflags_pch_c -c \$in -o \$out"
+ description = "CC \$out"
+ depfile = "\$out.d"
+ deps = "gcc"
+ }
+ tool("cxx") {
+ command = "$cxx -MMD -MF \$out.d \$defines \$includes \$cflags \$cflags_cc \$cflags_pch_cc -c \$in -o \$out"
+ description = "CXX \$out"
+ depfile = "\$out.d"
+ deps = "gcc"
+ }
+ tool("objc") {
+ command = "$cc -MMD -MF \$out.d \$defines \$includes \$cflags \$cflags_objc \$cflags_pch_objc -c \$in -o \$out"
+ description = "OBJC \$out"
+ depfile = "\$out.d"
+ deps = "gcc"
+ }
+ tool("objcxx") {
+ command = "$cxx -MMD -MF \$out.d \$defines \$includes \$cflags \$cflags_objcc \$cflags_pch_objcc -c \$in -o \$out"
+ description = "OBJCXX \$out"
+ depfile = "\$out.d"
+ deps = "gcc"
+ }
+ tool("alink") {
+ command = "rm -f \$out && ./gyp-mac-tool filter-libtool libtool \$libtool_flags -static -o \$out \$in\$postbuilds"
+ description = "LIBTOOL-STATIC \$out, POSTBUILDS"
+ }
+ tool("solink") {
+ command = "if [ ! -e \$lib -o ! -e \${lib}.TOC ] || otool -l \$lib | grep -q LC_REEXPORT_DYLIB ; then \$ld -shared \$ldflags -o \$lib \$in \$solibs \$libs\$postbuilds && { otool -l \$lib | grep LC_ID_DYLIB -A 5; nm -gP \$lib | cut -f1-2 -d' ' | grep -v U\$\$; true; } > \${lib}.TOC; else \$ld -shared \$ldflags -o \$lib \$in \$solibs \$libs\$postbuilds && { otool -l \$lib | grep LC_ID_DYLIB -A 5; nm -gP \$lib | cut -f1-2 -d' ' | grep -v U\$\$; true; } > \${lib}.tmp && if ! cmp -s \${lib}.tmp \${lib}.TOC; then mv \${lib}.tmp \${lib}.TOC ; fi; fi"
+ description = "SOLINK \$lib, POSTBUILDS"
+ #pool = "link_pool"
+ restat = "1"
+ }
+ tool("solink_module") {
+ command = "if [ ! -e \$lib -o ! -e \${lib}.TOC ] || otool -l \$lib | grep -q LC_REEXPORT_DYLIB ; then \$ld -shared \$ldflags -o \$lib \$in \$solibs \$libs\$postbuilds && { otool -l \$lib | grep LC_ID_DYLIB -A 5; nm -gP \$lib | cut -f1-2 -d' ' | grep -v U\$\$; true; } > \${lib}.TOC; else \$ld -shared \$ldflags -o \$lib \$in \$solibs \$libs\$postbuilds && { otool -l \$lib | grep LC_ID_DYLIB -A 5; nm -gP \$lib | cut -f1-2 -d' ' | grep -v U\$\$; true; } > \${lib}.tmp && if ! cmp -s \${lib}.tmp \${lib}.TOC; then mv \${lib}.tmp \${lib}.TOC ; fi; fi"
+ description = "SOLINK(module) \$lib, POSTBUILDS"
+ #pool = "link_pool"
+ restat = "1"
+ }
+ tool("link") {
+ command = "\$ld \$ldflags -o \$out \$in \$solibs \$libs\$postbuilds"
+ description = "LINK \$out, POSTBUILDS"
+ #pool = "link_pool"
+ }
+ #tool("infoplist") {
+ # command = "$cc -E -P -Wno-trigraphs -x c \$defines \$in -o \$out && plutil -convert xml1 \$out \$out"
+ # description = "INFOPLIST \$out"
+ #}
+ #tool("mac_tool") {
+ # command = "\$env ./gyp-mac-tool \$mactool_cmd \$in \$out"
+ # description = "MACTOOL \$mactool_cmd \$in"
+ #}
+ #tool("package_framework") {
+ # command = "./gyp-mac-tool package-framework \$out \$version\$postbuilds && touch \$out"
+ # description = "PACKAGE FRAMEWORK \$out, POSTBUILDS"
+ #}
+ tool("stamp") {
+ command = "\${postbuilds}touch \$out"
+ description = "STAMP \$out"
+ }
+ tool("copy") {
+ command = "ln -f \$in \$out 2>/dev/null || (rm -rf \$out && cp -af \$in \$out)"
+ description = "COPY \$in \$out"
+ }
+}
diff --git a/tools/gn/settings.cc b/tools/gn/settings.cc
index 50eee73..63b8afb 100644
--- a/tools/gn/settings.cc
+++ b/tools/gn/settings.cc
@@ -5,6 +5,7 @@
#include "tools/gn/settings.h"
#include "base/logging.h"
+#include "build/build_config.h"
#include "tools/gn/filesystem_utils.h"
Settings::Settings(const BuildSettings* build_settings,
@@ -12,7 +13,6 @@ Settings::Settings(const BuildSettings* build_settings,
const std::string& output_subdir_name)
: build_settings_(build_settings),
toolchain_(toolchain),
- target_os_(WIN), // FIXME(brettw) set this properly.
import_manager_(),
base_config_(this),
greedy_target_generation_(false) {
@@ -31,6 +31,17 @@ Settings::Settings(const BuildSettings* build_settings,
// one-off data without doing generation.
if (!toolchain_output_dir_.is_null())
toolchain_gen_dir_ = SourceDir(toolchain_output_dir_.value() + "gen/");
+
+
+#if defined(OS_WIN)
+ target_os_ = WIN;
+#elif defined(OS_MACOSX)
+ target_os_ = MAC;
+#elif defined(OS_LINUX)
+ target_os_ = LINUX;
+#else
+ #error implement me
+#endif
}
Settings::~Settings() {
diff --git a/tools/gn/settings.h b/tools/gn/settings.h
index f316561..1305c58 100644
--- a/tools/gn/settings.h
+++ b/tools/gn/settings.h
@@ -52,6 +52,7 @@ class Settings {
const Toolchain* toolchain() const { return toolchain_; }
bool IsMac() const { return target_os_ == MAC; }
+ bool IsLinux() const { return target_os_ == LINUX; }
bool IsWin() const { return target_os_ == WIN; }
TargetOS target_os() const { return target_os_; }
diff --git a/tools/gn/toolchain.cc b/tools/gn/toolchain.cc
index 20b81f5..23da1e7 100644
--- a/tools/gn/toolchain.cc
+++ b/tools/gn/toolchain.cc
@@ -8,6 +8,8 @@
const char* Toolchain::kToolCc = "cc";
const char* Toolchain::kToolCxx = "cxx";
+const char* Toolchain::kToolObjC = "objc";
+const char* Toolchain::kToolObjCxx = "objcxx";
const char* Toolchain::kToolAsm = "asm";
const char* Toolchain::kToolAlink = "alink";
const char* Toolchain::kToolSolink = "solink";
@@ -40,6 +42,8 @@ const Toolchain* Toolchain::AsToolchain() const {
Toolchain::ToolType Toolchain::ToolNameToType(const base::StringPiece& str) {
if (str == kToolCc) return TYPE_CC;
if (str == kToolCxx) return TYPE_CXX;
+ if (str == kToolObjC) return TYPE_OBJC;
+ if (str == kToolObjCxx) return TYPE_OBJCXX;
if (str == kToolAsm) return TYPE_ASM;
if (str == kToolAlink) return TYPE_ALINK;
if (str == kToolSolink) return TYPE_SOLINK;
@@ -55,6 +59,8 @@ std::string Toolchain::ToolTypeToName(ToolType type) {
switch (type) {
case TYPE_CC: return kToolCc;
case TYPE_CXX: return kToolCxx;
+ case TYPE_OBJC: return kToolObjC;
+ case TYPE_OBJCXX: return kToolObjCxx;
case TYPE_ASM: return kToolAsm;
case TYPE_ALINK: return kToolAlink;
case TYPE_SOLINK: return kToolSolink;
diff --git a/tools/gn/toolchain.h b/tools/gn/toolchain.h
index 22b8151..d15ca91 100644
--- a/tools/gn/toolchain.h
+++ b/tools/gn/toolchain.h
@@ -27,6 +27,8 @@ class Toolchain : public Item {
TYPE_NONE = 0,
TYPE_CC,
TYPE_CXX,
+ TYPE_OBJC,
+ TYPE_OBJCXX,
TYPE_ASM,
TYPE_ALINK,
TYPE_SOLINK,
@@ -40,6 +42,8 @@ class Toolchain : public Item {
static const char* kToolCc;
static const char* kToolCxx;
+ static const char* kToolObjC;
+ static const char* kToolObjCxx;
static const char* kToolAsm;
static const char* kToolAlink;
static const char* kToolSolink;
diff --git a/tools/gn/toolchain_manager.cc b/tools/gn/toolchain_manager.cc
index e6ce8e3..61c7ade 100644
--- a/tools/gn/toolchain_manager.cc
+++ b/tools/gn/toolchain_manager.cc
@@ -7,6 +7,7 @@
#include <set>
#include "base/bind.h"
+#include "build/build_config.h"
#include "tools/gn/err.h"
#include "tools/gn/item.h"
#include "tools/gn/item_node.h"
@@ -23,13 +24,25 @@ SourceFile DirToBuildFile(const SourceDir& dir) {
}
void SetSystemVars(const Settings& settings, Scope* scope) {
- // FIXME(brettw) port.
+#if defined(OS_WIN)
scope->SetValue("is_win", Value(NULL, 1), NULL);
- scope->SetValue("is_linux", Value(NULL, 0), NULL);
scope->SetValue("is_posix", Value(NULL, 0), NULL);
+#else
+ scope->SetValue("is_win", Value(NULL, 0), NULL);
+ scope->SetValue("is_posix", Value(NULL, 1), NULL);
+#endif
+
+#if defined(OS_MACOSX)
+ scope->SetValue("is_mac", Value(NULL, 1), NULL);
+#else
scope->SetValue("is_mac", Value(NULL, 0), NULL);
- scope->SetValue("is_android", Value(NULL, 0), NULL);
- scope->SetValue("is_ios", Value(NULL, 0), NULL);
+#endif
+
+#if defined(OS_LINUX)
+ scope->SetValue("is_linux", Value(NULL, 1), NULL);
+#else
+ scope->SetValue("is_linux", Value(NULL, 0), NULL);
+#endif
// Set this value without the terminating slash because the code expects
// $root_output_dir/foo to work.