Commit d5467426 authored by Brett Wilson's avatar Brett Wilson

Hook up link pools in GN.

Adds a toolchain variable "concurrent_links". The value of this variable in the default toolchain is used as the depth of the link pool for the build.

Remove the "pool" stuff from the tool definitions that was never hooked up. The link pool is hardcoded in GN and is controlled by the above variable.

R=scottmg@chromium.org

Review URL: https://codereview.chromium.org/508763002

Cr-Commit-Position: refs/heads/master@{#292261}
parent 14ac2486
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
// found in the LICENSE file. // found in the LICENSE file.
#include <algorithm> #include <algorithm>
#include <limits>
#include "tools/gn/err.h" #include "tools/gn/err.h"
#include "tools/gn/functions.h" #include "tools/gn/functions.h"
...@@ -202,15 +203,43 @@ const char kToolchain_Help[] = ...@@ -202,15 +203,43 @@ const char kToolchain_Help[] =
" source code. You can have more than one toolchain in use at once in\n" " source code. You can have more than one toolchain in use at once in\n"
" a build.\n" " a build.\n"
"\n" "\n"
" A toolchain specifies the commands to run for various input file\n" "Functions and variables\n"
" types via the \"tool\" call (see \"gn help tool\") and specifies\n"
" arguments to be passed to the toolchain build via the\n"
" \"toolchain_args\" call (see \"gn help toolchain_args\").\n"
"\n" "\n"
" In addition, a toolchain can specify dependencies via the \"deps\"\n" " tool()\n"
" variable like a target. These dependencies will be resolved before any\n" " The tool() function call specifies the commands commands to run for\n"
" target in the toolchain is compiled. To avoid circular dependencies\n" " a given step. See \"gn help tool\".\n"
" these must be targets defined in another toolchain.\n" "\n"
" toolchain_args()\n"
" List of arguments to pass to the toolchain when invoking this\n"
" toolchain. This applies only to non-default toolchains. See\n"
" \"gn help toolchain_args\" for more.\n"
"\n"
" deps\n"
" Dependencies of this toolchain. These dependencies will be resolved\n"
" before any target in the toolchain is compiled. To avoid circular\n"
" dependencies these must be targets defined in another toolchain.\n"
"\n"
" This is expressed as a list of targets, and generally these targets\n"
" will always specify a toolchain:\n"
" deps = [ \"//foo/bar:baz(//build/toolchain:bootstrap)\" ]\n"
"\n"
" This concept is somewhat inefficient to express in Ninja (it\n"
" requires a lot of duplicate of rules) so should only be used when\n"
" absolutely necessary.\n"
"\n"
" concurrent_links\n"
" In integer expressing the number of links that Ninja will perform in\n"
" parallel. GN will create a pool for shared library and executable\n"
" link steps with this many processes. Since linking is memory- and\n"
" I/O-intensive, projects with many large targets may want to limit\n"
" the number of parallel steps to avoid overloading the computer.\n"
" Since creating static libraries is generally not as intensive\n"
" there is no limit to \"alink\" steps.\n"
"\n"
" Defaults to 0 which Ninja interprets as \"no limit\".\n"
"\n"
" The value used will be the one from the default toolchain of the\n"
" current build.\n"
"\n" "\n"
"Invoking targets in toolchains:\n" "Invoking targets in toolchains:\n"
"\n" "\n"
...@@ -236,8 +265,11 @@ const char kToolchain_Help[] = ...@@ -236,8 +265,11 @@ const char kToolchain_Help[] =
"\n" "\n"
"Example:\n" "Example:\n"
" toolchain(\"plugin_toolchain\") {\n" " toolchain(\"plugin_toolchain\") {\n"
" concurrent_links = 8\n"
"\n"
" tool(\"cc\") {\n" " tool(\"cc\") {\n"
" command = \"gcc $in\"\n" " command = \"gcc $in\"\n"
" ...\n"
" }\n" " }\n"
"\n" "\n"
" toolchain_args() {\n" " toolchain_args() {\n"
...@@ -287,6 +319,21 @@ Value RunToolchain(Scope* scope, ...@@ -287,6 +319,21 @@ Value RunToolchain(Scope* scope,
return Value(); return Value();
} }
// Read concurrent_links (if any).
const Value* concurrent_links_value =
block_scope.GetValue("concurrent_links", true);
if (concurrent_links_value) {
if (!concurrent_links_value->VerifyTypeIs(Value::INTEGER, err))
return Value();
if (concurrent_links_value->int_value() < 0 ||
concurrent_links_value->int_value() > std::numeric_limits<int>::max()) {
*err = Err(*concurrent_links_value, "Value out of range.");
return Value();
}
toolchain->set_concurrent_links(
static_cast<int>(concurrent_links_value->int_value()));
}
if (!block_scope.CheckForUnusedVars(err)) if (!block_scope.CheckForUnusedVars(err))
return Value(); return Value();
...@@ -458,9 +505,6 @@ const char kTool_Help[] = ...@@ -458,9 +505,6 @@ const char kTool_Help[] =
" Posix systems:\n" " Posix systems:\n"
" output_prefix = \"lib\"\n" " output_prefix = \"lib\"\n"
"\n" "\n"
// TODO(brettw) document "pool" when it works.
//" pool [string, optional]\n"
//"\n"
" restat [boolean]\n" " restat [boolean]\n"
" Valid for: all tools (optional, defaults to false)\n" " Valid for: all tools (optional, defaults to false)\n"
"\n" "\n"
...@@ -742,7 +786,6 @@ Value RunTool(Scope* scope, ...@@ -742,7 +786,6 @@ Value RunTool(Scope* scope,
&Tool::set_depend_output, err) || &Tool::set_depend_output, err) ||
!ReadString(&block_scope, "output_prefix", tool.get(), !ReadString(&block_scope, "output_prefix", tool.get(),
&Tool::set_output_prefix, err) || &Tool::set_output_prefix, err) ||
!ReadString(&block_scope, "pool", tool.get(), &Tool::set_pool, err) ||
!ReadBool(&block_scope, "restat", tool.get(), &Tool::set_restat, err) || !ReadBool(&block_scope, "restat", tool.get(), &Tool::set_restat, err) ||
!ReadPattern(&block_scope, "rspfile", subst_validator, tool.get(), !ReadPattern(&block_scope, "rspfile", subst_validator, tool.get(),
&Tool::set_rspfile, err) || &Tool::set_rspfile, err) ||
......
...@@ -75,11 +75,13 @@ std::string GetSelfInvocationCommand(const BuildSettings* build_settings) { ...@@ -75,11 +75,13 @@ std::string GetSelfInvocationCommand(const BuildSettings* build_settings) {
NinjaBuildWriter::NinjaBuildWriter( NinjaBuildWriter::NinjaBuildWriter(
const BuildSettings* build_settings, const BuildSettings* build_settings,
const std::vector<const Settings*>& all_settings, const std::vector<const Settings*>& all_settings,
const Toolchain* default_toolchain,
const std::vector<const Target*>& default_toolchain_targets, const std::vector<const Target*>& default_toolchain_targets,
std::ostream& out, std::ostream& out,
std::ostream& dep_out) std::ostream& dep_out)
: build_settings_(build_settings), : build_settings_(build_settings),
all_settings_(all_settings), all_settings_(all_settings),
default_toolchain_(default_toolchain),
default_toolchain_targets_(default_toolchain_targets), default_toolchain_targets_(default_toolchain_targets),
out_(out), out_(out),
dep_out_(dep_out), dep_out_(dep_out),
...@@ -91,6 +93,7 @@ NinjaBuildWriter::~NinjaBuildWriter() { ...@@ -91,6 +93,7 @@ NinjaBuildWriter::~NinjaBuildWriter() {
void NinjaBuildWriter::Run() { void NinjaBuildWriter::Run() {
WriteNinjaRules(); WriteNinjaRules();
WriteLinkPool();
WriteSubninjas(); WriteSubninjas();
WritePhonyAndAllRules(); WritePhonyAndAllRules();
} }
...@@ -99,6 +102,7 @@ void NinjaBuildWriter::Run() { ...@@ -99,6 +102,7 @@ void NinjaBuildWriter::Run() {
bool NinjaBuildWriter::RunAndWriteFile( bool NinjaBuildWriter::RunAndWriteFile(
const BuildSettings* build_settings, const BuildSettings* build_settings,
const std::vector<const Settings*>& all_settings, const std::vector<const Settings*>& all_settings,
const Toolchain* default_toolchain,
const std::vector<const Target*>& default_toolchain_targets) { const std::vector<const Target*>& default_toolchain_targets) {
ScopedTrace trace(TraceItem::TRACE_FILE_WRITE, "build.ninja"); ScopedTrace trace(TraceItem::TRACE_FILE_WRITE, "build.ninja");
...@@ -118,7 +122,7 @@ bool NinjaBuildWriter::RunAndWriteFile( ...@@ -118,7 +122,7 @@ bool NinjaBuildWriter::RunAndWriteFile(
if (depfile.fail()) if (depfile.fail())
return false; return false;
NinjaBuildWriter gen(build_settings, all_settings, NinjaBuildWriter gen(build_settings, all_settings, default_toolchain,
default_toolchain_targets, file, depfile); default_toolchain_targets, file, depfile);
gen.Run(); gen.Run();
return true; return true;
...@@ -152,6 +156,12 @@ void NinjaBuildWriter::WriteNinjaRules() { ...@@ -152,6 +156,12 @@ void NinjaBuildWriter::WriteNinjaRules() {
out_ << std::endl; out_ << std::endl;
} }
void NinjaBuildWriter::WriteLinkPool() {
out_ << "pool link_pool\n"
<< " depth = " << default_toolchain_->concurrent_links() << std::endl
<< std::endl;
}
void NinjaBuildWriter::WriteSubninjas() { void NinjaBuildWriter::WriteSubninjas() {
for (size_t i = 0; i < all_settings_.size(); i++) { for (size_t i = 0; i < all_settings_.size(); i++) {
out_ << "subninja "; out_ << "subninja ";
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
class BuildSettings; class BuildSettings;
class Settings; class Settings;
class Target; class Target;
class Toolchain;
// Generates the toplevel "build.ninja" file. This references the individual // Generates the toplevel "build.ninja" file. This references the individual
// toolchain files and lists all input .gn files as dependencies of the // toolchain files and lists all input .gn files as dependencies of the
...@@ -22,11 +23,13 @@ class NinjaBuildWriter { ...@@ -22,11 +23,13 @@ class NinjaBuildWriter {
static bool RunAndWriteFile( static bool RunAndWriteFile(
const BuildSettings* settings, const BuildSettings* settings,
const std::vector<const Settings*>& all_settings, const std::vector<const Settings*>& all_settings,
const Toolchain* default_toolchain,
const std::vector<const Target*>& default_toolchain_targets); const std::vector<const Target*>& default_toolchain_targets);
private: private:
NinjaBuildWriter(const BuildSettings* settings, NinjaBuildWriter(const BuildSettings* settings,
const std::vector<const Settings*>& all_settings, const std::vector<const Settings*>& all_settings,
const Toolchain* default_toolchain,
const std::vector<const Target*>& default_toolchain_targets, const std::vector<const Target*>& default_toolchain_targets,
std::ostream& out, std::ostream& out,
std::ostream& dep_out); std::ostream& dep_out);
...@@ -35,6 +38,7 @@ class NinjaBuildWriter { ...@@ -35,6 +38,7 @@ class NinjaBuildWriter {
void Run(); void Run();
void WriteNinjaRules(); void WriteNinjaRules();
void WriteLinkPool();
void WriteSubninjas(); void WriteSubninjas();
void WritePhonyAndAllRules(); void WritePhonyAndAllRules();
...@@ -43,6 +47,7 @@ class NinjaBuildWriter { ...@@ -43,6 +47,7 @@ class NinjaBuildWriter {
const BuildSettings* build_settings_; const BuildSettings* build_settings_;
std::vector<const Settings*> all_settings_; std::vector<const Settings*> all_settings_;
const Toolchain* default_toolchain_;
std::vector<const Target*> default_toolchain_targets_; std::vector<const Target*> default_toolchain_targets_;
std::ostream& out_; std::ostream& out_;
std::ostream& dep_out_; std::ostream& dep_out_;
......
...@@ -105,8 +105,11 @@ void NinjaToolchainWriter::WriteToolRule(const Toolchain::ToolType type, ...@@ -105,8 +105,11 @@ void NinjaToolchainWriter::WriteToolRule(const Toolchain::ToolType type,
out_ << kIndent << "deps = msvc" << std::endl; out_ << kIndent << "deps = msvc" << std::endl;
} }
if (!tool->pool().empty()) // The link pool applies to linker tools. Don't count TYPE_ALINK since
out_ << kIndent << "pool = " << tool->pool() << std::endl; // static libraries are not generally intensive to write.
if (type == Toolchain::TYPE_SOLINK || type == Toolchain::TYPE_LINK)
out_ << kIndent << "pool = link_pool\n";
if (tool->restat()) if (tool->restat())
out_ << kIndent << "restat = 1" << std::endl; out_ << kIndent << "restat = 1" << std::endl;
} }
......
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
#include "tools/gn/location.h" #include "tools/gn/location.h"
#include "tools/gn/ninja_build_writer.h" #include "tools/gn/ninja_build_writer.h"
#include "tools/gn/ninja_toolchain_writer.h" #include "tools/gn/ninja_toolchain_writer.h"
#include "tools/gn/settings.h"
NinjaWriter::NinjaWriter(const BuildSettings* build_settings, NinjaWriter::NinjaWriter(const BuildSettings* build_settings,
Builder* builder) Builder* builder)
...@@ -88,9 +89,15 @@ bool NinjaWriter::WriteToolchains(std::vector<const Settings*>* all_settings, ...@@ -88,9 +89,15 @@ bool NinjaWriter::WriteToolchains(std::vector<const Settings*>* all_settings,
bool NinjaWriter::WriteRootBuildfiles( bool NinjaWriter::WriteRootBuildfiles(
const std::vector<const Settings*>& all_settings, const std::vector<const Settings*>& all_settings,
const std::vector<const Target*>& default_targets) { const std::vector<const Target*>& default_targets) {
// All Settings objects should have the same default toolchain, and there
// should always be at least one settings object in the build.
CHECK(!all_settings.empty());
const Toolchain* default_toolchain =
builder_->GetToolchain(all_settings[0]->default_toolchain_label());
// Write the root buildfile. // Write the root buildfile.
if (!NinjaBuildWriter::RunAndWriteFile(build_settings_, all_settings, if (!NinjaBuildWriter::RunAndWriteFile(build_settings_, all_settings,
default_targets)) { default_toolchain, default_targets)) {
Err(Location(), Err(Location(),
"Couldn't open toolchain buildfile(s) for writing").PrintToStdout(); "Couldn't open toolchain buildfile(s) for writing").PrintToStdout();
return false; return false;
......
...@@ -120,14 +120,6 @@ class Tool { ...@@ -120,14 +120,6 @@ class Tool {
output_prefix_ = s; output_prefix_ = s;
} }
const std::string& pool() const {
return pool_;
}
void set_pool(const std::string& s) {
DCHECK(!complete_);
pool_ = s;
}
bool restat() const { bool restat() const {
return restat_; return restat_;
} }
...@@ -182,7 +174,6 @@ class Tool { ...@@ -182,7 +174,6 @@ class Tool {
SubstitutionPattern link_output_; SubstitutionPattern link_output_;
SubstitutionPattern depend_output_; SubstitutionPattern depend_output_;
std::string output_prefix_; std::string output_prefix_;
std::string pool_;
bool restat_; bool restat_;
SubstitutionPattern rspfile_; SubstitutionPattern rspfile_;
SubstitutionPattern rspfile_content_; SubstitutionPattern rspfile_content_;
......
...@@ -24,6 +24,7 @@ const char* Toolchain::kToolCopy = "copy"; ...@@ -24,6 +24,7 @@ const char* Toolchain::kToolCopy = "copy";
Toolchain::Toolchain(const Settings* settings, const Label& label) Toolchain::Toolchain(const Settings* settings, const Label& label)
: Item(settings, label), : Item(settings, label),
concurrent_links_(0),
setup_complete_(false) { setup_complete_(false) {
} }
......
...@@ -108,9 +108,16 @@ class Toolchain : public Item { ...@@ -108,9 +108,16 @@ class Toolchain : public Item {
return substitution_bits_; return substitution_bits_;
} }
void set_concurrent_links(int cl) { concurrent_links_ = cl; }
int concurrent_links() const { return concurrent_links_; }
private: private:
scoped_ptr<Tool> tools_[TYPE_NUMTYPES]; scoped_ptr<Tool> tools_[TYPE_NUMTYPES];
// How many links to run in parallel. Only the default toolchain's version of
// this variable applies.
int concurrent_links_;
bool setup_complete_; bool setup_complete_;
// Substitutions used by the tools in this toolchain. // Substitutions used by the tools in this toolchain.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment