blob: c92b27c7b8a38edf136b5610b41554e473b68e97 [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.
import("//build/assembly/compare_json_list.gni")
import("//build/assembly/generated_image_assembly_config.gni")
import("//build/assembly/generated_images_config.gni")
import("//build/assembly/generated_images_config_old.gni")
import("//build/assembly/hermetic_inputs_for_image_assembly.gni")
import("//build/assembly/legacy_assembly_input_bundle.gni")
import("//build/bazel/assembly/bazel_assembly_images_config_inputs.gni")
import("//build/bazel/bazel_inputs.gni")
import("//bundles/assembly/platform_aibs.gni")
import("//build/drivers/driver_manifest.gni")
import("//build/images/filesystem_limits.gni")
import("//build/images/fvm.gni")
import("//build/info/info.gni")
import("//build/packages/package_metadata.gni")
import("//build/testing/verify_files_match.gni")
import("//build/zbi/zbi.gni")
import("//build/zircon/tools.gni")
import("//src/developer/ffx/build/ffx_action.gni")
import("//src/storage/fshost/fshost.gni")
import("//src/storage/fshost/generated_fshost_config.gni")
# Assembles a Fuchsia system.
#
# Given base, cache, and universe packages, assembles a Fuchsia system
# containing those packages.
#
# Parameters:
#
# image_name (optional; default: target_name)
# [string] The filename to give the ZBIs and VBMetas.
#
# namespace (optional; default: image_name)
# [string] A namespace to use for naming all the outputs and generated files.
#
# output_dir (optional; default: target_out_dir)
# [string] The output directory into which the final system ZBI is written.
#
# output_name (optional; default: <target_name>.zbi)
# [string] The name of the final system ZBI file.
#
# generate_image_metadata (optional, default=true)
# [boolean] if true, assembled_system() will generate the appropiate image
# metadata for the assembly output. This metadata will make the image
# discoverable by users of the "images" build api module, as long as
# the image is part of the dependency graph defined by the //:images.
#
# image_metadata_overrides (optional)
# [scope] Per-image overrides for the associated image metadata. Used for
# compliance among customers that depend on legacy fields as they were
# previously (quasi-)standardized. Any override that is supplied for an
# image not assembled is ignored. The scope contains the following:
#
# [scope] zbi, zbi_signed, vbmeta, minfs, blobfs, fvm, fvm_sparse,
# fvm_blob_sparse, fvm_fastboot (optional)
# An arbitrary scope of additional metadata to record for the
# associated image.
#
# metadata (optional)
# [scope] Usual GN meaning, passed to the image assembly target created by
# the template.
#
# testonly (optional)
# [bool] Usual GN meanings.
#
# Product parameters:
# assembly_images_config_label (optional)
# [label] A label for the above images config file. If not specified, global
# args will be used to generate an images config.
#
# product_assembly_config_label (required)
# [label] A label for the product assembly config, should be a
# `product_assembly_configuration` target.
#
# allow_userdebug_platform_bundle_use (optional; default=false)
# [boolean] If true, allow the 'userdebug' platform bundles to be used by
# the assembled system. (this is only a check made by GN, assembly itself
# may still access them)
#
# allow_eng_platform_bundle_use (optional; default=false)
# [boolean] If true, allow the 'eng' platform bundles to be used by the
# assembled system. (this is only a check made by GN, assembly itself may
# still access them)
#
# base_packages (required)
# [list of labels] The packages to include in the base package set.
#
# base_driver_packages (optional)
# [list of labels] The driver packages to include in the base package set.
#
# cache_packages (optional)
# [list of labels] The packages to cache in the images.
#
# universe_packages (optional)
# [list of labels] The packages to build in addition to the base and cache
# sets. These packages do not contribute to the produced images directly,
# however they may contribute to the config-data and shell-commands meta
# packages.
#
# meta_packages (optional)
# [list of labels] The packages to build in addition to the base and cache
# sets, but are base_packages themselves. These are packages that contain
# files that are generated based on other packages in the base, cache,
# and/or universe sets, and therefore cannot be part of those sets directly,
# or a GN dependency cycle will result.
#
# bootfs_labels (required)
# [list of labels] The objects installed on the bootfs partition of the
# generated ZBI.
#
# bootfs_package_labels (optional)
# [list of labels] The packages installed on the bootfs partition of the
# generated ZBI as meta.fars and content-id'd blobs.
#
# system_image_deps (optional)
# [list of labels] The objects installed in the system image.
#
# additional_boot_args (default: [])
# [list of strings] List of arguments to add to /boot/config/additional_boot_args.
# These arguments come after synthesized arguments to configure blobfs.
#
# fshost_config (default: {})
# [scope] Arguments to add to fshost's configuration. These
# arguments come before other arguments set by build args.
#
# use_assembly_fshost (default: false)
# [boolean] Whether to build the fshost component
#
# cmdline (optional)
# [list of strings] Kernel command line text.
#
# cmdline_deps (optional)
# [list of labels] Dependencies with metadata including additional kernel
# command arguments to add to the ZBI.
#
# include_component_id_index (default: false)
# [bool] Collect and merges a component id index from the base
# package set.
#
# include_shell_commands (default: true)
# [bool] Whether to include shell commands. Should be set to false for
# build without shell access.
#
# include_config_data (default: true)
# [bool] Whether to create a config_data package for the assembly or not.
#
# base_package_name (optional; default: "system_image")
# [string] The name to give the base package. For prime builds this
# should be "system_image_prime", so that the package does not override the
# non-prime package during publishing.
#
# kernel_zbi (optional; default: "//zircon/kernel")
# [label] Label of the zircon kernel to use. This needs to use the `images`
# metadata key to provide the `path` and `name` fields (see the
# build_api_module("images")` in `//BUILD.gn`). The default value is most likely
# the correct one. This should only be overridden in special circumstances.
#
# kernel_image_name (optional; default: "kernel")
# [string] The image name of the 'kernel_zbi' as seen in images.json. This is used
# as an override, that in conjunction with 'kernel_zbi' allows selecting a custom zbi
# image as the kernel zbi.
#
# must_exist_deps (optional; default: {})
# [scope of type:labels] A list of deps that we would like to validate are
# included (with their transitive deps) in the Image Assembly Config created
# by assembly
#
# must_exist = {
# base_packages = [...]
# cache_packages = [...]
# bootfs_labels = [...]
# bootfs_package_labels = [...]
# extra_base_deps = [...]
# boot_args = [...]
# cmdline = [...]
# cmdline_deps = [...]
# }
#
# core_realm_definition [optional]
# [label] The GN label of a `core_realm_definition()` template
#
# Board parameters:
#
# assembly_blob_layout_format (default: "compact")
# [string] The format blobfs should store blobs in. The valid values are "deprecated_padded" and
# "compact". The deprecated padded format is supported only for Astro devices and will be
# removed in the future (it wastes space).
#
# check_production_tag (default: false)
# [bool] Whether to check there is no non_production_tag dependencies.
#
# Board: BlobFS parameters
#
# blobfs_minimum_inodes, blobfs_minimum_data_bytes, blobfs_maximum_bytes, blobfs_maximum_contents_size (optional)
# [int] Size options for blobfs to pass to the fvm tool.
#
# Board: FVM/Fxfs parameters
#
# generate_fvm (optional; default: false)
# [bool] Whether to generate a FVM image.
#
# generate_fxfs (optional; default: false)
# [bool] Whether to generate an Fxfs image. Exclusive with generate_fvm. EXPERIMENTAL.
#
# assembly_include_account_in_fvm (optional; default: false)
# [bool] Whether to include an account partition in the FVM image.
#
# ramdisk_fvm_in_zbi (optional)
# DEPRECTATED, use ramdisk_in_zbi.
#
# ramdisk_in_zbi (optional)
# [bool] Whether the FVM or Fxfs image should be embedded into the ZBI as a ramdisk.
#
# assembly_fvm_slice_size (optional; default: 1048576)
# [int] The slice size of the FVM.
#
# fvm_truncate_to_length (optional)
# [int] The precise size to make the (non-sparse) FVM image. See
# documentation of the `--length` parameter of the `fvm` binary host tool
# for details.
#
# assembly_fxfs_reserved_space_bytes (optional; default: 16777216)
# [int] The number of extra bytes reserved in Fxfs.
#
# Board: ZBI arguments
#
# zbi_name (optional; default: target_name)
# [string] The name to give the ZBI in the out directory.
# Typically: fuchsia, recovery, etc.
#
# zbi_signing_script (optional)
# [path] Location of script to use to sign the ZBI.
#
# zbi_signing_args (optional)
# [list of strings] Arguments to pass to the signing script.
#
# zbi_signing_script_deps (optional)
# [list of labels] Dependencies needed by the signing script.
#
template("assembled_system") {
assert(defined(invoker.base_packages), "Need to define base_packages")
assert(defined(invoker.bootfs_labels), "Need to define bootfs_labels")
assert(defined(invoker.product_assembly_config_label),
"Need to define product_assembly_config_label")
generate_fvm = false
if (defined(invoker.generate_fvm)) {
generate_fvm = invoker.generate_fvm
}
generate_fxfs = false
if (defined(invoker.generate_fxfs)) {
generate_fxfs = invoker.generate_fxfs
}
assert(!generate_fvm || !generate_fxfs,
"Only one of Fxfs and FVM can host blobs")
_supports_blobs = generate_fvm || generate_fxfs
if (generate_fvm) {
_has_fastboot_fvm =
fvm_emmc_partition_size != false || fvm_ftl_nand_block_count != false
}
generate_image_metadata = true
if (defined(invoker.generate_image_metadata)) {
generate_image_metadata = invoker.generate_image_metadata
}
forward_variables_from(invoker, [ "image_metadata_overrides" ])
if (defined(image_metadata_overrides)) {
if (!sign_zbi) {
assert(
!defined(image_metadata_overrides.zbi_signed),
"No signed ZBI will be built: no metadata override should be provided")
}
if (!use_vbmeta) {
assert(!defined(image_metadata_overrides.vbmeta),
"No VBMeta will be built: no metadata override should be provided")
}
if (!generate_fvm) {
error_msg =
"No FVMs will be built: no metadata override should be provided"
assert(!defined(image_metadata_overrides.fvm), error_msg)
assert(!defined(image_metadata_overrides.fvm_sparse), error_msg)
assert(!defined(image_metadata_overrides.fvm_blob_sparse), error_msg)
assert(!defined(image_metadata_overrides.fvm_fastboot), error_msg)
not_needed([ "error_msg" ])
}
if (!generate_fxfs) {
assert(
!defined(image_metadata_overrides.fxfs),
"No Fxfs image will be built: no metadata override should be provided")
}
}
if (defined(invoker.must_exist_deps)) {
_must_exist = invoker.must_exist_deps
assert(invoker.must_exist_deps != {
},
"must_exist should provide a scope of deps")
assert(defined(_must_exist.base_packages),
"must_exist scope has required field base_packages")
assert(defined(_must_exist.cache_packages),
"must_exist scope has required field cache_packages")
assert(defined(_must_exist.bootfs_labels),
"must_exist scope has required field bootfs_labels")
assert(defined(_must_exist.bootfs_package_labels),
"must_exist scope has required field bootfs_package_labels")
assert(defined(_must_exist.extra_base_deps),
"must_exist scope has required field extra_base_deps")
assert(defined(_must_exist.boot_args),
"must_exist scope has required field boot_args")
assert(defined(_must_exist.cmdline),
"must_exist scope has required field cmdline")
assert(defined(_must_exist.cmdline_deps),
"must_exist scope has required field cmdline_deps")
}
kernel_zbi = "//zircon/kernel"
if (defined(invoker.kernel_zbi)) {
kernel_zbi = invoker.kernel_zbi
}
kernel_name = "kernel"
if (defined(invoker.kernel_image_name)) {
kernel_name = invoker.kernel_image_name
}
fvm_tool_target = "//src/storage/bin/fvm($host_toolchain)"
fvm_tool_path = get_label_info(fvm_tool_target, "root_out_dir")
fvm_tool_path += "/fvm"
# TODO: This should be removed once all clients are no longer supplying board_name.
not_needed(invoker, [ "board_name" ])
image_name = target_name
if (defined(invoker.image_name)) {
image_name = invoker.image_name
}
namespace = image_name
if (defined(invoker.namespace)) {
namespace = invoker.namespace
}
base_package_name = "system_image"
if (defined(invoker.base_package_name)) {
base_package_name = invoker.base_package_name
}
# Internal labels used for Image Assembly.
labels = {
base_packages_group = "${namespace}.base_packages"
cache_packages_group = "${namespace}.cache_packages"
meta_packages_group = "${namespace}.meta_packages"
all_packages_group = "${namespace}.packages"
legacy_assembly_input_bundle = "${namespace}.legacy_input_bundle"
generated_config_for_legacy_bundle =
"${namespace}.legacy_image_assembly_config"
image_assembly_inputs = "${namespace}.image_assembly_inputs"
images_config_old = "${namespace}.images_config_old"
images_config = "${namespace}.images_config"
images_config_matches = "${namespace}.images_config_matches"
product_assembler = "${namespace}.product_assembler"
image_assembler = "${namespace}.image_assembler"
fshost_validator = "${namespace}.fshost_validator"
copy_vbmeta = "${namespace}.copy_vbmeta"
copy_zbi = "${namespace}.copy_zbi"
copy_zbi_signed = "${namespace}.copy_zbi_signed"
copy_zbi_manifest = "${namespace}.copy_zbi_manifest"
copy_images = "${namespace}.copy_images"
shell_commands = "${namespace}.shell_commands"
assembly_generated_packages = "${namespace}.assembly_generated_packages"
fshost = "${namespace}.fs_host"
compare_command_logs = "${namespace}.compare_command_logs"
compare_images_manifests = "${namespace}.compare_images_manifests"
# *_platform_aib_labels come from //bundles/assembly/platform_aibs.gni
if (defined(invoker.use_bringup_platform_bundles_only) &&
invoker.use_bringup_platform_bundles_only) {
platform_common_aibs = bringup_platform_aib_labels
} else if (defined(invoker.allow_eng_platform_bundle_use) &&
invoker.allow_eng_platform_bundle_use) {
platform_common_aibs = eng_platform_aib_labels
not_needed(invoker, [ "allow_userdebug_platform_bundle_use" ])
} else {
if (defined(invoker.allow_userdebug_platform_bundle_use) &&
invoker.allow_userdebug_platform_bundle_use) {
platform_common_aibs = userdebug_platform_aib_labels
} else {
platform_common_aibs = user_platform_aib_labels
}
}
bazel_images_config_inputs = "${namespace}.bazel_images_config_inputs"
bazel_legacy_aib = "${namespace}.bazel_legacy_aib"
partial_image_assembly_config_for_validations =
"${namespace}.validation_image_assembly_config"
validation_legacy_aib =
"${namespace}.validation_legacy_assembly_input_bundle"
product_assembly_config = invoker.product_assembly_config_label
}
# Intermediate files produced for Image Assembly.
files = {
product_assembly_config =
get_label_info(labels.product_assembly_config, "target_out_dir") + "/" +
get_label_info(labels.product_assembly_config, "name") +
"/product_assembly_config.json"
image_assembly_inputs = "$target_out_dir/${namespace}.image_assembly_inputs"
images_config_old = "$target_out_dir/${namespace}.images_config_old.json"
images_config = "$target_out_dir/${namespace}.images_config.json"
outdir = "$target_out_dir/$namespace"
gendir = "$outdir/gen"
# The cmc_merge() template this is used with prepends $target_out_dir.
fshost_merged_cml = "${namespace}/fshost.merged.cml"
legacy_assembly_input_bundle_dir = "${outdir}/legacy"
legacy_assembly_input_bundle_manifest =
"${legacy_assembly_input_bundle_dir}/assembly_config.json"
# This file is created implicitly by ffx assembly product, so this is the
# path that it's expected to be found at, not the path that it's to be
# written to.
regenerated_image_assembly_config = "${outdir}/image_assembly.json"
bootfs_files = "${gendir}/bootfs_files.list"
additional_boot_args = "${gendir}/additional_boot_args.txt"
zbi = "${outdir}/${image_name}.zbi"
zbi_signed = "${zbi}.signed"
vbmeta = "${outdir}/${image_name}.vbmeta"
if (generate_fvm) {
blobfs = "${outdir}/blob.blk"
fvm = "${outdir}/fvm.blk"
fvm_sparse = "${outdir}/fvm.sparse.blk"
fvm_blob_sparse = "${outdir}/fvm.blob.sparse.blk"
fvm_fastboot_tmp = "${outdir}/fvm.fastboot.tmp.blk"
fvm_fastboot = "${outdir}/fvm.fastboot.blk"
} else if (generate_fxfs) {
fxfs = "${outdir}/fxfs.blk"
}
base_package = "${outdir}/base/meta.far"
base_package_manifest = "${outdir}/base/package_manifest.json"
base_package_merkle = "${outdir}/base/base.merkle"
packages = "${outdir}/packages.json"
zbi_manifest = "${gendir}/zbi.json"
blobfs_manifest = "${gendir}/blob.manifest"
blobs_json = "${gendir}/blobs.json"
bootfs_packages = "${gendir}/data/bootfs_packages"
static_packages = "${gendir}/${base_package_name}/data/static_packages"
cache_packages = "${gendir}/${base_package_name}/data/cache_packages.json"
base_meta_package = "${gendir}/${base_package_name}/meta/package"
base_pkg_abi_revision =
"${gendir}/${base_package_name}/meta/fuchsia.abi/abi-revision"
assembly_manifest = "${outdir}/images.json"
config_data_manifest = "${outdir}/config_data/package_manifest.json"
image_command_log = "${gendir}/command_log.json"
# Determine which ZBI we are shipping.
zbi_final = zbi
if (defined(invoker.zbi_signing_script)) {
zbi_final = zbi_signed
}
# The directory in which all the platform AIBs can be found
platform_common_aibs_dir =
get_label_info("//bundles/assembly", "target_out_dir")
# platform_aib_files and eng_platform_aib_files come from
# //bundles/assembly/platform_aibs.gni.
#
# This isn't strictly required, but it allows the AIB input files to be
# specified in GN.
if (defined(invoker.use_bringup_platform_bundles_only) &&
invoker.use_bringup_platform_bundles_only) {
platform_common_aibs = bringup_platform_aib_files
} else if (defined(invoker.allow_eng_platform_bundle_use) &&
invoker.allow_eng_platform_bundle_use) {
platform_common_aibs = eng_platform_aib_files
} else {
if (defined(invoker.allow_userdebug_platform_bundle_use) &&
invoker.allow_userdebug_platform_bundle_use) {
platform_common_aibs = userdebug_platform_aib_files
} else {
platform_common_aibs = user_platform_aib_files
}
}
}
_base_packages = invoker.base_packages
_base_driver_packages = []
_cache_packages = []
_universe_packages = []
_meta_packages = []
if (defined(invoker.cache_packages)) {
_cache_packages = invoker.cache_packages
}
if (defined(invoker.universe_packages)) {
_universe_packages = invoker.universe_packages
}
if (defined(invoker.meta_packages)) {
_meta_packages = invoker.meta_packages
}
# Split out driver packages into a separate list so that we
# can generate a driver-manager-base-config package.
# We do not generate the package when there is no fvm and drivers
# go directly into bootfs.
if (defined(invoker.base_driver_packages) && _supports_blobs) {
_base_driver_packages = invoker.base_driver_packages
}
system_image_deps = []
if (defined(invoker.system_image_deps) && _supports_blobs) {
system_image_deps += invoker.system_image_deps
} else {
not_needed(invoker, [ "system_image_deps" ])
}
ramdisk_in_zbi = false
if (defined(invoker.ramdisk_fvm_in_zbi)) {
ramdisk_in_zbi = invoker.ramdisk_fvm_in_zbi && _supports_blobs
}
if (defined(invoker.ramdisk_in_zbi)) {
ramdisk_in_zbi =
(invoker.ramdisk_in_zbi && _supports_blobs) || ramdisk_in_zbi
}
additional_boot_args = []
if (defined(invoker.additional_boot_args)) {
additional_boot_args = invoker.additional_boot_args
}
use_assembly_fshost =
defined(invoker.use_assembly_fshost) && invoker.use_assembly_fshost
fshost_config = {
}
if (defined(invoker.fshost_config)) {
fshost_config = invoker.fshost_config
}
# Defaults to true if the invoker doesn't pass "include_shell_commands"
include_shell_commands = _supports_blobs
if (defined(invoker.include_shell_commands)) {
if (invoker.include_shell_commands) {
assert(
_supports_blobs,
"Shell command package generation is only valid if the fvm is being created.")
}
include_shell_commands = invoker.include_shell_commands
}
if (!include_shell_commands) {
not_needed([ "_universe_packages" ])
}
# Compile the fshost component and configuration needed for this assembly
fshost_component_and_config(labels.fshost) {
# THIS CANNOT BE MARKED TESTONLY, EVEN IF THE ASSEMBLY IS. This template
# changes behavior to create a non-bootable fshost if testly is set to true.
testonly = false
# Correct the component name since the target_name is per-image.
component_name = "fshost"
# This is picked up by the `cmc_merge()` within `fshost_cml()`, through its
# use of foward_variables_from(invoker, ["output_name" ...]).
output_name = files.fshost_merged_cml
options = {
# Use the defaults from the build args set in generated_fshost_config.gni
data_filesystem_format = data_filesystem_format
use_disk_migration = use_disk_migration
# Override with anything passed from `fshost_config`
forward_variables_from(fshost_config, "*")
# Always set ramdisk_image if the assmebled ZBI contains a ramdisk.
if (ramdisk_in_zbi) {
ramdisk_image = true
}
fxfs_blob = fxfs_blob
}
}
# Create GN groups for each of the package sets.
group(labels.base_packages_group) {
forward_variables_from(invoker, [ "testonly" ])
public_deps = _base_packages
}
group(labels.cache_packages_group) {
forward_variables_from(invoker, [ "testonly" ])
public_deps = _cache_packages
}
# The group of generated packages that contain files that depend on metadata
# walks of the base/cache/universe package sets and therefore cannot be part
# of those package sets.
group(labels.meta_packages_group) {
forward_variables_from(invoker, [ "testonly" ])
public_deps = _meta_packages
}
#######
# Build the images using the Image Assembler.
#
generated_image_assembly_config(labels.generated_config_for_legacy_bundle) {
forward_variables_from(invoker,
[
"testonly",
"visibility",
"include_component_id_index",
"include_config_data",
])
kernel_image = kernel_zbi
kernel_image_name = kernel_name
base_packages = []
if (_supports_blobs) {
base_packages = _base_packages
base_packages += _meta_packages
cache_packages = _cache_packages
}
config_data_packages = _base_packages + _universe_packages + _cache_packages
boot_args = additional_boot_args
# Search for BootFS packages in these targets.
bootfs_package_labels = []
if (defined(invoker.bootfs_package_labels)) {
bootfs_package_labels += invoker.bootfs_package_labels
}
# Search for BootFS files in these targets.
bootfs_labels = invoker.bootfs_labels
bootfs_labels += [ kernel_image ]
if (!use_assembly_fshost) {
bootfs_labels += [ ":${labels.fshost}" ]
}
# Only builds which support blobs need base-resolver.
if (_supports_blobs) {
bootfs_labels += [ "//src/sys/base-resolver:bootfs" ]
}
extra_base_deps = system_image_deps
# Search for the Kernel cmdline in the BootFS dependencies.
cmdline_deps = invoker.bootfs_labels
if (defined(invoker.cmdline_deps)) {
cmdline_deps += invoker.cmdline_deps
}
if (defined(invoker.cmdline)) {
cmdline = invoker.cmdline
}
}
generated_images_config_old(labels.images_config_old) {
forward_variables_from(invoker,
[
"testonly",
"visibility",
"zbi_signing_script",
"zbi_signing_args",
"blobfs_maximum_bytes",
"blobfs_minimum_data_bytes",
"blobfs_maximum_contents_size",
"blobfs_minimum_inodes",
"fvm_truncate_to_length",
])
output_path = files.images_config_old
zbi_name = "${image_name}"
fvm_reserved_slices = fvm_reserved_slices
generate_fvm = generate_fvm
fvm_slice_size = 1048576
if (defined(invoker.assembly_fvm_slice_size)) {
fvm_slice_size = invoker.assembly_fvm_slice_size
}
blob_layout_format = "compact"
if (defined(invoker.assembly_blob_layout_format)) {
blob_layout_format = invoker.assembly_blob_layout_format
}
}
generated_images_config(labels.images_config) {
forward_variables_from(invoker,
[
"testonly",
"visibility",
])
output_path = files.images_config
zbi = {
name = "${image_name}"
compression = zbi_compression
if (defined(invoker.zbi_signing_script)) {
signing_script = invoker.zbi_signing_script
if (defined(invoker.zbi_signing_args)) {
signing_args = invoker.zbi_signing_args
}
}
}
if (use_vbmeta) {
vbmeta = {
key = avb_key
key_metadata = avb_atx_metadata
if (extra_vbmeta_descriptors != false) {
extra_descriptors = extra_vbmeta_descriptors
}
}
}
if (generate_fvm) {
_slice_size = 1048576
_blob_layout_format = "compact"
if (defined(invoker.assembly_fvm_slice_size)) {
_slice_size = invoker.assembly_fvm_slice_size
}
if (defined(invoker.assembly_blob_layout_format)) {
_blob_layout_format = invoker.assembly_blob_layout_format
}
fvm = {
# Parameters
slice_size = _slice_size
if (defined(invoker.fvm_truncate_to_length)) {
truncate_to_length = invoker.fvm_truncate_to_length
}
if (fvm_max_disk_size != false) {
max_disk_size = fvm_max_disk_size
}
# Filesystems
blobfs = {
layout = _blob_layout_format
if (defined(invoker.blobfs_minimum_inodes)) {
minimum_inodes = invoker.blobfs_minimum_inodes
}
if (defined(invoker.blobfs_minimum_data_bytes)) {
minimum_data_bytes = invoker.blobfs_minimum_data_bytes
}
if (defined(invoker.blobfs_maximum_bytes)) {
maximum_bytes = invoker.blobfs_maximum_bytes
}
if (defined(invoker.blobfs_maximum_contents_size)) {
maximum_contents_size = invoker.blobfs_maximum_contents_size
}
}
reserved = {
slices = fvm_reserved_slices
}
# Optional outputs (emmc and nand)
if (fvm_partition != "") {
if (fvm_emmc_partition_size != false) {
emmc = {
# EMMC fvms are by default compressed.
compress = fvm_fastboot_compression != "none"
truncate_to_length = fvm_emmc_partition_size
}
} else if (fvm_ftl_nand_block_count != false) {
nand = {
if (fvm_max_disk_size != false) {
max_disk_size = fvm_max_disk_size
}
# NAND fvms are by default uncompressed.
compress = fvm_fastboot_compression != "default"
block_count = fvm_ftl_nand_block_count
oob_size = fvm_ftl_nand_oob_size
page_size = fvm_ftl_nand_page_size
pages_per_block = fvm_ftl_nand_pages_per_block
}
} else {
assert(
false,
"|fvm_partition| is specified. But failed to determine the target format.")
}
}
}
}
if (generate_fxfs) {
fxfs = {
if (defined(invoker.assembly_fxfs_reserved_space_bytes)) {
reserved_space_bytes = invoker.assembly_fxfs_reserved_space_bytes
}
}
}
}
if (defined(_must_exist)) {
generated_image_assembly_config(
labels.partial_image_assembly_config_for_validations) {
forward_variables_from(invoker,
[
"testonly",
"visibility",
"include_component_id_index",
])
include_config_data = true
forward_variables_from(_must_exist, [ "base_packages" ])
kernel_image = kernel_zbi
kernel_image_name = kernel_name
config_data_packages = _must_exist.base_packages + _universe_packages +
_must_exist.cache_packages
}
legacy_assembly_input_bundle(labels.validation_legacy_aib) {
forward_variables_from(invoker,
[
"testonly",
"visibility",
])
image_assembly_label =
":${labels.partial_image_assembly_config_for_validations}"
bundle_name = "must_exist"
bundles_dir = files.outdir
include_config_data = true
create_package = false
create_package_archive = false
}
}
if (defined(invoker.assembly_images_config_label)) {
_images_config_file =
get_label_info(invoker.assembly_images_config_label, "target_out_dir") +
"/" + get_label_info(invoker.assembly_images_config_label, "name") +
".json"
verify_files_match(labels.images_config_matches) {
forward_variables_from(invoker,
[
"testonly",
"visibility",
])
deps = [
":${labels.images_config}",
invoker.assembly_images_config_label,
]
first = files.images_config
second = _images_config_file
display_text_diff_on_failure = true
}
}
bazel_assembly_images_config_inputs(labels.bazel_images_config_inputs) {
forward_variables_from(invoker,
[
"testonly",
"visibility",
])
images_config = files.images_config
images_config_target = labels.images_config
}
check_production_tag = false
if (defined(invoker.check_production_tag)) {
check_production_tag = invoker.check_production_tag
}
# Create the legacy assembly input bundle for the above-generated image
# assembly configuration.
legacy_assembly_input_bundle(labels.legacy_assembly_input_bundle) {
forward_variables_from(invoker,
[
"testonly",
"visibility",
])
image_assembly_label = ":${labels.generated_config_for_legacy_bundle}"
bundles_dir = files.outdir
include_config_data = _supports_blobs
create_package = defined(invoker.create_legacy_aib_package) &&
invoker.create_legacy_aib_package
create_package_archive = defined(invoker.create_legacy_aib_archive) &&
invoker.create_legacy_aib_archive
# The core realm is part of the base packages. Do not generate
# the core realm if we are not generating an FVM
if (defined(invoker.core_realm_definition) && _supports_blobs) {
core_realm_definition = invoker.core_realm_definition
} else {
not_needed(invoker, [ "core_realm_definition" ])
}
base_driver_packages = _base_driver_packages
if (include_shell_commands) {
shell_command_packages =
_base_packages + _universe_packages + _cache_packages
}
}
# Run product assembly.
ffx_action(labels.product_assembler) {
forward_variables_from(invoker,
[
"testonly",
"visibility",
])
# This will not be resolved except by moving to Bazel.
hermetic_deps = false
ffx_tool = "//src/developer/ffx/plugins/assembly:ffx_assembly_tool"
ffx_tool_output_name = "ffx-assembly"
args = [
"--config",
"assembly_enabled=true",
"assembly",
"product",
"--product",
rebase_path(files.product_assembly_config, root_build_dir),
"--input-bundles-dir",
rebase_path(files.platform_common_aibs_dir, root_build_dir),
"--legacy-bundle",
rebase_path(files.legacy_assembly_input_bundle_dir, root_build_dir),
"--outdir",
rebase_path(files.outdir, root_build_dir),
]
if (board_information_for_assembly != false) {
args += [
"--board-info",
rebase_path(board_information_for_assembly, root_build_dir),
]
}
deps = [
":${labels.legacy_assembly_input_bundle}",
labels.product_assembly_config,
] + labels.platform_common_aibs
inputs = [
files.legacy_assembly_input_bundle_manifest,
files.product_assembly_config,
] + files.platform_common_aibs
outputs = [ files.regenerated_image_assembly_config ]
# If there aren't blobs, there won't be a config-data package, and so it
# won't be created by product assembly (it won't have any config data in
# the legacy or common configs.)
if (_supports_blobs) {
outputs += [ files.config_data_manifest ]
}
}
hermetic_inputs_for_image_assembly(labels.image_assembly_inputs) {
forward_variables_from(invoker,
[
"testonly",
"visibility",
])
deps = [
":${labels.images_config}",
":${labels.product_assembler}",
]
image_assembly_config = files.regenerated_image_assembly_config
images_config = files.images_config
output = files.image_assembly_inputs
}
if (use_assembly_fshost) {
python_action("${labels.fshost_validator}") {
forward_variables_from(invoker,
[
"testonly",
"visibility",
])
deps = [
":${labels.fshost}",
":${labels.product_assembler}",
"//tools/configc($host_toolchain)",
]
outputs = [ "$target_out_dir/${labels.fshost_validator}.txt" ]
depfile = "$target_out_dir/$target_name.d"
binary_label = "//build/assembly/scripts:fshost_validator"
args = [
"--output",
rebase_path(outputs[0], root_build_dir),
"--configc-bin",
"host-tools/configc",
"--gn-fshost-component",
rebase_path("${target_out_dir}/cml/${labels.fshost}.manifest/fshost.cm",
root_build_dir),
"--assembly-fshost-component",
rebase_path("${files.outdir}/fshost/fshost/fshost.cm", root_build_dir),
"--gn-fshost-cml",
rebase_path("${target_out_dir}/${files.fshost_merged_cml}",
root_build_dir),
"--assembly-fshost-cml",
rebase_path("${files.outdir}/fshost/fshost/fshost.cml", root_build_dir),
"--gn-fshost-cvf",
rebase_path("${target_out_dir}/${labels.fshost}.config_cvf.cvf",
root_build_dir),
"--assembly-fshost-cvf",
rebase_path(
"${files.outdir}/bootfs/repackaging/components/meta/fshost.cvf",
root_build_dir),
"--depfile",
rebase_path(depfile, root_build_dir),
]
}
}
ffx_action(labels.image_assembler) {
no_output_dir_leaks = false
forward_variables_from(invoker,
[
"testonly",
"visibility",
])
hermetic_inputs_target = ":${labels.image_assembly_inputs}"
hermetic_inputs_file = files.image_assembly_inputs
ffx_tool = "//src/developer/ffx/plugins/assembly:ffx_assembly_tool"
ffx_tool_output_name = "ffx-assembly"
args = [
"--config",
"assembly_enabled=true",
"assembly",
"create-system",
"--image-assembly-config",
rebase_path(files.regenerated_image_assembly_config, root_build_dir),
"--images",
rebase_path(files.images_config, root_build_dir),
"--base-package-name",
"$base_package_name",
"--gendir",
rebase_path(files.gendir, root_build_dir),
"--outdir",
rebase_path(files.outdir, root_build_dir),
]
if (defined(invoker.assembly_include_account_in_fvm) &&
invoker.assembly_include_account_in_fvm) {
args += [ "--include-account" ]
}
if (ramdisk_in_zbi) {
args += [
"--mode",
"embed-in-zbi",
]
} else if (!_supports_blobs) {
args += [
"--mode",
"bootfs",
]
}
deps = []
if (defined(invoker.deps)) {
deps += invoker.deps
}
deps += [
":${labels.images_config}",
":${labels.product_assembler}",
]
# Set the deps needed in order to run the zbi_signing_script
if (defined(invoker.zbi_signing_script_deps)) {
deps += invoker.zbi_signing_script_deps
}
# Validate that the Assembly-built fshost is identical to the GN-built
# fshost until the latter is removed.
if (use_assembly_fshost) {
deps += [ ":${labels.fshost_validator}" ]
}
inputs = [
files.images_config,
files.regenerated_image_assembly_config,
]
if (defined(invoker.inputs)) {
inputs += invoker.inputs
}
outputs = [
files.bootfs_files,
files.additional_boot_args,
files.zbi,
files.zbi_manifest,
files.packages,
files.bootfs_packages,
files.image_command_log,
files.assembly_manifest,
]
if (defined(invoker.zbi_signing_script)) {
outputs += [ files.zbi_signed ]
}
if (use_vbmeta) {
outputs += [ files.vbmeta ]
}
# Base package dependencies and outputs, if this configuration uses them.
if (_supports_blobs) {
deps += [
blobfs_tool_target,
fvm_tool_target,
]
inputs += [
blobfs_tool_path,
fvm_tool_path,
]
outputs += [
# In the outdir.
files.base_package,
files.base_package_manifest,
files.base_package_merkle,
# In the gendir.
files.blobfs_manifest,
files.blobs_json,
files.static_packages,
files.cache_packages,
files.base_meta_package,
files.base_pkg_abi_revision,
]
if (generate_fvm) {
outputs += [
files.fvm,
files.fvm_sparse,
files.blobfs,
files.fvm_blob_sparse,
]
if (_has_fastboot_fvm) {
outputs += [ files.fvm_fastboot ]
if (fvm_ftl_nand_block_count != false) {
outputs += [ files.fvm_fastboot_tmp ]
}
}
}
if (generate_fxfs) {
outputs += [ files.fxfs ]
}
}
metadata = {
# We insert these barriers to prevent the dependencies of these images
# from leaking into images "higher up" in the dependency chain.
package_barrier = []
config_package_barrier = []
distribution_entries_barrier = []
images = []
if (defined(invoker.metadata)) {
forward_variables_from(invoker.metadata, "*")
}
if (generate_image_metadata) {
_image_overrides = {
zbi = {
}
zbi_signed = {
}
vbmeta = {
}
blobfs = {
}
fvm = {
}
fvm_sparse = {
}
fvm_blob_sparse = {
}
fvm_fastboot = {
}
fxfs = {
}
if (defined(image_metadata_overrides)) {
forward_variables_from(image_metadata_overrides, "*")
}
}
}
if (generate_image_metadata) {
# (Mostly) common fields across all image metadata.
_common_metadata = {
label = get_label_info(":$target_name", "label_with_toolchain")
cpu = current_cpu
}
images += [
# ZBI
{
name = image_name
type = "zbi"
forward_variables_from(_common_metadata, "*")
if (defined(invoker.output_dir)) {
label = get_label_info(labels.copy_zbi, "label_with_toolchain")
path = rebase_path("${invoker.output_dir}/" +
get_path_info(files.zbi, "file"),
root_build_dir)
} else {
path = rebase_path(files.zbi, root_build_dir)
}
forward_variables_from(_image_overrides["zbi"], "*")
},
]
if (generate_fvm) {
images += [
# BlobFS
{
name = "${image_name}.blob"
path = rebase_path(files.blobfs, root_build_dir)
type = "blk"
forward_variables_from(_common_metadata, "*")
forward_variables_from(_image_overrides["blobfs"], "*")
},
# FVM
{
name = "${image_name}.fvm"
path = rebase_path(files.fvm, root_build_dir)
type = "blk"
forward_variables_from(_common_metadata, "*")
forward_variables_from(_image_overrides["fvm"], "*")
},
# Sparse FVM
{
name = "${image_name}.fvm_sparse"
path = rebase_path(files.fvm_sparse, root_build_dir)
type = "blk"
forward_variables_from(_common_metadata, "*")
forward_variables_from(_image_overrides["fvm_sparse"], "*")
},
]
} else if (generate_fxfs) {
images += [
{
name = "${image_name}.fxfs"
path = rebase_path(files.fxfs, root_build_dir)
type = "blk"
forward_variables_from(_image_overrides["fxfs"], "*")
},
]
}
# Optionally add the signed images.
if (sign_zbi) {
images += [
{
name = image_name
type = "zbi.signed"
forward_variables_from(_common_metadata, "*")
if (defined(invoker.output_dir)) {
label = get_label_info(labels.copy_zbi_signed,
"label_with_toolchain")
path = rebase_path("${invoker.output_dir}/" +
get_path_info(files.zbi_signed, "file"),
root_build_dir)
} else {
path = rebase_path(files.zbi_signed, root_build_dir)
}
forward_variables_from(_image_overrides["zbi_signed"], "*")
},
]
}
# Optionally add the vbmeta image.
if (use_vbmeta) {
images += [
{
name = image_name
type = "vbmeta"
forward_variables_from(_common_metadata, "*")
if (defined(invoker.output_dir)) {
label =
get_label_info(labels.copy_vbmeta, "label_with_toolchain")
path = rebase_path("${invoker.output_dir}/" +
get_path_info(files.vbmeta, "file"),
root_build_dir)
} else {
path = rebase_path(files.vbmeta, root_build_dir)
}
forward_variables_from(_image_overrides["vbmeta"], "*")
},
]
}
# Optionally include the blob-only sparse FVM.
if (generate_fvm && include_fvm_blob_sparse) {
images += [
{
name = "${image_name}.fvm_blob_sparse"
path = rebase_path(files.fvm_blob_sparse, root_build_dir)
type = "blk"
forward_variables_from(_common_metadata, "*")
forward_variables_from(_image_overrides["fvm_blob_sparse"], "*")
},
]
}
# Optionally include the fastboot FVM.
if (generate_fvm && _has_fastboot_fvm) {
images += [
{
name = "${image_name}.fvm_fastboot"
path = rebase_path(files.fvm_fastboot, root_build_dir)
type = "blk"
forward_variables_from(_common_metadata, "*")
forward_variables_from(_image_overrides["fvm_fastboot"], "*")
},
]
}
}
}
if (check_production_tag) {
assert_no_deps = [ "//build/validate:non_production_tag" ]
}
}
#######
# Optionally, copy the resulting ZBI to the specified directory.
#
if (defined(invoker.output_dir)) {
assert(
invoker.output_dir != target_out_dir,
"The specified output directory must be different from the default target_out_dir")
# The output name is the same as the original file by default.
# Otherwise, it takes the output_name, and strips any extension.
output_name = "${image_name}"
if (defined(invoker.output_name)) {
parts = string_split(invoker.output_name, ".")
output_name = parts[0]
}
copy(labels.copy_zbi) {
forward_variables_from(invoker,
[
"testonly",
"visibility",
])
sources = [ files.zbi ]
outputs = [ "${invoker.output_dir}/${output_name}.zbi" ]
deps = [ ":${labels.image_assembler}" ]
}
copy(labels.copy_zbi_manifest) {
forward_variables_from(invoker,
[
"testonly",
"visibility",
])
sources = [ files.zbi_manifest ]
outputs = [ "${invoker.output_dir}/${output_name}.zbi.json" ]
deps = [ ":${labels.image_assembler}" ]
}
if (defined(invoker.zbi_signing_script)) {
copy(labels.copy_zbi_signed) {
forward_variables_from(invoker,
[
"testonly",
"visibility",
])
sources = [ files.zbi_signed ]
outputs = [ "${invoker.output_dir}/${output_name}.zbi.signed" ]
deps = [ ":${labels.image_assembler}" ]
}
}
if (use_vbmeta) {
copy(labels.copy_vbmeta) {
forward_variables_from(invoker,
[
"testonly",
"visibility",
])
sources = [ files.vbmeta ]
outputs = [ "${invoker.output_dir}/${output_name}.vbmeta" ]
deps = [ ":${labels.image_assembler}" ]
}
}
group(labels.copy_images) {
forward_variables_from(invoker,
[
"testonly",
"visibility",
])
public_deps = [
":${labels.copy_zbi_manifest}",
":${labels.copy_zbi}",
]
if (defined(invoker.zbi_signing_script)) {
public_deps += [ ":${labels.copy_zbi_signed}" ]
}
if (use_vbmeta) {
public_deps += [ ":${labels.copy_vbmeta}" ]
}
}
}
#######
# Check the golden files.
#
# TODO(fxbug.dev/101283): These checks are no longer a part of
# `assembled_system()`. Remove `not_needed(...)` once all build configurations
# no longer specify scrutiny verifier configuration.
not_needed(invoker,
[
"cmdline_goldens",
"bootfs_goldens",
"static_pkgs_goldens",
"route_sources_config",
])
bazel_input_resource_directory(labels.bazel_legacy_aib) {
forward_variables_from(invoker, [ "testonly" ])
source_dir = "${files.legacy_assembly_input_bundle_dir}"
dest_dir = rebase_path("${files.outdir}/${labels.bazel_legacy_aib}",
root_build_dir)
deps = [ ":${labels.legacy_assembly_input_bundle}" ]
}
group(target_name) {
forward_variables_from(invoker,
[
"testonly",
"visibility",
])
# public_deps is used, so that the outputs of these dependencies are
# available to external targets.
public_deps = [
":${labels.generated_config_for_legacy_bundle}",
":${labels.image_assembler}",
":${labels.images_config}",
]
if (defined(invoker.output_dir)) {
public_deps += [ ":${labels.copy_images}" ]
}
if (defined(invoker.assembly_images_config_label)) {
public_deps += [ ":${labels.images_config_matches}" ]
}
if (defined(_must_exist)) {
public_deps += [
":${labels.partial_image_assembly_config_for_validations}",
":${labels.validation_legacy_aib}",
]
}
metadata = {
# Assembly does not emit information about the packages that it includes
# via metadata, but via its own output files.
distribution_entries_barrier = []
package_barrier = []
assembly_package_barrier = []
driver_package_barrier = []
shell_commands_barrier = []
system_image_package_barrier = []
system_image_extra_package_manifest_barrier = []
test_component_manifest_barrier = []
test_component_manifest_program_barrier = []
assembly_inputs_barrier = []
assembly_manifests = [
{
image_name = namespace
assembly_manifest_path =
rebase_path(files.assembly_manifest, root_build_dir)
label = get_label_info(target_name, "label_with_toolchain")
},
]
}
}
}