blob: 7f9f39994c44811c4bf39a8692542daaa9efbd09 [file] [log] [blame]
# Copyright 2022 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.
import("//build/group_with_inputs.gni")
# Create a product assembly config file from the lists of packages and config
# passed into the template.
#
# This template specifically converts lists of labels for fuchsia_package() and
# prebuilt_package() into the lists of output paths needed. This keeps the
# contract about where those two templates place the package manifest internal
# to fuchsia.git.
#
# As outputs, this creates:
#
# outputs = [
# "${target_out_dir}/${target_name}/product_assembly_config.json"
# ]
#
#
# Arguments:
#
# Product-specified Package Sets:
# These are optional lists of targets that produce Fuchsia Packages. These
# are NOT walked for metadata, but must be the exact desired package-creating
# targets.
#
# base_packages [optional]
# [list, GN targets] A list of GN targets that are the specific targets for
# the product-provided packages to place into the base set.
#
# cache_packages [optional]
# [list, GN targets] A list of GN targets that are the specific targets for
# the product-provided packages to place into the cache set.
#
# platform [optional]
# [scope] This is the platform configuration scope
#
# product [optional]
# [scope] This is the product configuration scope
#
# GN Usual:
# testonly
# visibility
template("product_assembly_configuration") {
labels = {
# So it can be reused.
target_name = target_name
assembly_config = "${target_name}.product_assembly_config.json"
# This is a publicly visible, test-only target, that allows the assembly
# config to be used without needing the deps used create it.
assembly_config_for_validation =
"${target_name}.product_assembly_config.json.for_validation"
base_package_set = "${target_name}.base_packages"
cache_package_set = "${target_name}.cache_packages"
# Base packages specified by the invoker, used to create the list of
# manifests and as the deps for the package set targets.
base_package_labels = []
if (defined(invoker.base_packages)) {
base_package_labels += invoker.base_packages
}
# Cache packages specified by the invoker, used to create the list of
# manifests and as the deps for the package set targets.
cache_package_labels = []
if (defined(invoker.cache_packages)) {
cache_package_labels += invoker.cache_packages
}
}
files = {
outdir = "$target_out_dir/$target_name"
assembly_config_file = "$outdir/product_assembly_config.json"
# Compute the paths for the package manifests (as files). This is
# closely coupled with how fuchsia_package() and prebuilt_package() both
# create a package manifest from their label.
base_package_manifests = []
foreach(package_target, labels.base_package_labels) {
_package_out_dir = get_label_info(package_target, "target_out_dir")
_package_name = get_label_info(package_target, "name")
base_package_manifests +=
[ "${_package_out_dir}/${_package_name}/package_manifest.json" ]
}
cache_package_manifests = []
foreach(package_target, labels.cache_package_labels) {
_package_out_dir = get_label_info(package_target, "target_out_dir")
_package_name = get_label_info(package_target, "name")
cache_package_manifests +=
[ "${_package_out_dir}/${_package_name}/package_manifest.json" ]
}
}
_assembly_config = {
# Create the platform configuration section from the caller's argument
platform = {
if (defined(invoker.platform)) {
forward_variables_from(invoker.platform, "*")
}
assert(defined(build_type), "The platform build-type must be specified.")
}
# Create the product configuration section from the caller's arguments.
product = {
if (defined(invoker.product)) {
forward_variables_from(invoker.product, "*")
}
# Create the packages.base and package.cache sets if they weren't passed
# in from the invoker.
if (!defined(packages)) {
packages = {
}
}
if (!defined(packages.base)) {
packages.base = []
}
if (!defined(packages.cache)) {
packages.cache = []
}
packages.base += rebase_path(files.base_package_manifests, root_build_dir)
packages.cache +=
rebase_path(files.cache_package_manifests, root_build_dir)
}
}
# Generate the Product Assembly configuration file itself.
#
# This does _not_ have deps on any of the passed in targets, which is why it
# restricts it's visibility to the target that does dep on them.
#
generated_file(labels.assembly_config) {
forward_variables_from(invoker, [ "testonly" ])
visibility = [
":${labels.assembly_config_for_validation}",
":${labels.target_name}",
]
outputs = [ files.assembly_config_file ]
output_conversion = "json"
contents = _assembly_config
}
# These are used to detect if the deps don't correspond to a set of input
# files (the deps can be larger than the set of files, but not the other way
# around). Since we're computing the manifest paths from the labels, if the
# label to something other than a package is added, we'll compute a manifest
# path that doesn't exist. This catches it here, instead of inside a build
# action which can't explain why it can't find a file.
# Create a target for the base packages, so they appear in the dep graph
# as distinct from the cache packages, and validate that they produce all of
# the manifests whose paths were computed from the labels.
group_with_inputs(labels.base_package_set) {
inputs = files.base_package_manifests
deps = labels.base_package_labels
}
# Create a target for the cache packages, so they appear in the dep graph
# as distinct from the cache packages, and validate that they produce all of
# the manifests whose paths were computed from the labels.
group_with_inputs(labels.cache_package_set) {
inputs = files.cache_package_manifests
deps = labels.cache_package_labels
}
group(labels.target_name) {
forward_variables_from(invoker,
[
"deps",
"public_deps",
"testonly",
"visibility",
])
if (!defined(public_deps)) {
public_deps = []
}
public_deps += [ ":${labels.assembly_config}" ]
if (!defined(deps)) {
deps = []
}
deps += [
":${labels.base_package_set}",
":${labels.cache_package_set}",
]
}
# A testonly group with no visibilty restrictions, that allows the use of the
# generated product assembly config file in validation actions that don't
# require the existence of the packages and binaries that it points to.
group(labels.assembly_config_for_validation) {
testonly = true
public_deps = [ ":${labels.assembly_config}" ]
}
}