Commit 43bf6a5b authored by brettw@chromium.org's avatar brettw@chromium.org

This changes the current directory for script execution to be the build...

This changes the current directory for script execution to be the build directory rather than the current BUILDfile directory. This makes things more consistent and simplifies some implementation.

It adds a new function to_build_path() for buildfiles to convert files to the build directory for this kind of call.

I removed all of the built-in relative* variables that were required to support this, and added one for target_out_dir and root_out_dir.

I added some tests and a test helper object since I was doing this kind of Scope setup a lot.

R=scottmg@chromium.org

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

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@223622 0039d316-1c4b-4281-b951-d872f2087c98
parent 62956918
...@@ -41,6 +41,7 @@ static_library("gn_lib") { ...@@ -41,6 +41,7 @@ static_library("gn_lib") {
"function_set_default_toolchain.cc", "function_set_default_toolchain.cc",
"function_set_defaults.cc", "function_set_defaults.cc",
"function_template.cc", "function_template.cc",
"function_to_build_path.cc",
"function_toolchain.cc", "function_toolchain.cc",
"function_write_file.cc", "function_write_file.cc",
"group_target_generator.cc", "group_target_generator.cc",
...@@ -155,6 +156,7 @@ test("gn_unittests") { ...@@ -155,6 +156,7 @@ test("gn_unittests") {
"escape_unittest.cc", "escape_unittest.cc",
"file_template_unittest.cc", "file_template_unittest.cc",
"filesystem_utils_unittest.cc", "filesystem_utils_unittest.cc",
"function_to_build_path_unittest.cc",
"input_conversion_unittest.cc", "input_conversion_unittest.cc",
"label_unittest.cc", "label_unittest.cc",
"ninja_helper_unittest.cc", "ninja_helper_unittest.cc",
...@@ -167,6 +169,8 @@ test("gn_unittests") { ...@@ -167,6 +169,8 @@ test("gn_unittests") {
"target_generator_unittest.cc", "target_generator_unittest.cc",
"target_manager_unittest.cc", "target_manager_unittest.cc",
"target_unittest.cc", "target_unittest.cc",
"test_with_scope.cc",
"test_with_scope.h",
"tokenizer_unittest.cc", "tokenizer_unittest.cc",
] ]
deps = [ deps = [
......
...@@ -242,10 +242,16 @@ const char kExecScript_Help[] = ...@@ -242,10 +242,16 @@ const char kExecScript_Help[] =
" generation will fail if the script does not exist or returns a nonzero\n" " generation will fail if the script does not exist or returns a nonzero\n"
" exit code.\n" " exit code.\n"
"\n" "\n"
" The current directory when executing the script will be the root\n"
" build directory. If you are passing file names, you will want to use\n"
" the to_build_dir() function to make file names relative to this\n"
" path (see \"gn help to_build_dir\").\n"
"\n"
"Arguments:\n" "Arguments:\n"
"\n" "\n"
" filename:\n" " filename:\n"
" File name of python script to execute, relative to the build file.\n" " File name of python script to execute. Non-absolute names will\n"
" be treated as relative to the current build file.\n"
"\n" "\n"
" arguments:\n" " arguments:\n"
" A list of strings to be passed to the script as arguments.\n" " A list of strings to be passed to the script as arguments.\n"
...@@ -266,7 +272,7 @@ const char kExecScript_Help[] = ...@@ -266,7 +272,7 @@ const char kExecScript_Help[] =
"Example:\n" "Example:\n"
"\n" "\n"
" all_lines = exec_script(\"myscript.py\", [some_input], \"list lines\",\n" " all_lines = exec_script(\"myscript.py\", [some_input], \"list lines\",\n"
" [\"data_file.txt\"])\n"; " [ to_build_dir(\"data_file.txt\") ])\n";
Value RunExecScript(Scope* scope, Value RunExecScript(Scope* scope,
const FunctionCallNode* function, const FunctionCallNode* function,
...@@ -336,12 +342,15 @@ Value RunExecScript(Scope* scope, ...@@ -336,12 +342,15 @@ Value RunExecScript(Scope* scope,
begin_exec = base::TimeTicks::Now(); begin_exec = base::TimeTicks::Now();
} }
base::FilePath startup_dir =
build_settings->GetFullPath(build_settings->build_dir());
// Execute the process. // Execute the process.
// TODO(brettw) set the environment block. // TODO(brettw) set the environment block.
std::string output; std::string output;
std::string stderr_output; // TODO(brettw) not hooked up, see above. std::string stderr_output; // TODO(brettw) not hooked up, see above.
int exit_code = 0; int exit_code = 0;
if (!ExecProcess(cmdline, build_settings->GetFullPath(cur_dir), if (!ExecProcess(cmdline, startup_dir,
&output, &stderr_output, &exit_code)) { &output, &stderr_output, &exit_code)) {
*err = Err(function->function(), "Could not execute python.", *err = Err(function->function(), "Could not execute python.",
"I was trying to execute \"" + FilePathToUTF8(python_path) + "\"."); "I was trying to execute \"" + FilePathToUTF8(python_path) + "\".");
...@@ -356,9 +365,8 @@ Value RunExecScript(Scope* scope, ...@@ -356,9 +365,8 @@ Value RunExecScript(Scope* scope,
// TODO(brettw) maybe we need stderr also for reasonable stack dumps. // TODO(brettw) maybe we need stderr also for reasonable stack dumps.
if (exit_code != 0) { if (exit_code != 0) {
std::string msg = "Current dir: " + std::string msg = "Current dir: " + FilePathToUTF8(startup_dir) +
FilePathToUTF8(build_settings->GetFullPath(cur_dir)) + "\nCommand: " + "\nCommand: " + cmdline.GetCommandLineString() +
cmdline.GetCommandLineString() +
"\nReturned " + base::IntToString(exit_code); "\nReturned " + base::IntToString(exit_code);
if (!output.empty()) if (!output.empty())
msg += " and printed out:\n\n" + output; msg += " and printed out:\n\n" + output;
......
// 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.
#include "tools/gn/build_settings.h"
#include "tools/gn/functions.h"
#include "tools/gn/parse_tree.h"
#include "tools/gn/path_output.h"
#include "tools/gn/scope.h"
#include "tools/gn/settings.h"
#include "tools/gn/source_dir.h"
#include "tools/gn/source_file.h"
#include "tools/gn/value.h"
namespace functions {
namespace {
// Returns true if the given value looks like a directory, otherwise we'll
// assume it's a file.
bool ValueLooksLikeDir(const std::string& value) {
if (value.empty())
return true;
size_t value_size = value.size();
// Count the number of dots at the end of the string.
size_t num_dots = 0;
while (num_dots < value_size && value[value_size - num_dots - 1] == '.')
num_dots++;
if (num_dots == value.size())
return true; // String is all dots.
if (value[value_size - num_dots - 1] == '/' ||
value[value_size - num_dots - 1] == '\\')
return true; // String is a [back]slash followed by 0 or more dots.
// Anything else.
return false;
}
Value ConvertOneBuildPath(const Scope* scope,
const FunctionCallNode* function,
const Value& value,
const PathOutput& path_output,
Err* err) {
if (!value.VerifyTypeIs(Value::STRING, err))
return Value();
const std::string& string_value = value.string_value();
std::ostringstream buffer;
if (ValueLooksLikeDir(string_value)) {
SourceDir absolute =
scope->GetSourceDir().ResolveRelativeDir(string_value);
path_output.WriteDir(buffer, absolute, PathOutput::DIR_NO_LAST_SLASH);
} else {
SourceFile absolute =
scope->GetSourceDir().ResolveRelativeFile(string_value);
path_output.WriteFile(buffer, absolute);
}
return Value(function, buffer.str());
}
} // namespace
const char kToBuildPath[] = "to_build_path";
const char kToBuildPath_Help[] =
"to_build_path: Rebase a file or directory to the build output dir.\n"
"\n"
" <converted> = to_build_path(<file_or_path_string_or_list>)\n"
"\n"
" Takes a string argument representing a file name, or a list of such\n"
" strings and converts it/them to be relative to the root build output\n"
" directory (which is the current directory when running scripts).\n"
"\n"
" The input can be:\n"
" - Paths relative to the BUILD file like \"foo.txt\".\n"
" - Source-root absolute paths like \"//foo/bar/foo.txt\".\n"
" - System absolute paths like \"/usr/include/foo.h\" or\n"
" \"/C:/foo/bar.h\" (these will be passed unchanged).\n"
" - A list of such values (the result will be a list of each item\n"
" converted as per the above description).\n"
"\n"
" Normally for sources and in cases where GN is providing file names\n"
" to a tool, the paths will automatically be converted to be relative\n"
" to the build directory. However, if you pass additional arguments,\n"
" GN won't know that the string is actually a file path. These will\n"
" need to be manually converted to be relative to the build dir using\n"
" to_build_path().\n"
"\n"
" Trailing slashes will not be reflected in the output.\n"
"\n"
" Additionally, on Windows, slashes will be converted to backslashes.\n"
"\n"
"Example:\n"
" custom(\"myscript\") {\n"
" # Don't use for sources, GN will automatically convert these since\n"
" # it knows they're files.\n"
" sources = [ \"foo.txt\", \"bar.txt\" ]\n"
"\n"
" # Extra file args passed manually need to be explicitly converted:\n"
" args = [ \"--data\", to_build_path(\"//mything/data/input.dat\"),\n"
" \"--rel\", to_build_path(\"relative_path.txt\") ]\n"
" }\n";
Value RunToBuildPath(Scope* scope,
const FunctionCallNode* function,
const std::vector<Value>& args,
Err* err) {
if (args.size() != 1) {
*err = Err(function->function(), "to_build_path takes one argument.");
return Value();
}
const Value& value = args[0];
PathOutput path_output(scope->settings()->build_settings()->build_dir(),
ESCAPE_NONE, true);
if (value.type() == Value::STRING) {
return ConvertOneBuildPath(scope, function, value, path_output, err);
} else if (value.type() == Value::LIST) {
Value ret(function, Value::LIST);
ret.list_value().reserve(value.list_value().size());
for (size_t i = 0; i < value.list_value().size(); i++) {
ret.list_value().push_back(
ConvertOneBuildPath(scope, function, value.list_value()[i],
path_output, err));
}
return ret;
}
*err = Err(function->function(),
"to_build_path requires a list or a string.");
return Value();
}
} // namespace functions
// 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.
#include "testing/gtest/include/gtest/gtest.h"
#include "tools/gn/functions.h"
#include "tools/gn/parse_tree.h"
#include "tools/gn/test_with_scope.h"
namespace {
void ExpectCallEqualsString(Scope* scope,
const std::string& input,
const std::string& expected) {
std::vector<Value> args;
args.push_back(Value(NULL, input));
Err err;
FunctionCallNode function;
Value result = functions::RunToBuildPath(scope, &function, args, &err);
EXPECT_FALSE(err.has_error());
EXPECT_EQ(Value::STRING, result.type());
EXPECT_EQ(expected, result.string_value());
}
} // namespace
TEST(ToBuildPath, Strings) {
TestWithScope setup;
setup.build_settings()->SetBuildDir(SourceDir("//out/Debug/"));
Scope* scope = setup.scope();
scope->set_source_dir(SourceDir("//tools/gn/"));
// Absolute system paths are unchanged.
ExpectCallEqualsString(scope, "/", "/");
ExpectCallEqualsString(scope, "/foo", "/foo");
ExpectCallEqualsString(scope, "/foo/", "/foo");
ExpectCallEqualsString(scope, "/foo/bar.txt", "/foo/bar.txt");
// Build-file relative paths.
ExpectCallEqualsString(scope, ".", "../../tools/gn");
ExpectCallEqualsString(scope, "foo.txt", "../../tools/gn/foo.txt");
ExpectCallEqualsString(scope, "..", "../../tools");
ExpectCallEqualsString(scope, "../", "../../tools");
ExpectCallEqualsString(scope, "../foo.txt", "../../tools/foo.txt");
// Source-root paths.
ExpectCallEqualsString(scope, "//", "../..");
ExpectCallEqualsString(scope, "//foo/", "../../foo");
ExpectCallEqualsString(scope, "//foo.txt", "../../foo.txt");
ExpectCallEqualsString(scope, "//foo/bar.txt", "../../foo/bar.txt");
// Source-root paths. It might be nice if we detected the strings start
// with the build dir and collapse, but this is the current behavior.
ExpectCallEqualsString(scope, "//out/Debug/",
"../../out/Debug"); // Could be ".".
ExpectCallEqualsString(scope, "//out/Debug/foo/",
"../../out/Debug/foo"); // Could be "foo".
}
// Test list input.
TEST(ToBuildPath, List) {
TestWithScope setup;
setup.build_settings()->SetBuildDir(SourceDir("//out/Debug/"));
setup.scope()->set_source_dir(SourceDir("//tools/gn/"));
std::vector<Value> args;
args.push_back(Value(NULL, Value::LIST));
args[0].list_value().push_back(Value(NULL, "foo.txt"));
args[0].list_value().push_back(Value(NULL, "bar.txt"));
Err err;
FunctionCallNode function;
Value ret = functions::RunToBuildPath(setup.scope(), &function, args, &err);
EXPECT_FALSE(err.has_error());
ASSERT_EQ(Value::LIST, ret.type());
ASSERT_EQ(2u, ret.list_value().size());
EXPECT_EQ("../../tools/gn/foo.txt", ret.list_value()[0].string_value());
EXPECT_EQ("../../tools/gn/bar.txt", ret.list_value()[1].string_value());
}
TEST(ToBuildPath, Errors) {
TestWithScope setup;
setup.build_settings()->SetBuildDir(SourceDir("//out/Debug/"));
// No arg input should issue an error.
Err err;
std::vector<Value> args;
FunctionCallNode function;
Value ret = functions::RunToBuildPath(setup.scope(), &function, args, &err);
EXPECT_TRUE(err.has_error());
// One arg int input.
args.push_back(Value(NULL, static_cast<int64>(5)));
err = Err();
ret = functions::RunToBuildPath(setup.scope(), &function, args, &err);
EXPECT_TRUE(err.has_error());
// Two arg string input.
args.clear();
args.push_back(Value(NULL, "hello"));
args.push_back(Value(NULL, "world"));
err = Err();
ret = functions::RunToBuildPath(setup.scope(), &function, args, &err);
EXPECT_TRUE(err.has_error());
}
...@@ -512,6 +512,7 @@ struct FunctionInfoInitializer { ...@@ -512,6 +512,7 @@ struct FunctionInfoInitializer {
INSERT_FUNCTION(StaticLibrary) INSERT_FUNCTION(StaticLibrary)
INSERT_FUNCTION(Template) INSERT_FUNCTION(Template)
INSERT_FUNCTION(Test) INSERT_FUNCTION(Test)
INSERT_FUNCTION(ToBuildPath)
INSERT_FUNCTION(Tool) INSERT_FUNCTION(Tool)
INSERT_FUNCTION(Toolchain) INSERT_FUNCTION(Toolchain)
INSERT_FUNCTION(ToolchainArgs) INSERT_FUNCTION(ToolchainArgs)
......
...@@ -211,6 +211,13 @@ Value RunTest(Scope* scope, ...@@ -211,6 +211,13 @@ Value RunTest(Scope* scope,
BlockNode* block, BlockNode* block,
Err* err); Err* err);
extern const char kToBuildPath[];
extern const char kToBuildPath_Help[];
Value RunToBuildPath(Scope* scope,
const FunctionCallNode* function,
const std::vector<Value>& args,
Err* err);
extern const char kTool[]; extern const char kTool[];
extern const char kTool_Help[]; extern const char kTool_Help[];
Value RunTool(Scope* scope, Value RunTool(Scope* scope,
......
...@@ -123,7 +123,11 @@ const char kCustom_Help[] = ...@@ -123,7 +123,11 @@ const char kCustom_Help[] =
" files and generate a set of output files.\n" " files and generate a set of output files.\n"
"\n" "\n"
" The script will be executed with the given arguments with the current\n" " The script will be executed with the given arguments with the current\n"
" directory being that of the current BUILD file.\n" " directory being that of the root build directory. If you pass\n"
" to your script, see \"gn help to_build_path\" for how to convert\n"
" file names to be relative to the build directory (file names in the\n"
" sources, outputs, and source_prereqs will be all treated as relative\n"
" to the current build file and converted as needed automatically).\n"
"\n" "\n"
" There are two modes. The first mode is the \"per-file\" mode where you\n" " There are two modes. The first mode is the \"per-file\" mode where you\n"
" specify a list of sources and the script is run once for each one as a\n" " specify a list of sources and the script is run once for each one as a\n"
...@@ -151,8 +155,8 @@ const char kCustom_Help[] = ...@@ -151,8 +155,8 @@ const char kCustom_Help[] =
"\n" "\n"
" {{source}}\n" " {{source}}\n"
" Expanded in |args|, this is the name of the source file relative\n" " Expanded in |args|, this is the name of the source file relative\n"
" to the current directory when running the script. This is how\n" " to the build directory This is how you specify the current input\n"
" you specify the current input file to your script.\n" " file to your script.\n"
"\n" "\n"
" {{source_name_part}}\n" " {{source_name_part}}\n"
" Expanded in |args| and |outputs|, this is just the filename part\n" " Expanded in |args| and |outputs|, this is just the filename part\n"
...@@ -176,16 +180,21 @@ const char kCustom_Help[] = ...@@ -176,16 +180,21 @@ const char kCustom_Help[] =
" source_prereqs = [ \"my_configuration.txt\" ]\n" " source_prereqs = [ \"my_configuration.txt\" ]\n"
" outputs = [ \"$target_gen_dir/{{source_name_part}}.h\",\n" " outputs = [ \"$target_gen_dir/{{source_name_part}}.h\",\n"
" \"$target_gen_dir/{{source_name_part}}.cc\" ]\n" " \"$target_gen_dir/{{source_name_part}}.cc\" ]\n"
"\n"
" # Note that since \"args\" is opaque to GN, if you specify paths\n"
" # here, you will need to convert it to be relative to the build\n"
" # directory using \"to_build_path()\".\n"
" args = [ \"{{source}}\",\n" " args = [ \"{{source}}\",\n"
" \"-o\",\n" " \"-o\",\n"
" \"$relative_target_gen_dir/{{source_name_part}}.h\" ]\n" " to_build_path(relative_target_gen_dir) + \"/\" +\n"
" {{source_name_part}}.h\" ]\n"
" }\n" " }\n"
"\n" "\n"
" custom(\"just_run_this_guy_once\") {\n" " custom(\"just_run_this_guy_once\") {\n"
" script = \"doprocessing.py\"\n" " script = \"doprocessing.py\"\n"
" source_prereqs = [ \"my_configuration.txt\" ]\n" " source_prereqs = [ \"my_configuration.txt\" ]\n"
" outputs = [ \"$target_gen_dir/insightful_output.txt\" ]\n" " outputs = [ \"$target_gen_dir/insightful_output.txt\" ]\n"
" args = [ \"--output_dir\", $target_gen_dir ]\n" " args = [ \"--output_dir\", to_build_path(target_gen_dir) ]\n"
" }\n"; " }\n";
Value RunCustom(Scope* scope, Value RunCustom(Scope* scope,
......
...@@ -51,6 +51,7 @@ ...@@ -51,6 +51,7 @@
'function_set_default_toolchain.cc', 'function_set_default_toolchain.cc',
'function_set_defaults.cc', 'function_set_defaults.cc',
'function_template.cc', 'function_template.cc',
'function_to_build_path.cc',
'function_toolchain.cc', 'function_toolchain.cc',
'function_write_file.cc', 'function_write_file.cc',
'group_target_generator.cc', 'group_target_generator.cc',
...@@ -165,6 +166,7 @@ ...@@ -165,6 +166,7 @@
'escape_unittest.cc', 'escape_unittest.cc',
'file_template_unittest.cc', 'file_template_unittest.cc',
'filesystem_utils_unittest.cc', 'filesystem_utils_unittest.cc',
'function_to_build_path_unittest.cc',
'input_conversion_unittest.cc', 'input_conversion_unittest.cc',
'label_unittest.cc', 'label_unittest.cc',
'ninja_helper_unittest.cc', 'ninja_helper_unittest.cc',
...@@ -177,6 +179,8 @@ ...@@ -177,6 +179,8 @@
'target_generator_unittest.cc', 'target_generator_unittest.cc',
'target_manager_unittest.cc', 'target_manager_unittest.cc',
'target_unittest.cc', 'target_unittest.cc',
'test_with_scope.cc',
'test_with_scope.h',
'tokenizer_unittest.cc', 'tokenizer_unittest.cc',
], ],
'dependencies': [ 'dependencies': [
......
...@@ -21,26 +21,7 @@ NinjaScriptTargetWriter::~NinjaScriptTargetWriter() { ...@@ -21,26 +21,7 @@ NinjaScriptTargetWriter::~NinjaScriptTargetWriter() {
void NinjaScriptTargetWriter::Run() { void NinjaScriptTargetWriter::Run() {
WriteEnvironment(); WriteEnvironment();
// Run the script from the dir of the BUILD file. This has no trailing std::string custom_rule_name = WriteRuleDefinition();
// slash.
const SourceDir& script_cd = target_->label().dir();
std::string script_cd_to_root = InvertDir(script_cd);
if (script_cd_to_root.empty()) {
script_cd_to_root = ".";
} else {
// Remove trailing slash.
DCHECK(script_cd_to_root[script_cd_to_root.size() - 1] == '/');
script_cd_to_root.resize(script_cd_to_root.size() - 1);
}
// Compute the relative script file name. The script string should start with
// 2 slashes, and we trim 1.
DCHECK(target_->script_values().script().is_source_absolute());
std::string script_relative_to_cd = script_cd_to_root;
const std::string& script_string = target_->script_values().script().value();
script_relative_to_cd.append(&script_string[1], script_string.size() - 1);
std::string custom_rule_name = WriteRuleDefinition(script_relative_to_cd);
std::string implicit_deps = GetSourcesImplicitDeps(); std::string implicit_deps = GetSourcesImplicitDeps();
// Collects all output files for writing below. // Collects all output files for writing below.
...@@ -48,8 +29,7 @@ void NinjaScriptTargetWriter::Run() { ...@@ -48,8 +29,7 @@ void NinjaScriptTargetWriter::Run() {
if (has_sources()) { if (has_sources()) {
// Write separate rules for each input source file. // Write separate rules for each input source file.
WriteSourceRules(custom_rule_name, implicit_deps, script_cd, WriteSourceRules(custom_rule_name, implicit_deps, &output_files);
script_cd_to_root, &output_files);
} else { } else {
// No sources, write a rule that invokes the script once with the // No sources, write a rule that invokes the script once with the
// outputs as outputs, and the data as inputs. // outputs as outputs, and the data as inputs.
...@@ -70,18 +50,17 @@ void NinjaScriptTargetWriter::Run() { ...@@ -70,18 +50,17 @@ void NinjaScriptTargetWriter::Run() {
WriteStamp(output_files); WriteStamp(output_files);
} }
std::string NinjaScriptTargetWriter::WriteRuleDefinition( std::string NinjaScriptTargetWriter::WriteRuleDefinition() {
const std::string& script_relative_to_cd) {
// Make a unique name for this rule. // Make a unique name for this rule.
//
// Use a unique name for the response file when there are multiple build
// steps so that they don't stomp on each other. When there are no sources,
// there will be only one invocation so we can use a simple name.
std::string target_label = target_->label().GetUserVisibleName(true); std::string target_label = target_->label().GetUserVisibleName(true);
std::string custom_rule_name(target_label); std::string custom_rule_name(target_label);
ReplaceChars(custom_rule_name, ":/()", "_", &custom_rule_name); ReplaceChars(custom_rule_name, ":/()", "_", &custom_rule_name);
custom_rule_name.append("_rule"); custom_rule_name.append("_rule");
// Use a unique name for the response file when there are multiple build
// steps so that they don't stomp on each other. When there are no sources,
// there will be only one invocation so we can use a simple name.
if (settings_->IsWin()) { if (settings_->IsWin()) {
// Send through gyp-win-tool and use a response file. // Send through gyp-win-tool and use a response file.
std::string rspfile = custom_rule_name; std::string rspfile = custom_rule_name;
...@@ -91,16 +70,14 @@ std::string NinjaScriptTargetWriter::WriteRuleDefinition( ...@@ -91,16 +70,14 @@ std::string NinjaScriptTargetWriter::WriteRuleDefinition(
out_ << "rule " << custom_rule_name << std::endl; out_ << "rule " << custom_rule_name << std::endl;
out_ << " command = $pythonpath gyp-win-tool action-wrapper $arch " out_ << " command = $pythonpath gyp-win-tool action-wrapper $arch "
<< rspfile << " "; << rspfile << std::endl;
path_output_.WriteDir(out_, target_->label().dir(),
PathOutput::DIR_NO_LAST_SLASH);
out_ << std::endl;
out_ << " description = CUSTOM " << target_label << std::endl; out_ << " description = CUSTOM " << target_label << std::endl;
out_ << " restat = 1" << std::endl; out_ << " restat = 1" << std::endl;
out_ << " rspfile = " << rspfile << std::endl; out_ << " rspfile = " << rspfile << std::endl;
// The build command goes in the rsp file. // The build command goes in the rsp file.
out_ << " rspfile_content = $pythonpath " << script_relative_to_cd; out_ << " rspfile_content = $pythonpath ";
path_output_.WriteFile(out_, target_->script_values().script());
for (size_t i = 0; i < target_->script_values().args().size(); i++) { for (size_t i = 0; i < target_->script_values().args().size(); i++) {
const std::string& arg = target_->script_values().args()[i]; const std::string& arg = target_->script_values().args()[i];
out_ << " "; out_ << " ";
...@@ -112,7 +89,8 @@ std::string NinjaScriptTargetWriter::WriteRuleDefinition( ...@@ -112,7 +89,8 @@ std::string NinjaScriptTargetWriter::WriteRuleDefinition(
out_ << " command = cd "; out_ << " command = cd ";
path_output_.WriteDir(out_, target_->label().dir(), path_output_.WriteDir(out_, target_->label().dir(),
PathOutput::DIR_NO_LAST_SLASH); PathOutput::DIR_NO_LAST_SLASH);
out_ << "; $pythonpath " << script_relative_to_cd; out_ << "; $pythonpath ";
path_output_.WriteFile(out_, target_->script_values().script());
for (size_t i = 0; i < target_->script_values().args().size(); i++) { for (size_t i = 0; i < target_->script_values().args().size(); i++) {
const std::string& arg = target_->script_values().args()[i]; const std::string& arg = target_->script_values().args()[i];
out_ << " "; out_ << " ";
...@@ -145,8 +123,6 @@ void NinjaScriptTargetWriter::WriteArg(const std::string& arg) { ...@@ -145,8 +123,6 @@ void NinjaScriptTargetWriter::WriteArg(const std::string& arg) {
void NinjaScriptTargetWriter::WriteSourceRules( void NinjaScriptTargetWriter::WriteSourceRules(
const std::string& custom_rule_name, const std::string& custom_rule_name,
const std::string& implicit_deps, const std::string& implicit_deps,
const SourceDir& script_cd,
const std::string& script_cd_to_root,
std::vector<OutputFile>* output_files) { std::vector<OutputFile>* output_files) {
// Construct the template for generating the output files from each source. // Construct the template for generating the output files from each source.
const Target::FileList& outputs = target_->script_values().outputs(); const Target::FileList& outputs = target_->script_values().outputs();
...@@ -162,9 +138,6 @@ void NinjaScriptTargetWriter::WriteSourceRules( ...@@ -162,9 +138,6 @@ void NinjaScriptTargetWriter::WriteSourceRules(
// Prevent re-allocating each time by initializing outside the loop. // Prevent re-allocating each time by initializing outside the loop.
std::vector<std::string> output_template_result; std::vector<std::string> output_template_result;
// Path output formatter for wrigin source paths passed to the script.
PathOutput script_source_path_output(script_cd, ESCAPE_SHELL, true);
const Target::FileList& sources = target_->sources(); const Target::FileList& sources = target_->sources();
for (size_t i = 0; i < sources.size(); i++) { for (size_t i = 0; i < sources.size(); i++) {
// Write outputs for this source file computed by the template. // Write outputs for this source file computed by the template.
...@@ -188,7 +161,7 @@ void NinjaScriptTargetWriter::WriteSourceRules( ...@@ -188,7 +161,7 @@ void NinjaScriptTargetWriter::WriteSourceRules(
// OutputFile object by putting a non-output-relative path in it to signal // OutputFile object by putting a non-output-relative path in it to signal
// that the PathWriter should not prepend directories. // that the PathWriter should not prepend directories.
out_ << " source = "; out_ << " source = ";
script_source_path_output.WriteFile(out_, sources[i]); path_output_.WriteFile(out_, sources[i]);
out_ << std::endl; out_ << std::endl;
out_ << " source_name_part = " out_ << " source_name_part = "
......
...@@ -24,7 +24,7 @@ class NinjaScriptTargetWriter : public NinjaTargetWriter { ...@@ -24,7 +24,7 @@ class NinjaScriptTargetWriter : public NinjaTargetWriter {
// Returns the name of the custom rule generated. This will be based on the // Returns the name of the custom rule generated. This will be based on the
// target name, and will include the string "$unique_name" if there are // target name, and will include the string "$unique_name" if there are
// multiple inputs. // multiple inputs.
std::string WriteRuleDefinition(const std::string& script_relative_to_cd); std::string WriteRuleDefinition();
// Writes the rules for compiling each source, writing all output files // Writes the rules for compiling each source, writing all output files
// to the given vector. // to the given vector.
...@@ -33,8 +33,6 @@ class NinjaScriptTargetWriter : public NinjaTargetWriter { ...@@ -33,8 +33,6 @@ class NinjaScriptTargetWriter : public NinjaTargetWriter {
// to each build step, it starts with a "|" if it's nonempty. // to each build step, it starts with a "|" if it's nonempty.
void WriteSourceRules(const std::string& custom_rule_name, void WriteSourceRules(const std::string& custom_rule_name,
const std::string& implicit_deps, const std::string& implicit_deps,
const SourceDir& script_cd,
const std::string& script_cd_to_root,
std::vector<OutputFile>* output_files); std::vector<OutputFile>* output_files);
void WriteArg(const std::string& arg); void WriteArg(const std::string& arg);
......
...@@ -27,22 +27,14 @@ const Value* ScopePerFileProvider::GetProgrammaticValue( ...@@ -27,22 +27,14 @@ const Value* ScopePerFileProvider::GetProgrammaticValue(
if (ident == variables::kPythonPath) if (ident == variables::kPythonPath)
return GetPythonPath(); return GetPythonPath();
if (ident == variables::kRelativeBuildToSourceRootDir)
return GetRelativeBuildToSourceRootDir();
if (ident == variables::kRelativeRootOutputDir)
return GetRelativeRootOutputDir();
if (ident == variables::kRelativeRootGenDir)
return GetRelativeRootGenDir();
if (ident == variables::kRelativeSourceRootDir)
return GetRelativeSourceRootDir();
if (ident == variables::kRelativeTargetOutputDir)
return GetRelativeTargetOutputDir();
if (ident == variables::kRelativeTargetGenDir)
return GetRelativeTargetGenDir();
if (ident == variables::kRootGenDir) if (ident == variables::kRootGenDir)
return GetRootGenDir(); return GetRootGenDir();
if (ident == variables::kRootOutDir)
return GetRootOutDir();
if (ident == variables::kTargetGenDir) if (ident == variables::kTargetGenDir)
return GetTargetGenDir(); return GetTargetGenDir();
if (ident == variables::kTargetOutDir)
return GetTargetOutDir();
return NULL; return NULL;
} }
...@@ -73,62 +65,6 @@ const Value* ScopePerFileProvider::GetPythonPath() { ...@@ -73,62 +65,6 @@ const Value* ScopePerFileProvider::GetPythonPath() {
return python_path_.get(); return python_path_.get();
} }
const Value* ScopePerFileProvider::GetRelativeBuildToSourceRootDir() {
if (!relative_build_to_source_root_dir_) {
const SourceDir& build_dir =
scope_->settings()->build_settings()->build_dir();
relative_build_to_source_root_dir_.reset(
new Value(NULL, InvertDirWithNoLastSlash(build_dir)));
}
return relative_build_to_source_root_dir_.get();
}
const Value* ScopePerFileProvider::GetRelativeRootOutputDir() {
if (!relative_root_output_dir_) {
relative_root_output_dir_.reset(new Value(NULL,
GetRelativeRootWithNoLastSlash() +
GetRootOutputDirWithNoLastSlash(scope_->settings())));
}
return relative_root_output_dir_.get();
}
const Value* ScopePerFileProvider::GetRelativeRootGenDir() {
if (!relative_root_gen_dir_) {
relative_root_gen_dir_.reset(new Value(NULL,
GetRelativeRootWithNoLastSlash() +
GetRootGenDirWithNoLastSlash(scope_->settings())));
}
return relative_root_gen_dir_.get();
}
const Value* ScopePerFileProvider::GetRelativeSourceRootDir() {
if (!relative_source_root_dir_) {
relative_source_root_dir_.reset(new Value(NULL,
GetRelativeRootWithNoLastSlash()));
}
return relative_source_root_dir_.get();
}
const Value* ScopePerFileProvider::GetRelativeTargetOutputDir() {
if (!relative_target_output_dir_) {
relative_target_output_dir_.reset(new Value(NULL,
GetRelativeRootWithNoLastSlash() +
GetRootOutputDirWithNoLastSlash(scope_->settings()) + "/obj" +
GetFileDirWithNoLastSlash()));
}
return relative_target_output_dir_.get();
}
const Value* ScopePerFileProvider::GetRelativeTargetGenDir() {
if (!relative_target_gen_dir_) {
relative_target_gen_dir_.reset(new Value(NULL,
GetRelativeRootWithNoLastSlash() +
GetRootGenDirWithNoLastSlash(scope_->settings()) +
GetFileDirWithNoLastSlash()));
}
return relative_target_gen_dir_.get();
}
const Value* ScopePerFileProvider::GetRootGenDir() { const Value* ScopePerFileProvider::GetRootGenDir() {
if (!root_gen_dir_) { if (!root_gen_dir_) {
root_gen_dir_.reset(new Value(NULL, root_gen_dir_.reset(new Value(NULL,
...@@ -137,6 +73,14 @@ const Value* ScopePerFileProvider::GetRootGenDir() { ...@@ -137,6 +73,14 @@ const Value* ScopePerFileProvider::GetRootGenDir() {
return root_gen_dir_.get(); return root_gen_dir_.get();
} }
const Value* ScopePerFileProvider::GetRootOutDir() {
if (!root_out_dir_) {
root_out_dir_.reset(new Value(NULL,
"/" + GetRootOutputDirWithNoLastSlash(scope_->settings())));
}
return root_out_dir_.get();
}
const Value* ScopePerFileProvider::GetTargetGenDir() { const Value* ScopePerFileProvider::GetTargetGenDir() {
if (!target_gen_dir_) { if (!target_gen_dir_) {
target_gen_dir_.reset(new Value(NULL, target_gen_dir_.reset(new Value(NULL,
...@@ -147,6 +91,16 @@ const Value* ScopePerFileProvider::GetTargetGenDir() { ...@@ -147,6 +91,16 @@ const Value* ScopePerFileProvider::GetTargetGenDir() {
return target_gen_dir_.get(); return target_gen_dir_.get();
} }
const Value* ScopePerFileProvider::GetTargetOutDir() {
if (!target_out_dir_) {
target_out_dir_.reset(new Value(NULL,
"/" +
GetRootOutputDirWithNoLastSlash(scope_->settings()) + "/obj" +
GetFileDirWithNoLastSlash()));
}
return target_out_dir_.get();
}
// static // static
std::string ScopePerFileProvider::GetRootOutputDirWithNoLastSlash( std::string ScopePerFileProvider::GetRootOutputDirWithNoLastSlash(
const Settings* settings) { const Settings* settings) {
...@@ -173,16 +127,3 @@ std::string ScopePerFileProvider::GetFileDirWithNoLastSlash() const { ...@@ -173,16 +127,3 @@ std::string ScopePerFileProvider::GetFileDirWithNoLastSlash() const {
dir_value[dir_value.size() - 1] == '/'); dir_value[dir_value.size() - 1] == '/');
return dir_value.substr(1, dir_value.size() - 2); return dir_value.substr(1, dir_value.size() - 2);
} }
std::string ScopePerFileProvider::GetRelativeRootWithNoLastSlash() const {
return InvertDirWithNoLastSlash(scope_->GetSourceDir());
}
// static
std::string ScopePerFileProvider::InvertDirWithNoLastSlash(
const SourceDir& dir) {
std::string inverted = InvertDir(dir);
if (inverted.empty())
return ".";
return inverted.substr(0, inverted.size() - 1);
}
...@@ -25,37 +25,24 @@ class ScopePerFileProvider : public Scope::ProgrammaticProvider { ...@@ -25,37 +25,24 @@ class ScopePerFileProvider : public Scope::ProgrammaticProvider {
const Value* GetCurrentToolchain(); const Value* GetCurrentToolchain();
const Value* GetDefaultToolchain(); const Value* GetDefaultToolchain();
const Value* GetPythonPath(); const Value* GetPythonPath();
const Value* GetRelativeBuildToSourceRootDir();
const Value* GetRelativeRootOutputDir();
const Value* GetRelativeRootGenDir();
const Value* GetRelativeSourceRootDir();
const Value* GetRelativeTargetOutputDir();
const Value* GetRelativeTargetGenDir();
const Value* GetRootGenDir(); const Value* GetRootGenDir();
const Value* GetRootOutDir();
const Value* GetTargetGenDir(); const Value* GetTargetGenDir();
const Value* GetTargetOutDir();
static std::string GetRootOutputDirWithNoLastSlash(const Settings* settings); static std::string GetRootOutputDirWithNoLastSlash(const Settings* settings);
static std::string GetRootGenDirWithNoLastSlash(const Settings* settings); static std::string GetRootGenDirWithNoLastSlash(const Settings* settings);
std::string GetFileDirWithNoLastSlash() const; std::string GetFileDirWithNoLastSlash() const;
std::string GetRelativeRootWithNoLastSlash() const;
// Inverts the given directory, returning it with no trailing slash. If the
// result would be empty, "." is returned to indicate the current dir.
static std::string InvertDirWithNoLastSlash(const SourceDir& dir);
// All values are lazily created. // All values are lazily created.
scoped_ptr<Value> current_toolchain_; scoped_ptr<Value> current_toolchain_;
scoped_ptr<Value> default_toolchain_; scoped_ptr<Value> default_toolchain_;
scoped_ptr<Value> python_path_; scoped_ptr<Value> python_path_;
scoped_ptr<Value> relative_build_to_source_root_dir_;
scoped_ptr<Value> relative_root_output_dir_;
scoped_ptr<Value> relative_root_gen_dir_;
scoped_ptr<Value> relative_source_root_dir_;
scoped_ptr<Value> relative_target_output_dir_;
scoped_ptr<Value> relative_target_gen_dir_;
scoped_ptr<Value> root_gen_dir_; scoped_ptr<Value> root_gen_dir_;
scoped_ptr<Value> root_out_dir_;
scoped_ptr<Value> target_gen_dir_; scoped_ptr<Value> target_gen_dir_;
scoped_ptr<Value> target_out_dir_;
DISALLOW_COPY_AND_ASSIGN(ScopePerFileProvider); DISALLOW_COPY_AND_ASSIGN(ScopePerFileProvider);
}; };
......
...@@ -31,20 +31,12 @@ TEST(ScopePerFileProvider, Expected) { ...@@ -31,20 +31,12 @@ TEST(ScopePerFileProvider, Expected) {
variables::kCurrentToolchain)->string_value()); variables::kCurrentToolchain)->string_value());
EXPECT_EQ("//toolchain:default", provider.GetProgrammaticValue( EXPECT_EQ("//toolchain:default", provider.GetProgrammaticValue(
variables::kDefaultToolchain)->string_value()); variables::kDefaultToolchain)->string_value());
EXPECT_EQ("../..",provider.GetProgrammaticValue(
variables::kRelativeBuildToSourceRootDir)->string_value());
EXPECT_EQ("../out/Debug", provider.GetProgrammaticValue(
variables::kRelativeRootOutputDir)->string_value());
EXPECT_EQ("../out/Debug/gen", provider.GetProgrammaticValue(
variables::kRelativeRootGenDir)->string_value());
EXPECT_EQ("..", provider.GetProgrammaticValue(
variables::kRelativeSourceRootDir)->string_value());
EXPECT_EQ("../out/Debug/obj/source", provider.GetProgrammaticValue(
variables::kRelativeTargetOutputDir)->string_value());
EXPECT_EQ("../out/Debug/gen/source", provider.GetProgrammaticValue(
variables::kRelativeTargetGenDir)->string_value());
EXPECT_EQ("//out/Debug/gen",provider.GetProgrammaticValue( EXPECT_EQ("//out/Debug/gen",provider.GetProgrammaticValue(
variables::kRootGenDir)->string_value()); variables::kRootGenDir)->string_value());
EXPECT_EQ("//out/Debug",provider.GetProgrammaticValue(
variables::kRootOutDir)->string_value());
EXPECT_EQ("//out/Debug/gen/source",provider.GetProgrammaticValue( EXPECT_EQ("//out/Debug/gen/source",provider.GetProgrammaticValue(
variables::kTargetGenDir)->string_value()); variables::kTargetGenDir)->string_value());
EXPECT_EQ("//out/Debug/obj/source",provider.GetProgrammaticValue(
variables::kTargetOutDir)->string_value());
} }
...@@ -321,6 +321,8 @@ component("base") { ...@@ -321,6 +321,8 @@ component("base") {
"message_loop/message_pump_ozone.h", "message_loop/message_pump_ozone.h",
"message_loop/message_pump_win.cc", "message_loop/message_pump_win.cc",
"message_loop/message_pump_win.h", "message_loop/message_pump_win.h",
"message_loop/message_pump_x11.cc",
"message_loop/message_pump_x11.h",
"metrics/field_trial.cc", "metrics/field_trial.cc",
"metrics/field_trial.h", "metrics/field_trial.h",
"metrics/sample_map.cc", "metrics/sample_map.cc",
......
...@@ -90,9 +90,10 @@ config("compiler") { ...@@ -90,9 +90,10 @@ config("compiler") {
"-pthread", "-pthread",
"-pipe", # Use pipes for communicating between sub-processes. Faster. "-pipe", # Use pipes for communicating between sub-processes. Faster.
] ]
gold_path = to_build_path("//third_party/gold")
ldflags += [ ldflags += [
# Use Gold for linking: it is checked out in the source tree. # Use Gold for linking: it is checked out in the source tree.
"-B$relative_build_to_source_root_dir/third_party/gold", "-B$gold_path",
"-fPIC", "-fPIC",
"-pthread", "-pthread",
......
...@@ -2,8 +2,8 @@ ...@@ -2,8 +2,8 @@
# Use of this source code is governed by a BSD-style license that can be # Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file. # found in the LICENSE file.
cc = "$relative_build_to_source_root_dir/third_party/llvm-build/Release+Asserts/bin/clang" cc = to_build_path("//third_party/llvm-build/Release+Asserts/bin/clang")
cxx = "$relative_build_to_source_root_dir/third_party/llvm-build/Release+Asserts/bin/clang++" cxx = to_build_path("//third_party/llvm-build/Release+Asserts/bin/clang++")
ld = cxx ld = cxx
toolchain("clang") { toolchain("clang") {
......
...@@ -173,8 +173,6 @@ static_library("utility") { ...@@ -173,8 +173,6 @@ static_library("utility") {
# Resources -------------------------------------------------------------------- # Resources --------------------------------------------------------------------
print("resourcing")
group("chrome_resources") { group("chrome_resources") {
deps = [ deps = [
":browser_resources", ":browser_resources",
...@@ -194,7 +192,6 @@ grit("renderer_resources") { ...@@ -194,7 +192,6 @@ grit("renderer_resources") {
external = true external = true
source = "renderer/resources/renderer_resources.grd" source = "renderer/resources/renderer_resources.grd"
} }
print("resourcing 2")
group("chrome_strings") { group("chrome_strings") {
deps = [ deps = [
...@@ -220,7 +217,6 @@ grit("google_chrome_strings") { ...@@ -220,7 +217,6 @@ grit("google_chrome_strings") {
external = true external = true
source = "app/google_chrome_strings.grd" source = "app/google_chrome_strings.grd"
} }
print("resourcing 3")
group("chrome_extra_resources") { group("chrome_extra_resources") {
deps = [ deps = [
...@@ -251,7 +247,6 @@ grit("translate_internals_resources") { ...@@ -251,7 +247,6 @@ grit("translate_internals_resources") {
external = true external = true
source = "browser/resources/translate_internals_resources.grd" source = "browser/resources/translate_internals_resources.grd"
} }
print("resourcing 4")
group("theme_resources") { group("theme_resources") {
deps = [ deps = [
...@@ -263,5 +258,3 @@ grit("app_theme_resources") { ...@@ -263,5 +258,3 @@ grit("app_theme_resources") {
external = true external = true
source = "app/theme/theme_resources.grd" source = "app/theme/theme_resources.grd"
} }
print("resourcing done")
...@@ -9,17 +9,15 @@ template("grit") { ...@@ -9,17 +9,15 @@ template("grit") {
"Neither \"sources\" nor \"outputs\" can be defined for the grit " + "Neither \"sources\" nor \"outputs\" can be defined for the grit " +
"template $target_name") "template $target_name")
resource_ids = "$relative_source_root_dir/tools/gritsettings/resource_ids" resource_ids = to_build_path("//tools/gritsettings/resource_ids")
output_dir = "$relative_target_gen_dir" output_dir = to_build_path(target_gen_dir)
grit_info_script = to_build_path("//tools/grit/grit_info.py")
# Note that this needs to be source-absolute since the current directory will source_path = to_build_path(source)
# be that of the file invoking the template, not this file.
grit_info_script = "$relative_source_root_dir/tools/grit/grit_info.py"
grit_inputs = exec_script(grit_info_script, grit_inputs = exec_script(grit_info_script,
[ "--inputs", source, "-f", resource_ids], "list lines") [ "--inputs", source_path, "-f", resource_ids], "list lines")
grit_outputs = exec_script(grit_info_script, grit_outputs = exec_script(grit_info_script,
[ "--outputs", "$output_dir", source, "-f", resource_ids ], [ "--outputs", "$output_dir", source_path, "-f", resource_ids ],
"list lines") "list lines")
# The current grit setup makes an file in $target_gen_dir/grit/foo.h that # The current grit setup makes an file in $target_gen_dir/grit/foo.h that
...@@ -33,15 +31,15 @@ template("grit") { ...@@ -33,15 +31,15 @@ template("grit") {
grit_custom_target = target_name + "_grit" grit_custom_target = target_name + "_grit"
custom(grit_custom_target) { custom(grit_custom_target) {
script = "$relative_source_root_dir/tools/grit/grit.py" script = "//tools/grit/grit.py"
source_prereqs = grit_inputs source_prereqs = grit_inputs
outputs = grit_outputs outputs = grit_outputs
# TODO(brettw) grit_defines. # TODO(brettw) grit_defines.
args = [ args = [
"-i", source, "build", "-i", source_path, "build",
"-f", resource_ids, "-f", resource_ids,
"-o", relative_target_gen_dir, "-o", output_dir,
] ]
} }
......
// 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.
#include "tools/gn/test_with_scope.h"
TestWithScope::TestWithScope()
: build_settings_(),
toolchain_(Label(SourceDir("//toolchain/"), "tc")),
settings_(&build_settings_, &toolchain_, std::string()),
scope_(&settings_) {
}
TestWithScope::~TestWithScope() {
}
// 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.
#ifndef TOOLS_GN_TEST_WITH_SCOPE_H_
#define TOOLS_GN_TEST_WITH_SCOPE_H_
#include "base/basictypes.h"
#include "tools/gn/build_settings.h"
#include "tools/gn/scope.h"
#include "tools/gn/settings.h"
#include "tools/gn/toolchain.h"
// A helper class for setting up a Scope that a test can use. It makes a
// toolchain and sets up all the build state.
class TestWithScope {
public:
TestWithScope();
~TestWithScope();
BuildSettings* build_settings() { return &build_settings_; }
Settings* settings() { return &settings_; }
Scope* scope() { return &scope_; }
private:
BuildSettings build_settings_;
Toolchain toolchain_;
Settings settings_;
Scope scope_;
DISALLOW_COPY_AND_ASSIGN(TestWithScope);
};
#endif // TOOLS_GN_TEST_WITH_SCOPE_H_
This diff is collapsed.
...@@ -41,38 +41,22 @@ extern const char kPythonPath[]; ...@@ -41,38 +41,22 @@ extern const char kPythonPath[];
extern const char kPythonPath_HelpShort[]; extern const char kPythonPath_HelpShort[];
extern const char kPythonPath_Help[]; extern const char kPythonPath_Help[];
extern const char kRelativeBuildToSourceRootDir[];
extern const char kRelativeBuildToSourceRootDir_HelpShort[];
extern const char kRelativeBuildToSourceRootDir_Help[];
extern const char kRelativeRootGenDir[];
extern const char kRelativeRootGenDir_HelpShort[];
extern const char kRelativeRootGenDir_Help[];
extern const char kRelativeRootOutputDir[];
extern const char kRelativeRootOutputDir_HelpShort[];
extern const char kRelativeRootOutputDir_Help[];
extern const char kRelativeSourceRootDir[];
extern const char kRelativeSourceRootDir_HelpShort[];
extern const char kRelativeSourceRootDir_Help[];
extern const char kRelativeTargetGenDir[];
extern const char kRelativeTargetGenDir_HelpShort[];
extern const char kRelativeTargetGenDir_Help[];
extern const char kRelativeTargetOutputDir[];
extern const char kRelativeTargetOutputDir_HelpShort[];
extern const char kRelativeTargetOutputDir_Help[];
extern const char kRootGenDir[]; extern const char kRootGenDir[];
extern const char kRootGenDir_HelpShort[]; extern const char kRootGenDir_HelpShort[];
extern const char kRootGenDir_Help[]; extern const char kRootGenDir_Help[];
extern const char kRootOutDir[];
extern const char kRootOutDir_HelpShort[];
extern const char kRootOutDir_Help[];
extern const char kTargetGenDir[]; extern const char kTargetGenDir[];
extern const char kTargetGenDir_HelpShort[]; extern const char kTargetGenDir_HelpShort[];
extern const char kTargetGenDir_Help[]; extern const char kTargetGenDir_Help[];
extern const char kTargetOutDir[];
extern const char kTargetOutDir_HelpShort[];
extern const char kTargetOutDir_Help[];
// Target vars ----------------------------------------------------------------- // Target vars -----------------------------------------------------------------
extern const char kAllDependentConfigs[]; extern const char kAllDependentConfigs[];
......
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