Fix support for empty `script_executable` value in .gn file. A recent CL [1] broke the Fuchsia build because the latter sets the `script_executable` value to the empty script in its `.gn` file. This use case is documented to let GN invoke action scripts directly. This fixes the issue and adds a unit-test for this use case. [1] https://gn-review.googlesource.com/c/gn/+/13260 Bug: None Change-Id: I2660c6de0e8f41790c60bbb072149f1d7360e7f0 Reviewed-on: https://gn-review.googlesource.com/c/gn/+/13460 Reviewed-by: Brett Wilson <brettw@chromium.org> Commit-Queue: David Turner <digit@google.com>
diff --git a/src/gn/setup.cc b/src/gn/setup.cc index 8f1bd7a..68d42b7 100644 --- a/src/gn/setup.cc +++ b/src/gn/setup.cc
@@ -126,12 +126,14 @@ help --root-target"). script_executable [optional] - Path to specific Python executable or other interpreter to use in - action targets and exec_script calls. By default GN searches the - PATH for Python to execute these scripts. + By default, GN runs the scripts used in action targets and exec_script + calls using the Python interpreter found in PATH. This value specifies the + Python executable or other interpreter to use instead. - If set to the empty string, the path specified in action targets - and exec_script calls will be executed directly. + If set to the empty string, the scripts will be executed directly. + + The command-line switch --script-executable will override this value (see + "gn help --script-executable") secondary_source [optional] Label of an alternate directory tree to find input files. When searching @@ -781,12 +783,17 @@ if (!value->VerifyTypeIs(Value::STRING, err)) { return false; } - base::FilePath python_path = - ProcessFileExtensions(UTF8ToFilePath(value->string_value())); - if (python_path.empty()) { - *err = Err(Location(), "Could not find \"" + value->string_value() + - "\" from dotfile in PATH."); - return false; + // Note that an empty string value is valid, and means that the scripts + // invoked by actions will be run directly. + base::FilePath python_path; + if (!value->string_value().empty()) { + python_path = + ProcessFileExtensions(UTF8ToFilePath(value->string_value())); + if (python_path.empty()) { + *err = Err(Location(), "Could not find \"" + value->string_value() + + "\" from dotfile in PATH."); + return false; + } } build_settings_.set_python_path(python_path); } else {
diff --git a/src/gn/setup_unittest.cc b/src/gn/setup_unittest.cc index d905355..8239589 100644 --- a/src/gn/setup_unittest.cc +++ b/src/gn/setup_unittest.cc
@@ -46,6 +46,33 @@ EXPECT_EQ(gen_deps[0], base::MakeAbsoluteFilePath(dot_gn_name)); } +TEST_F(SetupTest, EmptyScriptExecutableDoesNotGenerateError) { + base::CommandLine cmdline(base::CommandLine::NO_PROGRAM); + + // Create a temp directory containing a .gn file and a BUILDCONFIG.gn file, + // pass it as --root. + base::ScopedTempDir in_temp_dir; + ASSERT_TRUE(in_temp_dir.CreateUniqueTempDir()); + base::FilePath in_path = in_temp_dir.GetPath(); + base::FilePath dot_gn_name = in_path.Append(FILE_PATH_LITERAL(".gn")); + WriteFile(dot_gn_name, + "buildconfig = \"//BUILDCONFIG.gn\"\n" + "script_executable = \"\"\n"); + + WriteFile(in_path.Append(FILE_PATH_LITERAL("BUILDCONFIG.gn")), ""); + cmdline.AppendSwitchASCII(switches::kRoot, FilePathToUTF8(in_path)); + + // Create another temp dir for writing the generated files to. + base::ScopedTempDir build_temp_dir; + ASSERT_TRUE(build_temp_dir.CreateUniqueTempDir()); + + // Run setup and check that the .gn file is in the scheduler's gen deps. + Setup setup; + Err err; + EXPECT_TRUE(setup.DoSetupWithErr(FilePathToUTF8(build_temp_dir.GetPath()), + true, cmdline, &err)); +} + #if defined(OS_WIN) TEST_F(SetupTest, MissingScriptExeGeneratesSetupErrorOnWindows) { base::CommandLine cmdline(base::CommandLine::NO_PROGRAM);
diff --git a/src/gn/switches.cc b/src/gn/switches.cc index 6caec3a..e670517 100644 --- a/src/gn/switches.cc +++ b/src/gn/switches.cc
@@ -119,8 +119,8 @@ action targets and exec_script calls. By default GN searches the PATH for Python to execute these scripts. - If set to the empty string, the path specified in action targets - and exec_script calls will be executed directly. + If set to the empty string, the path of scripts specified in action + targets and exec_script calls will be executed directly. )"; const char kQuiet[] = "q";