blob: 97bf296bb145f12054451a04f0a9f09e47dd9c71 [file] [log] [blame]
# Copyright 2024 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/assembly/product_assembly_config_file_impl.gni")
import("//build/group_with_inputs.gni")
# Define developer overrides for product assembly
#
# Params (all are optional):
#
# developer_only_options
# [scope] This is a set of flags and settings for product assembly that are
# only available as developer overrides, they are not available to products
# via the 'product_assembly_configuration()' template. It's a scope with
# the following fields (all optional):
#
# all_packages_in_base (optional; default=false)
# [bool] If set to true, all packages are moved from cache to base, and
# all platform-defined universe packages (such as shell commands) are as
# well.
#
# platform
# [scope] This is a set of values to override / overlay onto the platform
# configuration.
#
# kernel
# [scope] This is a set of flags and settings specifically for the kernel.
# It's a scope with the following fields (all optional):
#
# command_line_args (optional; defauilt = [])
# [list, strings] A list of kernel command-line arguments to add to the
# zbi that's created by assembly.
#
# base_packages [optional]
# [list, GN labels] A list of GN labels of fuchsia_package targets to
# include in the base package set.
#
# Note: These are direct labels for specific targets, not deps to walk for
# metadata. If the target isn't a package target, it will cause an error
# like:
# "no dependency provides the input <package_name>/package_manifest.json"
#
# cache_packages [optional]
# [list, GN labels] A list of GN labels of fuchsia_package targets to
# include in the cache package set.
#
# flexible_packages [optional]
# [list, GN labels] A list of GN labels of fuchsia_package targets that
# assembly may choose to put in base, cache, or elsewhere depending on the
# assembly context.
#
# bootfs_packages [optional]
# [list, GN labels] A list of GN labels of fuchsia_package targets to
# include in the bootfs package set.
#
# Note: These are direct labels for specific targets, not deps to walk for
# metadata. If the target isn't a package target, it will cause an error
# like:
# "no dependency provides the input <package_name>/package_manifest.json"
#
# Note: These are direct labels for specific targets, not deps to walk for
# metadata. If the target isn't a bootfs_files_for_assembly target, it will
# cause an error like:
# "no dependency provides the input <package_name>/bootfs_files.json"
#
# compiled_packages [optional]
# [list of GN scopes] List of GN scopes of `CompiledPackageDefinition`s
# that describe packages that are to be built dynamically by Assembly, for
# example, the `core` package. This is passed directly through to the AIB
# config so all paths should be rebased by the caller.
#
# Example:
#
# # Add a core shard
# compiled_packages = [
# {
# name = "core"
# components = [
# {
# component_name = "core"
# shards = [
# "//src/sys/process-resolver/meta/process_resolver.core_shard.cml",
# ]
# },
# ...
# ],
# contents = [ {
# label = "//some/gn/label"
# source = "//som/gn/file/path"
# destination = "foo/bar"
# } ]
# },
# ]
#
# shards [optional]
# [list of GN file paths] List of CML files to merge together when
# compiling the component.
#
# contents [optional]
# [list of GN scopes] List of GN scopes that describe a source/destination
# pair for a file to include in the package when it's compiled. An
# optional 'label' field is required when the file is created by the
# build, and is the label of the target that creates the file.
#
template("assembly_developer_overrides") {
labels = {
# So it can be reused.
target_name = target_name
assembly_overrides = "${target_name}.product_assembly_overrides.json"
# This is a second target created by the product_assembly_config_file()
# template that wraps up all the input file labels found in the product and
# platform config with the deps that are passed to this template.
assembly_overrides_inputs = "${assembly_overrides}.inputs"
}
files = {
outdir = "$target_out_dir/$target_name"
assembly_config_file = "$outdir/product_assembly_overrides.json"
}
creation_inputs = []
creation_deps = []
# Gather up all the developer-specified packages
_packages = []
foreach(package_set,
[
"base",
"cache",
"flexible",
"bootfs",
]) {
package_set_varname = "${package_set}_packages"
if (defined(invoker[package_set_varname])) {
foreach(package_target, invoker[package_set_varname]) {
_package_out_dir = get_label_info(package_target, "target_out_dir")
_package_name = get_label_info(package_target, "name")
_manifest_path =
"${_package_out_dir}/${_package_name}/package_manifest.json"
_packages += [
{
package = rebase_path(_manifest_path, root_build_dir)
set = package_set
},
]
creation_inputs += [ _manifest_path ]
creation_deps += [ package_target ]
}
}
}
_compiled_packages = []
if (defined(invoker.compiled_packages)) {
foreach(package, invoker.compiled_packages) {
_package = {
}
_package = {
forward_variables_from(package,
"*",
[
"contents",
"components",
"component_includes",
])
}
# Rebase and gather inputs for the contents and component shards
# Gather the deps and inputs files for the package contents.
if (defined(package.contents)) {
_contents = []
foreach(entry, package.contents) {
creation_inputs += [ entry.source ]
creation_deps += [ entry.label ]
_contents += [
{
destination = entry.destination
source = rebase_path("${entry.source}", root_build_dir)
},
]
}
_package.contents = _contents
}
# Gather the core shards as input files
if (defined(package.components)) {
components = []
foreach(entry, package.components) {
creation_inputs += entry.shards
components += [
{
forward_variables_from(entry, "*", [ "shards" ])
shards = rebase_path(entry.shards, root_build_dir)
},
]
}
_package.components = components
}
_compiled_packages += [ _package ]
}
}
_assembly_overrides = {
target_name = get_label_info(":$target_name", "label_no_toolchain")
forward_variables_from(invoker,
[
"developer_only_options",
"platform",
"kernel",
])
packages = _packages
packages_to_compile = _compiled_packages
}
# Generate the overrides configuration file itself.
#
# This uses the product_assembly_config_file() template to properly convert
# any file paths in the 'platform' and 'product' sections that need to be
# converted from GN paths into rebased file paths. See the template's file
# for more information on those paths.
#
product_assembly_config_file(labels.assembly_overrides) {
forward_variables_from(invoker,
[
"deps",
"public_deps",
"testonly",
])
visibility = [ ":${labels.target_name}" ]
outputs = [ files.assembly_config_file ]
product_assembly_config = _assembly_overrides
}
group_with_inputs(labels.target_name) {
forward_variables_from(invoker,
[
"testonly",
"visibility",
])
public_deps = [
":${labels.assembly_overrides_inputs}",
":${labels.assembly_overrides}",
]
inputs = creation_inputs
deps = creation_deps
# Block all metadata walks for packages, distribution entries, etc. These
# inputs should not exist in metadata walks, as they are added via the paths
# in the assembly config itself.
metadata = {
package_barrier = []
assembly_package_barrier = []
config_package_barrier = []
driver_package_barrier = []
system_image_package_barrier = []
distribution_entries_barrier = []
}
}
}
declare_args() {
# This GN arg enables developer overrides for the given assembly targets
#
# This is a list of scopes that take two fields:
# - assembly: (GN label pattern) the GN label(s) to apply the overrides to
# - overrides (GN label) the label of a set of developer overrides
#
# Example:
#
# product_assembly_overrides = [
# {
# assembly = "//build/images/fuchsia/*"
# overrides = "//local:my_assembly_overrides"
# }
# ]
product_assembly_overrides = []
}
foreach(overrides_def, product_assembly_overrides) {
assert(
defined(overrides_def.assembly),
"'product_assembly_overrides' must specify an assembly target to override using 'assembly'")
assert(
defined(overrides_def.overrides),
"'product_assembly_overrides' must specify an overrides target using 'overrides'")
}