GN: Make write_runtime_deps take effect only a target is resolved
BUG=604104
Review URL: https://codereview.chromium.org/1892393002
Cr-Original-Commit-Position: refs/heads/master@{#388496}
Cr-Mirrored-From: https://chromium.googlesource.com/chromium/src
Cr-Mirrored-Commit: fb8986d4df3e8b84db16cd5d719a2e38bb8a7b02
diff --git a/tools/gn/BUILD.gn b/tools/gn/BUILD.gn
index 2728c0d..bb36b1f 100644
--- a/tools/gn/BUILD.gn
+++ b/tools/gn/BUILD.gn
@@ -277,7 +277,6 @@
"function_write_file_unittest.cc",
"functions_target_unittest.cc",
"functions_unittest.cc",
- "group_target_generator_unittest.cc",
"header_checker_unittest.cc",
"inherited_libraries_unittest.cc",
"input_conversion_unittest.cc",
diff --git a/tools/gn/group_target_generator_unittest.cc b/tools/gn/group_target_generator_unittest.cc
deleted file mode 100644
index 3b0c824..0000000
--- a/tools/gn/group_target_generator_unittest.cc
+++ /dev/null
@@ -1,46 +0,0 @@
-// Copyright 2016 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/group_target_generator.h"
-#include "tools/gn/scheduler.h"
-#include "tools/gn/test_with_scope.h"
-
-namespace {
-
-// Returns true on success, false if write_file signaled an error.
-bool ParseWriteRuntimeDeps(Scope* scope, const std::string& value) {
- TestParseInput input(
- "group(\"foo\") { write_runtime_deps = " + value + "}");
- if (input.has_error())
- return false;
-
- Err err;
- input.parsed()->Execute(scope, &err);
- return !err.has_error();
-}
-
-} // namespace
-
-
-// Tests that actions can't have output substitutions.
-TEST(GroupTargetGenerator, WriteRuntimeDeps) {
- Scheduler scheduler;
- TestWithScope setup;
- Scope::ItemVector items_;
- setup.scope()->set_item_collector(&items_);
-
- // Should refuse to write files outside of the output dir.
- EXPECT_FALSE(ParseWriteRuntimeDeps(setup.scope(), "\"//foo.txt\""));
- EXPECT_EQ(0U, scheduler.GetWriteRuntimeDepsTargets().size());
-
- // Should fail for garbage inputs.
- EXPECT_FALSE(ParseWriteRuntimeDeps(setup.scope(), "0"));
- EXPECT_EQ(0U, scheduler.GetWriteRuntimeDepsTargets().size());
-
- // Should be able to write inside the out dir.
- EXPECT_TRUE(ParseWriteRuntimeDeps(setup.scope(), "\"//out/Debug/foo.txt\""));
- EXPECT_EQ(1U, scheduler.GetWriteRuntimeDepsTargets().size());
-}
-
diff --git a/tools/gn/runtime_deps_unittest.cc b/tools/gn/runtime_deps_unittest.cc
index 915fbc2..6c2013d 100644
--- a/tools/gn/runtime_deps_unittest.cc
+++ b/tools/gn/runtime_deps_unittest.cc
@@ -8,6 +8,7 @@
#include "testing/gtest/include/gtest/gtest.h"
#include "tools/gn/runtime_deps.h"
+#include "tools/gn/scheduler.h"
#include "tools/gn/target.h"
#include "tools/gn/test_with_scope.h"
@@ -282,3 +283,31 @@
MakePair("../../action.output", &action)) !=
result.end()) << GetVectorDescription(result);
}
+
+// Tests that actions can't have output substitutions.
+TEST(RuntimeDeps, WriteRuntimeDepsVariable) {
+ Scheduler scheduler;
+ TestWithScope setup;
+ Err err;
+
+ // Should refuse to write files outside of the output dir.
+ EXPECT_FALSE(setup.ExecuteSnippet(
+ "group(\"foo\") { write_runtime_deps = \"//foo.txt\" }", &err));
+
+ // Should fail for garbage inputs.
+ err = Err();
+ EXPECT_FALSE(setup.ExecuteSnippet(
+ "group(\"foo\") { write_runtime_deps = 0 }", &err));
+
+ // Should be able to write inside the out dir, and shouldn't write the one
+ // in the else clause.
+ err = Err();
+ EXPECT_TRUE(setup.ExecuteSnippet(
+ "if (true) {\n"
+ " group(\"foo\") { write_runtime_deps = \"//out/Debug/foo.txt\" }\n"
+ "} else {\n"
+ " group(\"bar\") { write_runtime_deps = \"//out/Debug/bar.txt\" }\n"
+ "}", &err));
+ EXPECT_EQ(1U, setup.items().size());
+ EXPECT_EQ(1U, scheduler.GetWriteRuntimeDepsTargets().size());
+}
diff --git a/tools/gn/target.cc b/tools/gn/target.cc
index 18c353e..e88c82f 100644
--- a/tools/gn/target.cc
+++ b/tools/gn/target.cc
@@ -324,6 +324,9 @@
CheckSourcesGenerated();
}
+ if (!write_runtime_deps_output_.value().empty())
+ g_scheduler->AddWriteRuntimeDepsTarget(this);
+
return true;
}
diff --git a/tools/gn/target_generator.cc b/tools/gn/target_generator.cc
index 2132a5b..90642d4 100644
--- a/tools/gn/target_generator.cc
+++ b/tools/gn/target_generator.cc
@@ -403,6 +403,5 @@
OutputFile output_file(GetBuildSettings(), source_file);
target_->set_write_runtime_deps_output(output_file);
- g_scheduler->AddWriteRuntimeDepsTarget(target_);
return true;
}
diff --git a/tools/gn/test_with_scope.cc b/tools/gn/test_with_scope.cc
index 32d5dd6..0ddd463 100644
--- a/tools/gn/test_with_scope.cc
+++ b/tools/gn/test_with_scope.cc
@@ -24,6 +24,7 @@
settings_.set_default_toolchain_label(toolchain_.label());
SetupToolchain(&toolchain_);
+ scope_.set_item_collector(&items_);
}
TestWithScope::~TestWithScope() {
@@ -37,6 +38,28 @@
return result;
}
+bool TestWithScope::ExecuteSnippet(const std::string& str, Err* err) {
+ TestParseInput input(str);
+ if (input.has_error()) {
+ *err = input.parse_err();
+ return false;
+ }
+
+ size_t first_item = items_.size();
+ input.parsed()->Execute(&scope_, err);
+ if (err->has_error())
+ return false;
+
+ for (size_t i = first_item; i < items_.size(); ++i) {
+ CHECK(items_[i]->AsTarget() != nullptr)
+ << "Only targets are supported in ExecuteSnippet()";
+ items_[i]->AsTarget()->SetToolchain(&toolchain_);
+ if (!items_[i]->OnResolved(err))
+ return false;
+ }
+ return true;
+}
+
// static
void TestWithScope::SetupToolchain(Toolchain* toolchain) {
Err err;
diff --git a/tools/gn/test_with_scope.h b/tools/gn/test_with_scope.h
index fa6fb4b..8853243 100644
--- a/tools/gn/test_with_scope.h
+++ b/tools/gn/test_with_scope.h
@@ -34,6 +34,7 @@
Toolchain* toolchain() { return &toolchain_; }
const Toolchain* toolchain() const { return &toolchain_; }
Scope* scope() { return &scope_; }
+ const Scope::ItemVector& items() { return items_; }
// This buffer accumulates output from any print() commands executed in the
// context of this test. Note that the implementation of this is not
@@ -44,6 +45,11 @@
// assert if the label isn't valid (this is intended for hardcoded labels).
Label ParseLabel(const std::string& str) const;
+ // Parses, evaluates, and resolves targets from the given snippet of code.
+ // All targets must be defined in dependency order (does not use a Builder,
+ // just blindly resolves all targets in order).
+ bool ExecuteSnippet(const std::string& str, Err* err);
+
// Fills in the tools for the given toolchain with reasonable default values.
// The toolchain in this object will be automatically set up with this
// function, it is exposed to allow tests to get the same functionality for
@@ -62,6 +68,7 @@
Settings settings_;
Toolchain toolchain_;
Scope scope_;
+ Scope::ItemVector items_;
// Supplies the scope with built-in variables like root_out_dir.
ScopePerFileProvider scope_progammatic_provider_;