Add ninja console pool support to GN
Allow GN actions to specify "console = true", which will translate into a "pool = console" setting in the generated ninja files. The console pool allows a ninja target to have unbuffered io, access to standard input, and is limited to one target at a time. R=brettw@chromium.org BUG= Review URL: https://codereview.chromium.org/1358803002 Cr-Commit-Position: refs/heads/master@{#350321}
This commit is contained in:
@ -54,6 +54,9 @@ void ActionTargetGenerator::DoRun() {
|
|||||||
if (!FillDepfile())
|
if (!FillDepfile())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (!FillConsole())
|
||||||
|
return;
|
||||||
|
|
||||||
if (!FillCheckIncludes())
|
if (!FillCheckIncludes())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -107,6 +110,16 @@ bool ActionTargetGenerator::FillDepfile() {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ActionTargetGenerator::FillConsole() {
|
||||||
|
const Value* value = scope_->GetValue(variables::kConsole, true);
|
||||||
|
if (!value)
|
||||||
|
return true;
|
||||||
|
if (!value->VerifyTypeIs(Value::BOOLEAN, err_))
|
||||||
|
return false;
|
||||||
|
target_->action_values().set_console(value->boolean_value());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool ActionTargetGenerator::CheckOutputs() {
|
bool ActionTargetGenerator::CheckOutputs() {
|
||||||
const SubstitutionList& outputs = target_->action_values().outputs();
|
const SubstitutionList& outputs = target_->action_values().outputs();
|
||||||
if (outputs.list().empty()) {
|
if (outputs.list().empty()) {
|
||||||
|
@ -26,6 +26,7 @@ class ActionTargetGenerator : public TargetGenerator {
|
|||||||
bool FillScript();
|
bool FillScript();
|
||||||
bool FillScriptArgs();
|
bool FillScriptArgs();
|
||||||
bool FillDepfile();
|
bool FillDepfile();
|
||||||
|
bool FillConsole();
|
||||||
|
|
||||||
// Checks for errors in the outputs variable.
|
// Checks for errors in the outputs variable.
|
||||||
bool CheckOutputs();
|
bool CheckOutputs();
|
||||||
|
@ -8,11 +8,9 @@
|
|||||||
#include "tools/gn/substitution_writer.h"
|
#include "tools/gn/substitution_writer.h"
|
||||||
#include "tools/gn/target.h"
|
#include "tools/gn/target.h"
|
||||||
|
|
||||||
ActionValues::ActionValues() {
|
ActionValues::ActionValues() : console_(false) {}
|
||||||
}
|
|
||||||
|
|
||||||
ActionValues::~ActionValues() {
|
ActionValues::~ActionValues() {}
|
||||||
}
|
|
||||||
|
|
||||||
void ActionValues::GetOutputsAsSourceFiles(
|
void ActionValues::GetOutputsAsSourceFiles(
|
||||||
const Target* target,
|
const Target* target,
|
||||||
|
@ -43,11 +43,16 @@ class ActionValues {
|
|||||||
bool has_depfile() const { return !depfile_.ranges().empty(); }
|
bool has_depfile() const { return !depfile_.ranges().empty(); }
|
||||||
void set_depfile(const SubstitutionPattern& depfile) { depfile_ = depfile; }
|
void set_depfile(const SubstitutionPattern& depfile) { depfile_ = depfile; }
|
||||||
|
|
||||||
|
// Console pool option
|
||||||
|
bool is_console() const { return console_; }
|
||||||
|
void set_console(bool value) { console_ = value; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
SourceFile script_;
|
SourceFile script_;
|
||||||
SubstitutionList args_;
|
SubstitutionList args_;
|
||||||
SubstitutionList outputs_;
|
SubstitutionList outputs_;
|
||||||
SubstitutionPattern depfile_;
|
SubstitutionPattern depfile_;
|
||||||
|
bool console_;
|
||||||
|
|
||||||
DISALLOW_COPY_AND_ASSIGN(ActionValues);
|
DISALLOW_COPY_AND_ASSIGN(ActionValues);
|
||||||
};
|
};
|
||||||
|
@ -127,7 +127,7 @@ const char kAction_Help[] =
|
|||||||
"\n"
|
"\n"
|
||||||
"Variables\n"
|
"Variables\n"
|
||||||
"\n"
|
"\n"
|
||||||
" args, data, data_deps, depfile, deps, outputs*, script*,\n"
|
" args, console, data, data_deps, depfile, deps, outputs*, script*,\n"
|
||||||
" inputs, sources\n"
|
" inputs, sources\n"
|
||||||
" * = required\n"
|
" * = required\n"
|
||||||
"\n"
|
"\n"
|
||||||
@ -198,7 +198,7 @@ const char kActionForEach_Help[] =
|
|||||||
"\n"
|
"\n"
|
||||||
"Variables\n"
|
"Variables\n"
|
||||||
"\n"
|
"\n"
|
||||||
" args, data, data_deps, depfile, deps, outputs*, script*,\n"
|
" args, console, data, data_deps, depfile, deps, outputs*, script*,\n"
|
||||||
" inputs, sources*\n"
|
" inputs, sources*\n"
|
||||||
" * = required\n"
|
" * = required\n"
|
||||||
"\n"
|
"\n"
|
||||||
|
@ -74,6 +74,10 @@ void NinjaActionTargetWriter::Run() {
|
|||||||
WriteDepfile(SourceFile());
|
WriteDepfile(SourceFile());
|
||||||
out_ << std::endl;
|
out_ << std::endl;
|
||||||
}
|
}
|
||||||
|
if (target_->action_values().is_console()) {
|
||||||
|
out_ << " pool = console";
|
||||||
|
out_ << std::endl;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
out_ << std::endl;
|
out_ << std::endl;
|
||||||
|
|
||||||
|
@ -76,6 +76,49 @@ TEST(NinjaActionTargetWriter, ActionNoSources) {
|
|||||||
EXPECT_EQ(expected, out.str());
|
EXPECT_EQ(expected, out.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Tests an action with no sources and console = true
|
||||||
|
TEST(NinjaActionTargetWriter, ActionNoSourcesConsole) {
|
||||||
|
TestWithScope setup;
|
||||||
|
Err err;
|
||||||
|
|
||||||
|
setup.build_settings()->SetBuildDir(SourceDir("//out/Debug/"));
|
||||||
|
Target target(setup.settings(), Label(SourceDir("//foo/"), "bar"));
|
||||||
|
target.set_output_type(Target::ACTION);
|
||||||
|
|
||||||
|
target.action_values().set_script(SourceFile("//foo/script.py"));
|
||||||
|
target.inputs().push_back(SourceFile("//foo/included.txt"));
|
||||||
|
|
||||||
|
target.action_values().outputs() =
|
||||||
|
SubstitutionList::MakeForTest("//out/Debug/foo.out");
|
||||||
|
target.action_values().set_console(true);
|
||||||
|
|
||||||
|
target.SetToolchain(setup.toolchain());
|
||||||
|
ASSERT_TRUE(target.OnResolved(&err));
|
||||||
|
|
||||||
|
setup.settings()->set_target_os(Settings::LINUX);
|
||||||
|
setup.build_settings()->set_python_path(base::FilePath(FILE_PATH_LITERAL(
|
||||||
|
"/usr/bin/python")));
|
||||||
|
|
||||||
|
std::ostringstream out;
|
||||||
|
NinjaActionTargetWriter writer(&target, out);
|
||||||
|
writer.Run();
|
||||||
|
|
||||||
|
const char expected[] =
|
||||||
|
"rule __foo_bar___rule\n"
|
||||||
|
" command = /usr/bin/python ../../foo/script.py\n"
|
||||||
|
" description = ACTION //foo:bar()\n"
|
||||||
|
" restat = 1\n"
|
||||||
|
"build obj/foo/bar.inputdeps.stamp: stamp ../../foo/script.py "
|
||||||
|
"../../foo/included.txt\n"
|
||||||
|
"\n"
|
||||||
|
"build foo.out: __foo_bar___rule | obj/foo/bar.inputdeps.stamp\n"
|
||||||
|
" pool = console\n"
|
||||||
|
"\n"
|
||||||
|
"build obj/foo/bar.stamp: stamp foo.out\n";
|
||||||
|
EXPECT_EQ(expected, out.str());
|
||||||
|
}
|
||||||
|
|
||||||
// Makes sure that we write sources as input dependencies for actions with
|
// Makes sure that we write sources as input dependencies for actions with
|
||||||
// both sources and inputs (ACTION_FOREACH treats the sources differently).
|
// both sources and inputs (ACTION_FOREACH treats the sources differently).
|
||||||
TEST(NinjaActionTargetWriter, ActionWithSources) {
|
TEST(NinjaActionTargetWriter, ActionWithSources) {
|
||||||
|
@ -574,6 +574,29 @@ const char kConfigs_Help[] =
|
|||||||
" }\n"
|
" }\n"
|
||||||
" }\n";
|
" }\n";
|
||||||
|
|
||||||
|
const char kConsole[] = "console";
|
||||||
|
const char kConsole_HelpShort[] =
|
||||||
|
"console [boolean]: Run this action in the console pool.";
|
||||||
|
const char kConsole_Help[] =
|
||||||
|
"console: Run this action in the console pool.\n"
|
||||||
|
"\n"
|
||||||
|
" Boolean. Defaults to false.\n"
|
||||||
|
"\n"
|
||||||
|
" Actions marked \"console = true\" will be run in the built-in ninja\n"
|
||||||
|
" \"console\" pool. They will have access to real stdin and stdout, and\n"
|
||||||
|
" output will not be buffered by ninja. This can be useful for\n"
|
||||||
|
" long-running actions with progress logs, or actions that require user \n"
|
||||||
|
" input.\n"
|
||||||
|
"\n"
|
||||||
|
" Only one console pool target can run at any one time in Ninja. Refer\n"
|
||||||
|
" to the Ninja documentation on the console pool for more info.\n"
|
||||||
|
"\n"
|
||||||
|
"Example\n"
|
||||||
|
"\n"
|
||||||
|
" action(\"long_action_with_progress_logs\") {\n"
|
||||||
|
" console = true\n"
|
||||||
|
" }\n";
|
||||||
|
|
||||||
const char kData[] = "data";
|
const char kData[] = "data";
|
||||||
const char kData_HelpShort[] =
|
const char kData_HelpShort[] =
|
||||||
"data: [file list] Runtime data file dependencies.";
|
"data: [file list] Runtime data file dependencies.";
|
||||||
@ -1246,6 +1269,7 @@ const VariableInfoMap& GetTargetVariables() {
|
|||||||
INSERT_VARIABLE(CheckIncludes)
|
INSERT_VARIABLE(CheckIncludes)
|
||||||
INSERT_VARIABLE(CompleteStaticLib)
|
INSERT_VARIABLE(CompleteStaticLib)
|
||||||
INSERT_VARIABLE(Configs)
|
INSERT_VARIABLE(Configs)
|
||||||
|
INSERT_VARIABLE(Console)
|
||||||
INSERT_VARIABLE(Data)
|
INSERT_VARIABLE(Data)
|
||||||
INSERT_VARIABLE(DataDeps)
|
INSERT_VARIABLE(DataDeps)
|
||||||
INSERT_VARIABLE(Defines)
|
INSERT_VARIABLE(Defines)
|
||||||
|
@ -115,6 +115,10 @@ extern const char kConfigs[];
|
|||||||
extern const char kConfigs_HelpShort[];
|
extern const char kConfigs_HelpShort[];
|
||||||
extern const char kConfigs_Help[];
|
extern const char kConfigs_Help[];
|
||||||
|
|
||||||
|
extern const char kConsole[];
|
||||||
|
extern const char kConsole_HelpShort[];
|
||||||
|
extern const char kConsole_Help[];
|
||||||
|
|
||||||
extern const char kData[];
|
extern const char kData[];
|
||||||
extern const char kData_HelpShort[];
|
extern const char kData_HelpShort[];
|
||||||
extern const char kData_Help[];
|
extern const char kData_Help[];
|
||||||
|
Reference in New Issue
Block a user