blob: 271b1a16a9c00b2659db40386b71ccc59d839ea4 [file] [log] [blame]
# Copyright 2019 The Fuchsia Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
# Generate a manifest file as used by `zbi`, `minfs`, etc.
#
# This produces a manifest file in the `TARGET=SOURCE` format where
# `SOURCE` is a host file path relative to $root_build_dir and `TARGET`
# is a path relative to some filesystem image or directory subtree being
# populated. The manifest is populated from optional fixed entries given
# in $manifest (see below) and from the dependency graph of this target.
#
# resource() targets as well as executable() et al and any targets with
# an `install_path` parameter contribute metadata to populate manifest
# files that depend on those targets. manifest_file() targets and other
# packaging steps act as dependency barriers to the manifest metadata
# collection, so if this target depends (directly or indirectly) on
# another manifest_file(), the dependencies of _that_ manifest_file()
# won't contribute entries to _this_ manifest (unless they are reached
# separately as dependencies of _this_ target by a dependency path not
# passing thruogh _that_ target).
#
# Parameters
#
# data_deps
# Optional: Has no effect on this target, but dependents will depend
# on these targets.
# Type: list(label)
#
# deps
# Optional: Dependencies examined for metadata. Transitive dependencies
# from here defining `metadata.manifest_lines` contribute to the manifest,
# pruned at targets that set `metadata.manifest_barrier`. Likewise,
# `metadata.manifest_files` contributes manifests (like $sources).
# Each manifest_file() target itself contributes that way, so another
# manifest_file() in the deps will be folded into this one.
# Type: list(label)
#
# output_dir
# Optional: Directory where the manifest file is written.
# Type: dir
# Default: target_gen_dir
#
# output_extension
# Optional: Extension added to $output_name.
# Type: string
# Default: "manifest"
#
# output_name
# Optional: Name of the manifest file written out.
# Type: string
# Default: target_name
#
# manifest
# Optional: Fixed entries for the manifest file. These augment the
# entries collected from `manifest_lines` metadata. Each entry is
# either a string that's a literal manifest entry line, or a scope
# with $sources and $outputs like a resource() target.
# Type: list(string or scope)
#
# sources
# Optional: Additional manifest files to be concatenated onto this one.
# Type: list(file)
#
template("manifest_file") {
forward_variables_from(invoker,
[
"output_dir",
"output_extension",
"output_name",
])
if (!defined(output_dir)) {
output_dir = target_gen_dir
}
if (!defined(output_extension)) {
output_extension = "manifest"
}
if (!defined(output_name)) {
output_name = target_name
}
manifest_file = "$output_dir/$output_name"
if (output_extension != "") {
manifest_file += ".$output_extension"
}
manifest_target = target_name
list_file = "$target_gen_dir/$target_name.list"
raw_file = "$target_gen_dir/$target_name.raw.manifest"
list_file_target = "_manifest_file.$target_name.list"
raw_file_target = "_manifest_file.$target_name.raw"
# An embedded manifest contributes to metadata.manifest_lines directly.
manifest_entries = []
manifest_inputs = []
if (defined(invoker.manifest)) {
foreach(entry, invoker.manifest) {
if (entry == "$entry") {
# It's a literal manifest entry string.
# Note this doesn't express any dependency on its source file!
manifest_entries += [ entry ]
} else {
# It's a manifest entry in the style of a copy() target.
foreach(source, entry.sources) {
manifest_inputs += [ source ]
source_path = rebase_path(source, root_build_dir)
foreach(target, process_file_template([ source ], entry.outputs)) {
manifest_entries += [ "${target}=${source_path}" ]
}
}
}
}
}
# This target produces the raw manifest file from metadata and fixed entries.
generated_file(raw_file_target) {
visibility = [ ":$list_file_target" ]
forward_variables_from(invoker,
[
"deps",
"testonly",
])
outputs = [
raw_file,
]
output_conversion = "list lines"
data_keys = [ "manifest_lines" ]
walk_keys = [ "manifest_barrier" ]
metadata = {
# This will be picked up by raw_file_target, below.
manifest_files = rebase_path(outputs, root_build_dir)
if (defined(invoker.sources)) {
manifest_files += rebase_path(invoker.sources, root_build_dir)
}
# This will be picked up by this target's own collection.
manifest_lines = manifest_entries
}
}
# This target produces the list of manifest files to combine.
# It always includes the raw file just produced and $sources,
# but can also pick up more files from metadata.
generated_file(list_file_target) {
visibility = [ ":$manifest_target" ]
forward_variables_from(invoker, [ "testonly" ])
outputs = [
list_file,
]
output_conversion = "list lines"
data_keys = [ "manifest_files" ]
walk_keys = [ "manifest_barrier" ]
deps = [
":$raw_file_target",
]
}
# This target produces the final manifest by combining all those files.
# The metadata from the invoker and for other manifest_file() targets
# goes here. It shouldn't be seen by the generated_file() targets above.
action(manifest_target) {
forward_variables_from(invoker,
[
"data_deps",
"testonly",
"visibility",
])
script = "$zx/public/gn/manifest-cat.sh"
sources = [
list_file,
]
outputs = [
manifest_file,
]
deps = [
":$list_file_target",
]
inputs = manifest_inputs
if (defined(invoker.sources)) {
# These are listed in $list_file and will appear in the depfile.
# Make sure they're built before the first run if necessary and let
# GN enforce that they come from the deps. This is the only reason
# to include deps and not just data_deps in this action() target.
# The deps are reached by $raw_file_target already.
inputs += invoker.sources
if (defined(invoker.deps)) {
deps += invoker.deps
}
}
depfile = "$manifest_file.d"
args = rebase_path(sources + outputs + [ depfile ], root_build_dir)
metadata = {
images = []
manifest_barrier = []
manifest_files = []
if (defined(invoker.metadata)) {
# This lets the invoker add to `images` and `manifest_barrier`,
# though our implicit contributions will always be there too.
forward_variables_from(invoker.metadata, "*")
}
# For the //:images build_api_module().
images += [
{
label = get_label_info(":$target_name", "label_with_toolchain")
name = output_name
path = rebase_path(manifest_file, root_build_dir)
type = "manifest"
cpu = current_cpu
os = current_os
},
]
# Another manifest_file() depending on this one will fold it in,
# just as this one folded in any `manifest_files` from its deps.
# The `manifest_barrier` set here (above) prevents any dependents
# from reaching dependencies we've already folded in.
manifest_files += [ rebase_path(manifest_file, root_build_dir) ]
}
}
}