List .gn file in build.ninja.d.
This way, gn reruns when the .gn file is touched.
Bug: 24
Change-Id: Iabc21ee5f4b82106c7d8004f8372b3d83471b515
Reviewed-on: https://gn-review.googlesource.com/c/3321
Commit-Queue: Brett Wilson <brettw@chromium.org>
Reviewed-by: Brett Wilson <brettw@chromium.org>
diff --git a/build/gen.py b/build/gen.py
index 9f5eaf2..56a6566 100755
--- a/build/gen.py
+++ b/build/gen.py
@@ -586,6 +586,7 @@
'tools/gn/runtime_deps_unittest.cc',
'tools/gn/scope_per_file_provider_unittest.cc',
'tools/gn/scope_unittest.cc',
+ 'tools/gn/setup_unittest.cc',
'tools/gn/source_dir_unittest.cc',
'tools/gn/source_file_unittest.cc',
'tools/gn/string_utils_unittest.cc',
diff --git a/tools/gn/command_analyze.cc b/tools/gn/command_analyze.cc
index 9aa698b..d3b24bf 100644
--- a/tools/gn/command_analyze.cc
+++ b/tools/gn/command_analyze.cc
@@ -106,6 +106,7 @@
return 1;
}
+ // Deliberately leaked to avoid expensive process teardown.
Setup* setup = new Setup;
if (!setup->DoSetup(args[0], false) || !setup->Run())
return 1;
diff --git a/tools/gn/command_args.cc b/tools/gn/command_args.cc
index 9980333..fac8683 100644
--- a/tools/gn/command_args.cc
+++ b/tools/gn/command_args.cc
@@ -205,6 +205,7 @@
}
int ListArgs(const std::string& build_dir) {
+ // Deliberately leaked to avoid expensive process teardown.
Setup* setup = new Setup;
if (!setup->DoSetup(build_dir, false) || !setup->Run())
return 1;
diff --git a/tools/gn/command_clean.cc b/tools/gn/command_clean.cc
index b138864..b354039 100644
--- a/tools/gn/command_clean.cc
+++ b/tools/gn/command_clean.cc
@@ -63,6 +63,7 @@
return 1;
}
+ // Deliberately leaked to avoid expensive process teardown.
Setup* setup = new Setup;
if (!setup->DoSetup(args[0], false))
return 1;
diff --git a/tools/gn/command_ls.cc b/tools/gn/command_ls.cc
index 65ec1a9..2609499 100644
--- a/tools/gn/command_ls.cc
+++ b/tools/gn/command_ls.cc
@@ -68,6 +68,7 @@
return 1;
}
+ // Deliberately leaked to avoid expensive process teardown.
Setup* setup = new Setup;
if (!setup->DoSetup(args[0], false) || !setup->Run())
return 1;
diff --git a/tools/gn/command_path.cc b/tools/gn/command_path.cc
index 333a78e..503ba6d 100644
--- a/tools/gn/command_path.cc
+++ b/tools/gn/command_path.cc
@@ -319,6 +319,7 @@
return 1;
}
+ // Deliberately leaked to avoid expensive process teardown.
Setup* setup = new Setup;
if (!setup->DoSetup(args[0], false))
return 1;
diff --git a/tools/gn/command_refs.cc b/tools/gn/command_refs.cc
index 92ecf10..1ca63ec 100644
--- a/tools/gn/command_refs.cc
+++ b/tools/gn/command_refs.cc
@@ -407,6 +407,7 @@
bool all = cmdline->HasSwitch("all");
bool all_toolchains = cmdline->HasSwitch(switches::kAllToolchains);
+ // Deliberately leaked to avoid expensive process teardown.
Setup* setup = new Setup;
if (!setup->DoSetup(args[0], false) || !setup->Run())
return 1;
diff --git a/tools/gn/exec_process_unittest.cc b/tools/gn/exec_process_unittest.cc
index 323a070..647bf42 100644
--- a/tools/gn/exec_process_unittest.cc
+++ b/tools/gn/exec_process_unittest.cc
@@ -67,7 +67,6 @@
// byte buffer and, if stdout is non-blocking, python will throw an IOError when
// a write exceeds the buffer size.
TEST(ExecProcessTest, TestLargeOutput) {
- base::ScopedTempDir temp_dir;
std::string std_out, std_err;
int exit_code;
@@ -78,7 +77,6 @@
}
TEST(ExecProcessTest, TestStdoutAndStderrOutput) {
- base::ScopedTempDir temp_dir;
std::string std_out, std_err;
int exit_code;
diff --git a/tools/gn/ninja_build_writer_unittest.cc b/tools/gn/ninja_build_writer_unittest.cc
index 55ffcc9..50530b1 100644
--- a/tools/gn/ninja_build_writer_unittest.cc
+++ b/tools/gn/ninja_build_writer_unittest.cc
@@ -113,7 +113,8 @@
target_baz.action_values().outputs() = SubstitutionList::MakeForTest(
"//out/Debug/out5.out", "//out/Debug/out6.out");
target_baz.SetToolchain(&other_toolchain);
- target_baz.action_values().set_pool(LabelPtrPair<Pool>(&another_regular_pool));
+ target_baz.action_values().set_pool(
+ LabelPtrPair<Pool>(&another_regular_pool));
ASSERT_TRUE(target_baz.OnResolved(&err));
// The console pool must be in the default toolchain.
diff --git a/tools/gn/setup.cc b/tools/gn/setup.cc
index 27c6475..6720f65 100644
--- a/tools/gn/setup.cc
+++ b/tools/gn/setup.cc
@@ -315,20 +315,25 @@
Setup::~Setup() = default;
bool Setup::DoSetup(const std::string& build_dir, bool force_create) {
- base::CommandLine* cmdline = base::CommandLine::ForCurrentProcess();
+ return DoSetup(build_dir, force_create,
+ *base::CommandLine::ForCurrentProcess());
+}
- scheduler_.set_verbose_logging(cmdline->HasSwitch(switches::kVerbose));
- if (cmdline->HasSwitch(switches::kTime) ||
- cmdline->HasSwitch(switches::kTracelog))
+bool Setup::DoSetup(const std::string& build_dir,
+ bool force_create,
+ const base::CommandLine& cmdline) {
+ scheduler_.set_verbose_logging(cmdline.HasSwitch(switches::kVerbose));
+ if (cmdline.HasSwitch(switches::kTime) ||
+ cmdline.HasSwitch(switches::kTracelog))
EnableTracing();
ScopedTrace setup_trace(TraceItem::TRACE_SETUP, "DoSetup");
- if (!FillSourceDir(*cmdline))
+ if (!FillSourceDir(cmdline))
return false;
if (!RunConfigFile())
return false;
- if (!FillOtherConfig(*cmdline))
+ if (!FillOtherConfig(cmdline))
return false;
// Must be after FillSourceDir to resolve.
@@ -344,10 +349,10 @@
}
if (fill_arguments_) {
- if (!FillArguments(*cmdline))
+ if (!FillArguments(cmdline))
return false;
}
- if (!FillPythonPath(*cmdline))
+ if (!FillPythonPath(cmdline))
return false;
// Check for unused variables in the .gn file.
@@ -361,10 +366,14 @@
}
bool Setup::Run() {
+ return Run(*base::CommandLine::ForCurrentProcess());
+}
+
+bool Setup::Run(const base::CommandLine& cmdline) {
RunPreMessageLoop();
if (!scheduler_.Run())
return false;
- return RunPostMessageLoop();
+ return RunPostMessageLoop(cmdline);
}
SourceFile Setup::GetBuildArgFile() const {
@@ -379,7 +388,7 @@
loader_->Load(root_build_file_, LocationRange(), Label());
}
-bool Setup::RunPostMessageLoop() {
+bool Setup::RunPostMessageLoop(const base::CommandLine& cmdline) {
Err err;
if (!builder_.CheckForBadItems(&err)) {
err.PrintToStdout();
@@ -387,8 +396,7 @@
}
if (!build_settings_.build_args().VerifyAllOverridesUsed(&err)) {
- if (base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kFailOnUnusedArgs)) {
+ if (cmdline.HasSwitch(switches::kFailOnUnusedArgs)) {
err.PrintToStdout();
return false;
}
@@ -416,11 +424,10 @@
}
// Write out tracing and timing if requested.
- const base::CommandLine* cmdline = base::CommandLine::ForCurrentProcess();
- if (cmdline->HasSwitch(switches::kTime))
+ if (cmdline.HasSwitch(switches::kTime))
PrintLongHelp(SummarizeTraces());
- if (cmdline->HasSwitch(switches::kTracelog))
- SaveTraces(cmdline->GetSwitchValuePath(switches::kTracelog));
+ if (cmdline.HasSwitch(switches::kTracelog))
+ SaveTraces(cmdline.GetSwitchValuePath(switches::kTracelog));
return true;
}
@@ -715,6 +722,12 @@
return false;
}
+ // Add a dependency on the build arguments file. If this changes, we want
+ // to re-generate the build. This causes the dotfile to make it into
+ // build.ninja.d.
+ g_scheduler->AddGenDependency(dotfile_name_);
+
+ // Also add a build dependency to the scope, which is used by `gn analyze`.
dotfile_scope_.AddBuildDependencyFile(SourceFile("//.gn"));
dotfile_root_->Execute(&dotfile_scope_, &err);
if (err.has_error()) {
diff --git a/tools/gn/setup.h b/tools/gn/setup.h
index 13d0da5..cca30ab 100644
--- a/tools/gn/setup.h
+++ b/tools/gn/setup.h
@@ -29,7 +29,7 @@
extern const char kDotfile_Help[];
-// Helper class to setup the build settings and environment for the various
+// Helper class to set up the build settings and environment for the various
// commands to run.
class Setup {
public:
@@ -49,12 +49,24 @@
// generation should set this to true to create it, but querying commands
// should set it to false to prevent creating oddly-named directories in case
// the user omits the build directory argument (which is easy to do).
+ //
+ // cmdline is the gn invocation command, with flags like --root and --dotfile.
+ // If no explicit cmdline is passed, base::CommandLine::ForCurrentProcess()
+ // is used.
bool DoSetup(const std::string& build_dir, bool force_create);
+ bool DoSetup(const std::string& build_dir,
+ bool force_create,
+ const base::CommandLine& cmdline);
// Runs the load, returning true on success. On failure, prints the error
// and returns false. This includes both RunPreMessageLoop() and
// RunPostMessageLoop().
+ //
+ // cmdline is the gn invocation command, with flags like --root and --dotfile.
+ // If no explicit cmdline is passed, base::CommandLine::ForCurrentProcess()
+ // is used.
bool Run();
+ bool Run(const base::CommandLine& cmdline);
Scheduler& scheduler() { return scheduler_; }
@@ -93,7 +105,7 @@
// Performs the two sets of operations to run the generation before and after
// the message loop is run.
void RunPreMessageLoop();
- bool RunPostMessageLoop();
+ bool RunPostMessageLoop(const base::CommandLine& cmdline);
// Fills build arguments. Returns true on success.
bool FillArguments(const base::CommandLine& cmdline);
diff --git a/tools/gn/setup_unittest.cc b/tools/gn/setup_unittest.cc
new file mode 100644
index 0000000..ab94ce1
--- /dev/null
+++ b/tools/gn/setup_unittest.cc
@@ -0,0 +1,44 @@
+// Copyright 2018 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/setup.h"
+
+#include "base/command_line.h"
+#include "base/files/file_util.h"
+#include "base/files/scoped_temp_dir.h"
+#include "tools/gn/filesystem_utils.h"
+#include "tools/gn/switches.h"
+#include "tools/gn/test_with_scheduler.h"
+
+using SetupTest = TestWithScheduler;
+
+static void WriteFile(const base::FilePath& file, const std::string& data) {
+ CHECK(data.size() == base::WriteFile(file, data.data(), data.size()));
+}
+
+TEST_F(SetupTest, DotGNFileIsGenDep) {
+ 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");
+ 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;
+ EXPECT_TRUE(
+ setup.DoSetup(FilePathToUTF8(build_temp_dir.GetPath()), true, cmdline));
+ std::vector<base::FilePath> gen_deps = g_scheduler->GetGenDependencies();
+ ASSERT_EQ(1u, gen_deps.size());
+ EXPECT_EQ(gen_deps[0], base::MakeAbsoluteFilePath(dot_gn_name));
+}