[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[];