[metadata] Add generated_file target type
This is a generic generated_file target type, but if the metadata attributes
are set it will act as a metadata collection.
Change-Id: Ie3a3c804ad6c69dc2db6ef8b58d705fc1105c365
Reviewed-on: https://gn-review.googlesource.com/c/3420
Commit-Queue: Julie Hockett <juliehockett@google.com>
Reviewed-by: Brett Wilson <brettw@chromium.org>
diff --git a/build/gen.py b/build/gen.py
index b5c2fbe..7a53a80 100755
--- a/build/gen.py
+++ b/build/gen.py
@@ -456,6 +456,7 @@
'tools/gn/function_template.cc',
'tools/gn/function_toolchain.cc',
'tools/gn/function_write_file.cc',
+ 'tools/gn/generated_file_target_generator.cc',
'tools/gn/group_target_generator.cc',
'tools/gn/header_checker.cc',
'tools/gn/import_manager.cc',
@@ -478,6 +479,7 @@
'tools/gn/ninja_bundle_data_target_writer.cc',
'tools/gn/ninja_copy_target_writer.cc',
'tools/gn/ninja_create_bundle_target_writer.cc',
+ 'tools/gn/ninja_generated_file_target_writer.cc',
'tools/gn/ninja_group_target_writer.cc',
'tools/gn/ninja_target_command_util.cc',
'tools/gn/ninja_target_writer.cc',
@@ -579,6 +581,7 @@
'tools/gn/ninja_bundle_data_target_writer_unittest.cc',
'tools/gn/ninja_copy_target_writer_unittest.cc',
'tools/gn/ninja_create_bundle_target_writer_unittest.cc',
+ 'tools/gn/ninja_generated_file_target_writer_unittest.cc',
'tools/gn/ninja_group_target_writer_unittest.cc',
'tools/gn/ninja_target_writer_unittest.cc',
'tools/gn/ninja_toolchain_writer_unittest.cc',
diff --git a/tools/gn/command_desc.cc b/tools/gn/command_desc.cc
index 9dd38c8..36b14b6 100644
--- a/tools/gn/command_desc.cc
+++ b/tools/gn/command_desc.cc
@@ -287,7 +287,8 @@
{variables::kPrecompiledSource, DefaultHandler},
{variables::kDeps, DepsHandler},
{variables::kLibs, DefaultHandler},
- {variables::kLibDirs, DefaultHandler}};
+ {variables::kLibDirs, DefaultHandler},
+ {variables::kWriteOutputConversion, DefaultHandler}};
}
void HandleProperty(const std::string& what,
@@ -364,6 +365,7 @@
HandleProperty(variables::kDeps, handler_map, v, dict);
HandleProperty(variables::kLibs, handler_map, v, dict);
HandleProperty(variables::kLibDirs, handler_map, v, dict);
+ HandleProperty(variables::kWriteOutputConversion, handler_map, v, dict);
#undef HandleProperty
@@ -468,6 +470,7 @@
lib_dirs
libs
metadata
+ output_conversion
outputs
public_configs
public
diff --git a/tools/gn/desc_builder.cc b/tools/gn/desc_builder.cc
index 209e9f4..a66a419 100644
--- a/tools/gn/desc_builder.cc
+++ b/tools/gn/desc_builder.cc
@@ -51,6 +51,7 @@
// "libs" : [ list of libraries ],
// "lib_dirs" : [ list of library directories ]
// "metadata" : [ dictionary of target metadata values ]
+// "output_conversion" : "string for output conversion"
// }
//
// Optionally, if "what" is specified while generating description, two other
@@ -459,6 +460,14 @@
FillInPrecompiledHeader(res.get(), target_->config_values());
}
+ // GeneratedFile vars.
+ if (target_->output_type() == Target::GENERATED_FILE) {
+ if (what(variables::kWriteOutputConversion)) {
+ res->SetKey(variables::kWriteOutputConversion,
+ std::move(ToBaseValue(target_->output_conversion())));
+ }
+ }
+
if (what(variables::kDeps))
res->SetWithoutPathExpansion(variables::kDeps, RenderDeps());
@@ -656,7 +665,8 @@
list->AppendString(elem.AsString());
res->SetWithoutPathExpansion(variables::kOutputs, std::move(list));
- } else if (target_->output_type() == Target::CREATE_BUNDLE) {
+ } else if (target_->output_type() == Target::CREATE_BUNDLE ||
+ target_->output_type() == Target::GENERATED_FILE) {
std::vector<SourceFile> output_files;
target_->bundle_data().GetOutputsAsSourceFiles(target_->settings(),
&output_files);
diff --git a/tools/gn/functions.cc b/tools/gn/functions.cc
index 6abe758..d43dc59 100644
--- a/tools/gn/functions.cc
+++ b/tools/gn/functions.cc
@@ -1251,6 +1251,7 @@
INSERT_FUNCTION(SourceSet, true)
INSERT_FUNCTION(StaticLibrary, true)
INSERT_FUNCTION(Target, true)
+ INSERT_FUNCTION(GeneratedFile, true)
INSERT_FUNCTION(Assert, false)
INSERT_FUNCTION(Config, false)
diff --git a/tools/gn/functions.h b/tools/gn/functions.h
index 5c707c4..97f5b0d 100644
--- a/tools/gn/functions.h
+++ b/tools/gn/functions.h
@@ -195,6 +195,15 @@
const std::vector<Value>& args,
Err* err);
+extern const char kGeneratedFile[];
+extern const char kGeneratedFile_HelpShort[];
+extern const char kGeneratedFile_Help[];
+Value RunGeneratedFile(Scope* scope,
+ const FunctionCallNode* function,
+ const std::vector<Value>& args,
+ BlockNode* block,
+ Err* err);
+
extern const char kGroup[];
extern const char kGroup_HelpShort[];
extern const char kGroup_Help[];
diff --git a/tools/gn/functions_target.cc b/tools/gn/functions_target.cc
index 008b47e..282b793 100644
--- a/tools/gn/functions_target.cc
+++ b/tools/gn/functions_target.cc
@@ -772,4 +772,44 @@
block, err);
}
+const char kGeneratedFile[] = "generated_file";
+const char kGeneratedFile_HelpShort[] =
+ "generated_file: Declare a generated_file target.";
+const char kGeneratedFile_Help[] =
+ R"(generated_file: Declare a generated_file target.
+
+ Writes data value(s) to disk on resolution. This target type mirrors some
+ functionality of the write_file() function, but also provides the ability to
+ collect metadata from its dependencies on resolution rather than writing out
+ parse time.
+
+ The `outputs` variable is required to be a list with a single element,
+ specifying the intended location of the output file.
+
+ The `output_conversion` variable specified the format to write the
+ value. See `gn help output_conversion`.
+
+ One of `data` or `data_keys` must be specified; use of `data` will write the
+ contents of that value to file, while use of `data_keys` will trigger a
+ metadata collection walk based on the dependencies of the target and the
+ optional values of the `rebase` and `walk_keys` variables. See
+ `gn help metadata`.
+
+Variables
+
+ data_keys
+ rebase
+ walk_keys
+ output_conversion
+)" DEPS_VARS DEPENDENT_CONFIG_VARS;
+
+Value RunGeneratedFile(Scope* scope,
+ const FunctionCallNode* function,
+ const std::vector<Value>& args,
+ BlockNode* block,
+ Err* err) {
+ return ExecuteGenericTarget(functions::kGeneratedFile, scope, function, args,
+ block, err);
+}
+
} // namespace functions
diff --git a/tools/gn/generated_file_target_generator.cc b/tools/gn/generated_file_target_generator.cc
new file mode 100644
index 0000000..96a9f37
--- /dev/null
+++ b/tools/gn/generated_file_target_generator.cc
@@ -0,0 +1,69 @@
+// 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/generated_file_target_generator.h"
+
+#include "tools/gn/err.h"
+#include "tools/gn/filesystem_utils.h"
+#include "tools/gn/parse_tree.h"
+#include "tools/gn/scope.h"
+#include "tools/gn/target.h"
+#include "tools/gn/variables.h"
+
+GeneratedFileTargetGenerator::GeneratedFileTargetGenerator(
+ Target* target,
+ Scope* scope,
+ const FunctionCallNode* function_call,
+ Target::OutputType type,
+ Err* err)
+ : TargetGenerator(target, scope, function_call, err), output_type_(type) {}
+
+GeneratedFileTargetGenerator::~GeneratedFileTargetGenerator() = default;
+
+void GeneratedFileTargetGenerator::DoRun() {
+ target_->set_output_type(output_type_);
+
+ if (!FillOutputs(false))
+ return;
+ if (target_->action_values().outputs().list().size() != 1) {
+ *err_ = Err(
+ function_call_, "generated_file target must have exactly one output.",
+ "You must specify exactly one value in the \"outputs\" array for the "
+ "destination of the write\n(see \"gn help generated_file\").");
+ return;
+ }
+
+ if (!FillContents()) {
+ *err_ = Err(function_call_, "Contents should be set.",
+ "The generated_file target requires the \"contents\" variable "
+ "be set. See \"gn help generated_file\".");
+ return;
+ }
+
+ if (!FillOutputConversion())
+ return;
+}
+
+bool GeneratedFileTargetGenerator::FillContents() {
+ const Value* value = scope_->GetValue(variables::kWriteValueContents, true);
+ if (!value)
+ return false;
+ target_->set_contents(*value);
+ return true;
+}
+
+bool GeneratedFileTargetGenerator::FillOutputConversion() {
+ const Value* value =
+ scope_->GetValue(variables::kWriteOutputConversion, true);
+ if (!value) {
+ target_->set_output_conversion(Value(function_call_, ""));
+ return true;
+ }
+ if (!value->VerifyTypeIs(Value::STRING, err_))
+ return false;
+
+ // Otherwise, the value itself will be checked when the conversion is done.
+ target_->set_output_conversion(*value);
+ return true;
+}
diff --git a/tools/gn/generated_file_target_generator.h b/tools/gn/generated_file_target_generator.h
new file mode 100644
index 0000000..6db9fb1
--- /dev/null
+++ b/tools/gn/generated_file_target_generator.h
@@ -0,0 +1,35 @@
+// 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.
+
+#ifndef TOOLS_GN_GENERATED_FILE_TARGET_GENERATOR_H_
+#define TOOLS_GN_GENERATED_FILE_TARGET_GENERATOR_H_
+
+#include "base/macros.h"
+#include "tools/gn/target.h"
+#include "tools/gn/target_generator.h"
+
+// Collects and writes specified data.
+class GeneratedFileTargetGenerator : public TargetGenerator {
+ public:
+ GeneratedFileTargetGenerator(Target* target,
+ Scope* scope,
+ const FunctionCallNode* function_call,
+ Target::OutputType type,
+ Err* err);
+ ~GeneratedFileTargetGenerator() override;
+
+ protected:
+ void DoRun() override;
+
+ private:
+ bool FillGeneratedFileOutput();
+ bool FillOutputConversion();
+ bool FillContents();
+
+ Target::OutputType output_type_;
+
+ DISALLOW_COPY_AND_ASSIGN(GeneratedFileTargetGenerator);
+};
+
+#endif // TOOLS_GN_GENERATED_FILE_TARGET_GENERATOR_H_
diff --git a/tools/gn/misc/emacs/gn-mode.el b/tools/gn/misc/emacs/gn-mode.el
index 38564c6..872bfd1 100644
--- a/tools/gn/misc/emacs/gn-mode.el
+++ b/tools/gn/misc/emacs/gn-mode.el
@@ -63,7 +63,7 @@
(defvar gn-font-lock-target-declaration-keywords
'("action" "action_foreach" "bundle_data" "copy" "create_bundle" "executable"
"group" "loadable_module" "shared_library" "source_set" "static_library"
- "target"))
+ "generated_file" "target"))
;; pool() is handled specially since it's also a variable name
(defvar gn-font-lock-buildfile-fun-keywords
@@ -92,7 +92,8 @@
"output_prefix_override" "outputs" "pool" "precompiled_header"
"precompiled_header_type" "precompiled_source" "product_type" "public"
"public_configs" "public_deps" "response_file_contents" "script" "sources"
- "testonly" "visibility" "write_runtime_deps" "bundle_contents_dir"))
+ "testonly" "visibility" "write_runtime_deps" "bundle_contents_dir"
+ "contents" "output_conversion"))
(defconst gn-font-lock-keywords
`((,(regexp-opt gn-font-lock-reserved-keywords 'words) .
diff --git a/tools/gn/misc/tm/GN.tmLanguage b/tools/gn/misc/tm/GN.tmLanguage
index 9c244ff..1d48889 100644
--- a/tools/gn/misc/tm/GN.tmLanguage
+++ b/tools/gn/misc/tm/GN.tmLanguage
@@ -65,7 +65,7 @@
<key>comment</key>
<string>targets</string>
<key>match</key>
- <string>\b(?:action|action_foreach|copy|executable|group|loadable_module|shared_library|source_set|static_library)\b</string>
+ <string>\b(?:action|action_foreach|copy|executable|group|loadable_module|shared_library|source_set|static_library|generated_file)\b</string>
<key>name</key>
<string>entity.name.tag.gn</string>
</dict>
@@ -89,7 +89,7 @@
<key>comment</key>
<string>target variables</string>
<key>match</key>
- <string>\b(?:all_dependent_configs|allow_circular_includes_from|args|asmflags|cflags|cflags_c|cflags_cc|cflags_objc|cflags_objcc|check_includes|complete_static_lib|configs|data|data_deps|defines|depfile|deps|include_dirs|inputs|ldflags|lib_dirs|libs|output_extension|output_name|outputs|public|public_configs|public_deps|script|sources|testonly|visibility)\b</string>
+ <string>\b(?:all_dependent_configs|allow_circular_includes_from|args|asmflags|cflags|cflags_c|cflags_cc|cflags_objc|cflags_objcc|check_includes|complete_static_lib|configs|data|data_deps|defines|depfile|deps|include_dirs|inputs|ldflags|lib_dirs|libs|output_extension|output_name|outputs|public|public_configs|public_deps|script|sources|testonly|visibility|contents|output_conversion)\b</string>
<key>name</key>
<string>entity.other.attribute-name.gn</string>
</dict>
diff --git a/tools/gn/misc/vim/syntax/gn.vim b/tools/gn/misc/vim/syntax/gn.vim
index 9dee605..a50f550 100644
--- a/tools/gn/misc/vim/syntax/gn.vim
+++ b/tools/gn/misc/vim/syntax/gn.vim
@@ -27,7 +27,7 @@
" Target declarations
syn keyword gnTarget action action_foreach copy executable group
syn keyword gnTarget shared_library source_set static_library
-syn keyword gnTarget loadable_module
+syn keyword gnTarget loadable_module generated_file
hi def link gnTarget Type
" Buildfile functions
@@ -48,7 +48,7 @@
syn keyword gnVariable include_dirs inputs ldflags lib_dirs libs
syn keyword gnVariable output_extension output_name outputs public
syn keyword gnVariable public_configs public_deps scripte sources testonly
-syn keyword gnVariable visibility
+syn keyword gnVariable visibility contents output_conversion
hi def link gnVariable Keyword
" Strings
diff --git a/tools/gn/ninja_generated_file_target_writer.cc b/tools/gn/ninja_generated_file_target_writer.cc
new file mode 100644
index 0000000..bf57f0c
--- /dev/null
+++ b/tools/gn/ninja_generated_file_target_writer.cc
@@ -0,0 +1,71 @@
+// 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/ninja_generated_file_target_writer.h"
+
+#include "base/strings/string_util.h"
+#include "tools/gn/deps_iterator.h"
+#include "tools/gn/filesystem_utils.h"
+#include "tools/gn/output_conversion.h"
+#include "tools/gn/output_file.h"
+#include "tools/gn/scheduler.h"
+#include "tools/gn/settings.h"
+#include "tools/gn/string_utils.h"
+#include "tools/gn/target.h"
+#include "tools/gn/trace.h"
+
+NinjaGeneratedFileTargetWriter::NinjaGeneratedFileTargetWriter(
+ const Target* target,
+ std::ostream& out)
+ : NinjaTargetWriter(target, out) {}
+
+NinjaGeneratedFileTargetWriter::~NinjaGeneratedFileTargetWriter() = default;
+
+void NinjaGeneratedFileTargetWriter::Run() {
+ // Write the file.
+ GenerateFile();
+
+ // A generated_file target should generate a stamp file with dependencies
+ // on each of the deps and data_deps in the target. The actual collection is
+ // done at gen time, and so ninja doesn't need to know about it.
+ std::vector<OutputFile> output_files;
+ for (const auto& pair : target_->GetDeps(Target::DEPS_LINKED))
+ output_files.push_back(pair.ptr->dependency_output_file());
+
+ std::vector<OutputFile> data_output_files;
+ const LabelTargetVector& data_deps = target_->data_deps();
+ for (const auto& pair : data_deps)
+ data_output_files.push_back(pair.ptr->dependency_output_file());
+
+ WriteStampForTarget(output_files, data_output_files);
+}
+
+void NinjaGeneratedFileTargetWriter::GenerateFile() {
+ std::vector<SourceFile> outputs_as_sources;
+ target_->action_values().GetOutputsAsSourceFiles(target_,
+ &outputs_as_sources);
+ CHECK(outputs_as_sources.size() == 1);
+
+ base::FilePath output =
+ settings_->build_settings()->GetFullPath(outputs_as_sources[0]);
+ ScopedTrace trace(TraceItem::TRACE_FILE_WRITE, outputs_as_sources[0].value());
+
+ // Compute output.
+ Err err;
+ std::ostringstream contents;
+ ConvertValueToOutput(settings_, target_->contents(),
+ target_->output_conversion(), contents, &err);
+
+ if (err.has_error()) {
+ g_scheduler->FailWithError(err);
+ return;
+ }
+
+ WriteFileIfChanged(output, contents.str(), &err);
+
+ if (err.has_error()) {
+ g_scheduler->FailWithError(err);
+ return;
+ }
+}
diff --git a/tools/gn/ninja_generated_file_target_writer.h b/tools/gn/ninja_generated_file_target_writer.h
new file mode 100644
index 0000000..fa2e6c2
--- /dev/null
+++ b/tools/gn/ninja_generated_file_target_writer.h
@@ -0,0 +1,25 @@
+// 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.
+
+#ifndef TOOLS_GN_NINJA_GENERATED_FILE_TARGET_WRITER_H_
+#define TOOLS_GN_NINJA_GENERATED_FILE_TARGET_WRITER_H_
+
+#include "base/macros.h"
+#include "tools/gn/ninja_target_writer.h"
+
+// Writes a .ninja file for a group target type.
+class NinjaGeneratedFileTargetWriter : public NinjaTargetWriter {
+ public:
+ NinjaGeneratedFileTargetWriter(const Target* target, std::ostream& out);
+ ~NinjaGeneratedFileTargetWriter() override;
+
+ void Run() override;
+
+ private:
+ void GenerateFile();
+
+ DISALLOW_COPY_AND_ASSIGN(NinjaGeneratedFileTargetWriter);
+};
+
+#endif // TOOLS_GN_NINJA_GENERATED_FILE_TARGET_WRITER_H_
diff --git a/tools/gn/ninja_generated_file_target_writer_unittest.cc b/tools/gn/ninja_generated_file_target_writer_unittest.cc
new file mode 100644
index 0000000..a01ef7b
--- /dev/null
+++ b/tools/gn/ninja_generated_file_target_writer_unittest.cc
@@ -0,0 +1,60 @@
+// Copyright 2014 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/ninja_generated_file_target_writer.h"
+
+#include "tools/gn/source_file.h"
+#include "tools/gn/target.h"
+#include "tools/gn/test_with_scheduler.h"
+#include "tools/gn/test_with_scope.h"
+#include "util/test/test.h"
+
+using NinjaGeneratedFileTargetWriterTest = TestWithScheduler;
+
+TEST_F(NinjaGeneratedFileTargetWriterTest, Run) {
+ Err err;
+ TestWithScope setup;
+
+ Target target(setup.settings(), Label(SourceDir("//foo/"), "bar"));
+ target.set_output_type(Target::GENERATED_FILE);
+ target.visibility().SetPublic();
+ target.action_values().outputs() =
+ SubstitutionList::MakeForTest("//out/Debug/foo.json");
+ target.set_contents(Value(nullptr, true));
+ target.set_output_conversion(Value(nullptr, "json"));
+
+ Target dep(setup.settings(), Label(SourceDir("//foo/"), "dep"));
+ dep.set_output_type(Target::ACTION);
+ dep.visibility().SetPublic();
+ dep.SetToolchain(setup.toolchain());
+ ASSERT_TRUE(dep.OnResolved(&err));
+
+ Target dep2(setup.settings(), Label(SourceDir("//foo/"), "dep2"));
+ dep2.set_output_type(Target::ACTION);
+ dep2.visibility().SetPublic();
+ dep2.SetToolchain(setup.toolchain());
+ ASSERT_TRUE(dep2.OnResolved(&err));
+
+ Target datadep(setup.settings(), Label(SourceDir("//foo/"), "datadep"));
+ datadep.set_output_type(Target::ACTION);
+ datadep.visibility().SetPublic();
+ datadep.SetToolchain(setup.toolchain());
+ ASSERT_TRUE(datadep.OnResolved(&err));
+
+ target.public_deps().push_back(LabelTargetPair(&dep));
+ target.public_deps().push_back(LabelTargetPair(&dep2));
+ target.data_deps().push_back(LabelTargetPair(&datadep));
+
+ target.SetToolchain(setup.toolchain());
+ ASSERT_TRUE(target.OnResolved(&err)) << err.message();
+
+ std::ostringstream out;
+ NinjaGeneratedFileTargetWriter writer(&target, out);
+ writer.Run();
+
+ const char expected[] =
+ "build obj/foo/bar.stamp: stamp obj/foo/dep.stamp obj/foo/dep2.stamp || "
+ "obj/foo/datadep.stamp\n";
+ EXPECT_EQ(expected, out.str());
+}
diff --git a/tools/gn/ninja_target_writer.cc b/tools/gn/ninja_target_writer.cc
index de87e8f..253436b 100644
--- a/tools/gn/ninja_target_writer.cc
+++ b/tools/gn/ninja_target_writer.cc
@@ -17,6 +17,7 @@
#include "tools/gn/ninja_bundle_data_target_writer.h"
#include "tools/gn/ninja_copy_target_writer.h"
#include "tools/gn/ninja_create_bundle_target_writer.h"
+#include "tools/gn/ninja_generated_file_target_writer.h"
#include "tools/gn/ninja_group_target_writer.h"
#include "tools/gn/ninja_utils.h"
#include "tools/gn/output_file.h"
@@ -83,6 +84,9 @@
} else if (target->output_type() == Target::GROUP) {
NinjaGroupTargetWriter writer(target, rules);
writer.Run();
+ } else if (target->output_type() == Target::GENERATED_FILE) {
+ NinjaGeneratedFileTargetWriter writer(target, rules);
+ writer.Run();
} else if (target->IsBinary()) {
needs_file_write = true;
NinjaBinaryTargetWriter writer(target, rules);
diff --git a/tools/gn/output_conversion.cc b/tools/gn/output_conversion.cc
index 70c21fa..7f62896 100644
--- a/tools/gn/output_conversion.cc
+++ b/tools/gn/output_conversion.cc
@@ -135,6 +135,10 @@
if (output_conversion == "") {
OutputDefault(output, out);
} else if (output_conversion == "list lines") {
+ if (output.type() != Value::LIST) {
+ *err = Err(original_output_conversion, "Not a valid list.");
+ return;
+ }
OutputListLines(output, out);
} else if (output_conversion == "string") {
OutputString(output, out);
diff --git a/tools/gn/target.cc b/tools/gn/target.cc
index bcddf8b..560f6d0 100644
--- a/tools/gn/target.cc
+++ b/tools/gn/target.cc
@@ -318,6 +318,8 @@
return functions::kBundleData;
case CREATE_BUNDLE:
return functions::kCreateBundle;
+ case GENERATED_FILE:
+ return functions::kGeneratedFile;
default:
return "";
}
@@ -631,7 +633,8 @@
case SOURCE_SET:
case COPY_FILES:
case ACTION:
- case ACTION_FOREACH: {
+ case ACTION_FOREACH:
+ case GENERATED_FILE: {
// These don't get linked to and use stamps which should be the first
// entry in the outputs. These stamps are named
// "<target_out_dir>/<targetname>.stamp".
diff --git a/tools/gn/target.h b/tools/gn/target.h
index 474f9c9..91553f6 100644
--- a/tools/gn/target.h
+++ b/tools/gn/target.h
@@ -46,6 +46,7 @@
ACTION_FOREACH,
BUNDLE_DATA,
CREATE_BUNDLE,
+ GENERATED_FILE,
};
enum DepsIterationType {
@@ -149,7 +150,7 @@
const Metadata& metadata() const { return metadata_; }
Metadata& metadata() { return metadata_; }
- // Collect metadata from this target and its dependencies. This is intended to
+ // Get metadata from this target and its dependencies. This is intended to
// be called after the target is resolved.
bool GetMetadata(const std::vector<std::string>& keys_to_extract,
const std::vector<std::string>& keys_to_walk,
@@ -158,6 +159,14 @@
std::set<const Target*>* targets_walked,
Err* err) const;
+ // GeneratedFile-related methods.
+ bool GenerateFile(Err* err) const;
+
+ const Value& contents() const { return contents_; }
+ void set_contents(const Value& value) { contents_ = value; }
+ const Value& output_conversion() const { return output_conversion_; }
+ void set_output_conversion(const Value& value) { output_conversion_ = value; }
+
bool testonly() const { return testonly_; }
void set_testonly(bool value) { testonly_ = value; }
@@ -184,7 +193,7 @@
bool hard_dep() const {
return output_type_ == ACTION || output_type_ == ACTION_FOREACH ||
output_type_ == COPY_FILES || output_type_ == CREATE_BUNDLE ||
- output_type_ == BUNDLE_DATA;
+ output_type_ == BUNDLE_DATA || output_type_ == GENERATED_FILE;
}
// Returns the iterator range which can be used in range-based for loops
@@ -404,6 +413,10 @@
Metadata metadata_;
+ // GenerateFile values.
+ Value output_conversion_;
+ Value contents_; // Value::NONE if metadata collection should occur.
+
DISALLOW_COPY_AND_ASSIGN(Target);
};
diff --git a/tools/gn/target_generator.cc b/tools/gn/target_generator.cc
index c7a9f08..9ad8969 100644
--- a/tools/gn/target_generator.cc
+++ b/tools/gn/target_generator.cc
@@ -19,6 +19,7 @@
#include "tools/gn/err.h"
#include "tools/gn/filesystem_utils.h"
#include "tools/gn/functions.h"
+#include "tools/gn/generated_file_target_generator.h"
#include "tools/gn/group_target_generator.h"
#include "tools/gn/metadata.h"
#include "tools/gn/parse_tree.h"
@@ -139,6 +140,10 @@
BinaryTargetGenerator generator(target.get(), scope, function_call,
Target::STATIC_LIBRARY, err);
generator.Run();
+ } else if (output_type == functions::kGeneratedFile) {
+ GeneratedFileTargetGenerator generator(target.get(), scope, function_call,
+ Target::GENERATED_FILE, err);
+ generator.Run();
} else {
*err = Err(function_call, "Not a known target type",
"I am very confused by the target type \"" + output_type + "\"");
diff --git a/tools/gn/toolchain.cc b/tools/gn/toolchain.cc
index e34acb5..d9aff43 100644
--- a/tools/gn/toolchain.cc
+++ b/tools/gn/toolchain.cc
@@ -180,6 +180,7 @@
const Target* target) {
// The contents of this list might be suprising (i.e. stamp tool for copy
// rules). See the header for why.
+ // TODO(crbug.com/gn/39): Don't emit stamp files for single-output targets.
switch (target->output_type()) {
case Target::GROUP:
return TYPE_STAMP;
@@ -198,6 +199,7 @@
case Target::BUNDLE_DATA:
case Target::CREATE_BUNDLE:
case Target::COPY_FILES:
+ case Target::GENERATED_FILE:
return TYPE_STAMP;
default:
NOTREACHED();
diff --git a/tools/gn/variables.cc b/tools/gn/variables.cc
index 16de86f..931261d 100644
--- a/tools/gn/variables.cc
+++ b/tools/gn/variables.cc
@@ -2009,6 +2009,26 @@
visibility = [ "./*", "//bar/*" ]
)";
+const char kWriteValueContents[] = "contents";
+const char kWriteValueContents_HelpShort[] =
+ "contents: Contents to write to file.";
+const char kWriteValueContents_Help[] =
+ R"(contents: Contents to write to file.
+
+ The contents of the file for a generated_file target.
+ See "gn help generated_file".
+)";
+
+const char kWriteOutputConversion[] = "output_conversion";
+const char kWriteOutputConversion_HelpShort[] =
+ "output_conversion: Data format for generated_file targets.";
+const char kWriteOutputConversion_Help[] =
+ R"("output_conversion: Data format for generated_file targets.
+
+ Controls how the "contents" of a generated_file target is formatted.
+ See "gn help output_conversion".
+)";
+
const char kWriteRuntimeDeps[] = "write_runtime_deps";
const char kWriteRuntimeDeps_HelpShort[] =
"write_runtime_deps: Writes the target's runtime_deps to the given path.";
@@ -2138,6 +2158,8 @@
INSERT_VARIABLE(XcodeTestApplicationName)
INSERT_VARIABLE(Testonly)
INSERT_VARIABLE(Visibility)
+ INSERT_VARIABLE(WriteOutputConversion)
+ INSERT_VARIABLE(WriteValueContents)
INSERT_VARIABLE(WriteRuntimeDeps)
INSERT_VARIABLE(XcodeExtraAttributes)
}
diff --git a/tools/gn/variables.h b/tools/gn/variables.h
index a90cb00..eb0190a 100644
--- a/tools/gn/variables.h
+++ b/tools/gn/variables.h
@@ -303,6 +303,14 @@
extern const char kVisibility_HelpShort[];
extern const char kVisibility_Help[];
+extern const char kWriteValueContents[];
+extern const char kWriteValueContents_HelpShort[];
+extern const char kWriteValueContents_Help[];
+
+extern const char kWriteOutputConversion[];
+extern const char kWriteOutputConversion_HelpShort[];
+extern const char kWriteOutputConversion_Help[];
+
extern const char kWriteRuntimeDeps[];
extern const char kWriteRuntimeDeps_HelpShort[];
extern const char kWriteRuntimeDeps_Help[];