[metadata] Adding metadata variable to target This adds the `metadata` variable to targets. Change-Id: Iddb8adada4323f6e44011bc315fa20674dcbcaff Reviewed-on: https://gn-review.googlesource.com/c/3300 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 56a6566..e32a609 100755 --- a/build/gen.py +++ b/build/gen.py
@@ -568,6 +568,7 @@ 'tools/gn/label_pattern_unittest.cc', 'tools/gn/label_unittest.cc', 'tools/gn/loader_unittest.cc', + 'tools/gn/metadata_unittest.cc', 'tools/gn/ninja_action_target_writer_unittest.cc', 'tools/gn/ninja_binary_target_writer_unittest.cc', 'tools/gn/ninja_build_writer_unittest.cc',
diff --git a/tools/gn/functions_target.cc b/tools/gn/functions_target.cc index 2339e17..008b47e 100644 --- a/tools/gn/functions_target.cc +++ b/tools/gn/functions_target.cc
@@ -16,9 +16,10 @@ #define DEPENDENT_CONFIG_VARS \ " Dependent configs: all_dependent_configs, public_configs\n" #define DEPS_VARS " Deps: data_deps, deps, public_deps\n" -#define GENERAL_TARGET_VARS \ - " General: check_includes, configs, data, friend, inputs, output_name,\n" \ - " output_extension, public, sources, testonly, visibility\n" +#define GENERAL_TARGET_VARS \ + " General: check_includes, configs, data, friend, inputs, metadata,\n" \ + " output_name, output_extension, public, sources, testonly,\n" \ + " visibility\n" namespace functions { @@ -138,7 +139,7 @@ R"( Variables - args, data, data_deps, depfile, deps, inputs, outputs*, pool, + args, data, data_deps, depfile, deps, inputs, metadata, outputs*, pool, response_file_contents, script*, sources * = required @@ -208,7 +209,7 @@ R"( Variables - args, data, data_deps, depfile, deps, inputs, outputs*, pool, + args, data, data_deps, depfile, deps, inputs, metadata, outputs*, pool, response_file_contents, script*, sources* * = required @@ -272,7 +273,7 @@ Variables - sources*, outputs*, deps, data_deps, public_deps, visibility + sources*, outputs*, deps, data_deps, metadata, public_deps, visibility * = required Examples @@ -361,7 +362,8 @@ bundle_executable_dir*, bundle_plugins_dir*, bundle_deps_filter, deps, data_deps, public_deps, visibility, product_type, code_signing_args, code_signing_script, code_signing_sources, code_signing_outputs, - xcode_extra_attributes, xcode_test_application_name, partial_info_plist + xcode_extra_attributes, xcode_test_application_name, partial_info_plist, + metadata * = required Example
diff --git a/tools/gn/metadata.h b/tools/gn/metadata.h new file mode 100644 index 0000000..fe66ff6 --- /dev/null +++ b/tools/gn/metadata.h
@@ -0,0 +1,55 @@ +// 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_METADATA_H_ +#define TOOLS_GN_METADATA_H_ + +#include <memory> + +#include "tools/gn/scope.h" +#include "tools/gn/source_dir.h" + +// Metadata about a particular target. +// +// Metadata is a collection of keys and values relating to a particular target. +// Generally, these keys will include three categories of strings: ordinary +// strings, filenames intended to be rebased according to their particular +// source directory, and target labels intended to be used as barriers to the +// walk. Verfication of these categories occurs at walk time, not creation +// time (since it is not clear until the walk which values are intended for +// which purpose). +// +// Represented as a scope in the expression language, here it is reduced to just +// the KeyValueMap (since it doesn't need the logical overhead of a full scope). +// Values must be lists of strings, as the walking collection logic contatenates +// their values across targets. +class Metadata { + public: + using Contents = Scope::KeyValueMap; + + // Members must be set explicitly. + Metadata() = default; + + const ParseNode* origin() const { return origin_; } + void set_origin(const ParseNode* origin) { origin_ = origin; } + + // The contents of this metadata varaiable. + const Contents& contents() const { return contents_; } + Contents& contents() { return contents_; } + void set_contents(Contents&& contents) { contents_.swap(contents); } + + // The relative source directory to use when rebasing. + const SourceDir& source_dir() const { return source_dir_; } + SourceDir& source_dir() { return source_dir_; } + void set_source_dir(const SourceDir& d) { source_dir_ = d; } + + private: + const ParseNode* origin_; + Contents contents_; + SourceDir source_dir_; + + DISALLOW_COPY_AND_ASSIGN(Metadata); +}; + +#endif // TOOLS_GN_METADATA_H_
diff --git a/tools/gn/metadata_unittest.cc b/tools/gn/metadata_unittest.cc new file mode 100644 index 0000000..cb94911 --- /dev/null +++ b/tools/gn/metadata_unittest.cc
@@ -0,0 +1,32 @@ +// 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/metadata.h" +#include "tools/gn/test_with_scope.h" +#include "util/test/test.h" + +TEST(MetadataTest, SetContents) { + Metadata metadata; + + ASSERT_TRUE(metadata.contents().empty()); + + Value a_expected(nullptr, Value::LIST); + a_expected.list_value().push_back(Value(nullptr, "foo")); + Value b_expected(nullptr, Value::LIST); + b_expected.list_value().push_back(Value(nullptr, true)); + + Metadata::Contents contents; + contents.insert(std::pair<base::StringPiece, Value>("a", a_expected)); + contents.insert(std::pair<base::StringPiece, Value>("b", b_expected)); + + metadata.set_contents(std::move(contents)); + + ASSERT_EQ(metadata.contents().size(), 2); + auto a_actual = metadata.contents().find("a"); + auto b_actual = metadata.contents().find("b"); + ASSERT_FALSE(a_actual == metadata.contents().end()); + ASSERT_FALSE(b_actual == metadata.contents().end()); + ASSERT_EQ(a_actual->second, a_expected); + ASSERT_EQ(b_actual->second, b_expected); +}
diff --git a/tools/gn/target.h b/tools/gn/target.h index 8754b61..5421cca 100644 --- a/tools/gn/target.h +++ b/tools/gn/target.h
@@ -20,6 +20,7 @@ #include "tools/gn/label_pattern.h" #include "tools/gn/label_ptr.h" #include "tools/gn/lib_file.h" +#include "tools/gn/metadata.h" #include "tools/gn/ordered_set.h" #include "tools/gn/output_file.h" #include "tools/gn/source_file.h" @@ -144,6 +145,10 @@ complete_static_lib_ = complete; } + // Metadata. Target takes ownership of the resulting scope. + const Metadata& metadata() const { return metadata_; } + Metadata& metadata() { return metadata_; } + bool testonly() const { return testonly_; } void set_testonly(bool value) { testonly_ = value; } @@ -388,6 +393,8 @@ OutputFile dependency_output_file_; std::vector<OutputFile> runtime_outputs_; + Metadata metadata_; + DISALLOW_COPY_AND_ASSIGN(Target); };
diff --git a/tools/gn/target_generator.cc b/tools/gn/target_generator.cc index 4bc693c..c7a9f08 100644 --- a/tools/gn/target_generator.cc +++ b/tools/gn/target_generator.cc
@@ -20,6 +20,7 @@ #include "tools/gn/filesystem_utils.h" #include "tools/gn/functions.h" #include "tools/gn/group_target_generator.h" +#include "tools/gn/metadata.h" #include "tools/gn/parse_tree.h" #include "tools/gn/scheduler.h" #include "tools/gn/scope.h" @@ -50,6 +51,9 @@ if (!FillDependencies()) return; + if (!FillMetadata()) + return; + if (!FillTestonly()) return; @@ -254,6 +258,36 @@ return true; } +bool TargetGenerator::FillMetadata() { + // Need to get a mutable value to mark all values in the scope as used. This + // cannot be done on a const Scope. + Value* value = scope_->GetMutableValue(variables::kMetadata, + Scope::SEARCH_CURRENT, true); + + if (!value) + return true; + + if (!value->VerifyTypeIs(Value::SCOPE, err_)) + return false; + + Scope* scope_value = value->scope_value(); + + scope_value->GetCurrentScopeValues(&target_->metadata().contents()); + scope_value->MarkAllUsed(); + + // Metadata values should always hold lists of Values, such that they can be + // collected and concatenated. Any additional specific type verification is + // done at walk time. + for (const auto& iter : target_->metadata().contents()) { + if (!iter.second.VerifyTypeIs(Value::LIST, err_)) + return false; + } + + target_->metadata().set_source_dir(scope_->GetSourceDir()); + target_->metadata().set_origin(value->origin()); + return true; +} + bool TargetGenerator::FillTestonly() { const Value* value = scope_->GetValue(variables::kTestonly, true); if (value) {
diff --git a/tools/gn/target_generator.h b/tools/gn/target_generator.h index 549f2cd..627505d 100644 --- a/tools/gn/target_generator.h +++ b/tools/gn/target_generator.h
@@ -68,6 +68,7 @@ bool FillDependentConfigs(); // Includes all types of dependent configs. bool FillData(); bool FillDependencies(); // Includes data dependencies. + bool FillMetadata(); bool FillTestonly(); bool FillAssertNoDeps(); bool FillWriteRuntimeDeps();
diff --git a/tools/gn/variables.cc b/tools/gn/variables.cc index a405d9d..16de86f 100644 --- a/tools/gn/variables.cc +++ b/tools/gn/variables.cc
@@ -1337,6 +1337,31 @@ libs = [ "ld" ] )"; +const char kMetadata[] = "metadata"; +const char kMetadata_HelpShort[] = "metadata: [scope] Metadata of this target."; +const char kMetadata_Help[] = + R"(metadata: Metadata of this target. + + Metadata is a collection of keys and values relating to a particular target. + Generally, these keys will include three categories of strings: ordinary + strings, filenames intended to be rebased according to their particular + source directory, and target labels intended to be used as barriers to the + walk. Verfication of these categories occurs at walk time, not creation + time (since it is not clear until the walk which values are intended for + which purpose). + + Example + + group("doom_melon") { + metadata = { + # These keys are not built in to GN but are interpreted when consuming + # metadata. + my_barrier = [] + my_files = [ "a.txt", "b.txt" ] + } + } +)"; + const char kOutputExtension[] = "output_extension"; const char kOutputExtension_HelpShort[] = "output_extension: [string] Value to use for the output's file extension."; @@ -2092,6 +2117,7 @@ INSERT_VARIABLE(Ldflags) INSERT_VARIABLE(Libs) INSERT_VARIABLE(LibDirs) + INSERT_VARIABLE(Metadata) INSERT_VARIABLE(OutputDir) INSERT_VARIABLE(OutputExtension) INSERT_VARIABLE(OutputName)
diff --git a/tools/gn/variables.h b/tools/gn/variables.h index 080989b..a90cb00 100644 --- a/tools/gn/variables.h +++ b/tools/gn/variables.h
@@ -219,6 +219,10 @@ extern const char kLibs_HelpShort[]; extern const char kLibs_Help[]; +extern const char kMetadata[]; +extern const char kMetadata_HelpShort[]; +extern const char kMetadata_Help[]; + extern const char kOutputDir[]; extern const char kOutputDir_HelpShort[]; extern const char kOutputDir_Help[];