blob: 945f0ce99e99280b6e5018ca9316df618ab58ded [file] [log] [blame]
# Copyright 2021 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.
# This is a re-implementation of //build/images/BUILD.gn, but using the ffx
# assembly plugin as the main implementation. Most of the work in this file
# is creating the translation between the Fuchsia Build and the inputs that the
# ffx assembly plugin expects.
import("//build/compiled_action.gni")
import("//build/components/fuchsia_system_package.gni")
import("//build/dist/resource.gni")
import("//build/images/args.gni")
import("//build/images/assembly/generated_board_config.gni")
import("//build/images/assembly/generated_product_config.gni")
import("//build/images/custom_signing.gni")
import("//build/images/vboot/vboot.gni")
import("//build/info/info.gni")
import("//build/packages/package_metadata.gni")
import("//build/security.gni")
import("//build/testing/verify_files_match.gni")
import("//src/developer/ffx/build/ffx_action.gni")
# These imports to be replaced by board-config json files
import("//build/images/filesystem_limits.gni")
import("//build/images/fvm.gni")
import("//build/product.gni")
import("//build/zbi/zbi.gni")
####
#
# Deal with "bringup" and other zbi-only builds.
#
# These builds set `bootfs_only` to true, and do not include a base/system_image
# package, pkgfs, blobfs, fvm, etc.
#
# This declares an inverted variable that has easier reading and is less likely
# to miss the `!` operator:
#
uses_base_package = !bootfs_only
####
#
# All the stuff in this file that we want to build by default:
#
group("assembly") {
testonly = true
deps = [
":images",
":input_validation_checks",
":output_validation_checks",
]
# Recovery-only configurations don't have a properly configured fuchsia.zbi,
# as they are really building a recovery.zbi, with it's own separate
# configuration.
#
# `ffx assembly` cannot build the configurations these fuchsia.zbi's have, and
# so we clear the deps here to disable all these targets.
if (recovery_only) {
deps = []
}
}
#####
#
# Labels used internally in this file
labels = {
board_config = "board_config.json"
}
# Labels whose outputs are used by Image Assembly, and are deps in this file
dep_labels = {
####
# External labels whose outputs are compared against for validity (temporary)
#
system_image_pkg = "//build/images:system_image.meta"
# `bootfs_only` is only set by 'bringup', which uses different assembly
# targets and differently named files in the previous assembly implementation
# than `core` and above. That difference should go away as
# //build/images/BUILD.gn is ported over to using ffx assembly.
if (bootfs_only) {
fuchsia_zbi = "//build/images/bringup"
fuchsia_zbi_manifest = fuchsia_zbi
if (use_vbmeta) {
fuchsia_vbmeta = "//build/images/bringup:bringup.vbmeta"
}
} else {
if (custom_signing_script != "" || use_vboot) {
fuchsia_zbi = "//build/images:signed"
} else {
fuchsia_zbi = "//build/images:fuchsia"
}
fuchsia_zbi_manifest = "//build/images:fuchsia_unverified"
if (use_vbmeta) {
fuchsia_vbmeta = "//build/images:fuchsia.vbmeta"
}
}
prev_update_pkg = "//build/images:update.meta"
prev_blobfs = "//build/images:blob.blk"
prev_fvm = "//build/images:fvm.blk"
prev_sparse_fvm = "//build/images:fvm.sparse.blk"
prev_sparse_blob_fvm = "//build/images:fvm.blob.sparse.blk"
prev_fastboot_fvm = "//build/images:fvm.fastboot.blk"
####
# Internal labels, in "dep" format:
#
board_config = ":" + labels.board_config
}
#####
#
# File Paths used by Image Assembly
#
# These are all the files that are inputs, outputs, or intermediates that are
# used by the actions in this file.
#
# files.foo = The "inputs" or "outputs" usage of the file "foo"
# files_args.foo = The same path, but rebased on $root_build_dir, for passing
# as a tool argument.
#
files = {
assembly_config = "${target_out_dir}/config.json"
board_config = "${target_out_dir}/board_config.json"
# The working directories for the ffx assembly image task.
gendir = "${target_out_dir}/gen"
outdir = target_out_dir
# Intermediates used by base package creation.
gen_base_static_packages = "${gendir}/data/static_packages"
gen_base_cache_packages = "${gendir}/data/cache_packages"
gen_base_meta_package = "${gendir}/system_image/meta/package"
# The base package output.
base_pkg = "${target_out_dir}/base.far"
# The ZBI output
zbi = "${target_out_dir}/fuchsia.zbi"
# If the ZBI is going to be "signed", or vendor-script-processed, then write
# the _actual_ ZBI to this path, and the one that will be used in the update
# package to the above path.
zbi_unsigned = "${zbi}.unsigned"
# ZBI output manifest
zbi_manifest = "${target_out_dir}/gen/zbi.json"
# The vbmeta (if created)
vbmeta = "${target_out_dir}/fuchsia.vbmeta"
# Intermediates used by update package creation.
gen_update_meta_package = "${gendir}/update/meta/package"
# The update package output
update_pkg = "${target_out_dir}/update.far"
# The BlobFS output
blobfs = "${target_out_dir}/blob.blk"
# The FVM output
fvm = "${target_out_dir}/fvm.blk"
sparse_fvm = "${target_out_dir}/fvm.sparse.blk"
sparse_blob_fvm = "${target_out_dir}/fvm.blob.sparse.blk"
fastboot_fvm = "${target_out_dir}/fvm.fastboot.blk"
#####
# Files used for validation against external label outputs (temporary)
#
# The base package re-extraction (temporary) output dir
extracted_base_pkg = "${target_out_dir}/extracted_base_pkg"
# The extracted base package contents
extracted_base_meta_contents = "${extracted_base_pkg}/meta/contents"
extracted_base_meta_package = "${extracted_base_pkg}/meta/package"
# The system-image package itself (from //build/images:system-image.meta)
system_image_pkg =
get_label_info(dep_labels.system_image_pkg, "target_out_dir") +
"/system_image.meta/meta.far"
# The system-image package re-extraction (temporary) output dir
extracted_sysimg_pkg = "${target_out_dir}/extracted_sysimg_pkg"
# The extracted base package contents
extracted_sysimg_meta_contents = "${extracted_sysimg_pkg}/meta/contents"
extracted_sysimg_meta_package = "${extracted_sysimg_pkg}/meta/package"
# bootfs_only is only set by 'bringup', which uses different assembly targets
# in the previous assembly implements.
if (bootfs_only) {
# The zbi created by //build/images/bringup
fuchsia_zbi = "${root_build_dir}/bringup.zbi"
fuchsia_zbi_manifest = "${fuchsia_zbi}.json"
# The vbmeta for bringup.
fuchsia_vbmeta = "${root_build_dir}/bringup.vbmeta"
fuchsia_vbmeta_salt = "${fuchsia_vbmeta}.salt"
} else {
if (custom_signing_script != "") {
# The vendor-processed zbi created by //build/images:signed
fuchsia_zbi = "${root_build_dir}/fuchsia.zbi.signed"
} else if (use_vboot) {
# The vboot-processed zbi created by //build/images:signed
fuchsia_zbi = "${root_build_dir}/fuchsia.zbi.vboot"
} else {
# The zbi created by //build/images:fuchsia
fuchsia_zbi = "${root_build_dir}/fuchsia.zbi"
}
fuchsia_zbi_manifest = "${root_build_dir}/fuchsia_unverified.zbi.json"
# The vbmeta for fuchsia_zbi
fuchsia_vbmeta = "${root_build_dir}/fuchsia.vbmeta"
fuchsia_vbmeta_salt = "${fuchsia_vbmeta}.salt"
}
# The update package re-extraction (temporary) output dir
extracted_update_pkg = "${target_out_dir}/extracted_update_pkg"
# The extracted update package contents
extracted_update_meta_contents = "${extracted_update_pkg}/meta/contents"
extracted_update_meta_package = "${extracted_update_pkg}/meta/package"
# The previous update package created by //build/images:fuchsia.vbmeta
prev_update_pkg = "${root_build_dir}/obj/build/images/update.meta/meta.far"
# The previous update package re-extraction (temporary) output dir
extracted_prev_update_pkg = "${target_out_dir}/extracted_fuchsia_update_pkg"
# The extracted previous update package contents
extracted_prev_update_meta_contents =
"${extracted_prev_update_pkg}/meta/contents"
extracted_prev_update_meta_package =
"${extracted_prev_update_pkg}/meta/package"
# The blobfs created by //build/images:blob.blk
prev_blobfs = "${root_build_dir}/obj/build/images/blob.blk"
# The minfs created by //build/images:data.blk
prev_minfs = "${root_build_dir}/obj/build/images/data.blk"
# The fvms created by the GN build.
prev_fvm = "${root_build_dir}/obj/build/images/fvm.blk"
prev_sparse_fvm = "${root_build_dir}/obj/build/images/fvm.sparse.blk"
prev_sparse_blob_fvm =
"${root_build_dir}/obj/build/images/fvm.blob.sparse.blk"
prev_fastboot_fvm = "${root_build_dir}/obj/build/images/fvm.fastboot.blk"
}
#####
# File path arguments used by Image Assembly (rebased for tool usage)
#
# This are most of the above files, rebased on root_build_dir, for use when
# calling tools with the paths.
#
# This is the hard way of doing `file_args = rebase_path(files, root_build_dir)`
file_args = {
assembly_config = rebase_path(files.assembly_config, root_build_dir)
board_config = rebase_path(files.board_config, root_build_dir)
gendir = rebase_path(files.gendir, root_build_dir)
outdir = rebase_path(files.outdir, root_build_dir)
gen_base_static_packages =
rebase_path(files.gen_base_static_packages, root_build_dir)
gen_base_cache_packages =
rebase_path(files.gen_base_cache_packages, root_build_dir)
base_pkg = rebase_path(files.base_pkg, root_build_dir)
zbi = rebase_path(files.zbi, root_build_dir)
zbi_manifest = rebase_path(files.zbi_manifest, root_build_dir)
update_pkg = rebase_path(files.update_pkg, root_build_dir)
# vboot input
zbi_unsigned = rebase_path(files.zbi_unsigned, root_build_dir)
#####
# Files used for validation against external label outputs (temporary)
#
extracted_base_pkg = rebase_path(files.extracted_base_pkg, root_build_dir)
system_image_pkg = rebase_path(files.system_image_pkg, root_build_dir)
extracted_sysimg_pkg = rebase_path(files.extracted_sysimg_pkg, root_build_dir)
fuchsia_zbi = rebase_path(files.fuchsia_zbi, root_build_dir)
if (defined(files.fuchsia_vbmeta)) {
fuchsia_vbmeta = rebase_path(files.fuchsia_vbmeta, root_build_dir)
fuchsia_vbmeta_salt = rebase_path(files.fuchsia_vbmeta_salt, root_build_dir)
}
extracted_update_pkg = rebase_path(files.extracted_update_pkg, root_build_dir)
prev_update_pkg = rebase_path(files.prev_update_pkg, root_build_dir)
extracted_prev_update_pkg =
rebase_path(files.extracted_prev_update_pkg, root_build_dir)
}
generated_product_config("product_config") {
testonly = true
output_path = files.assembly_config
kernel_image = "//zircon/kernel"
include_version_and_epoch = true
_base_packages = [
"//:additional_base_driver_packages",
"//:additional_base_packages",
"//build/images:driver-manager-base-config",
]
_base_packages += meta_package_labels
_cache_packages = [ "//:additional_cache_packages" ]
bootfs_labels = [ "//build/input:bootfs" ]
if (bootfs_only) {
# BootFS-only builds put all the packages in BootFS.
bootfs_labels += [ "//build/input:system_image" ]
bootfs_labels += _base_packages + _cache_packages
bootfs_labels += [ "//:additional_universe_packages" ]
} else {
# All other builds, put their packages in the FVM.
base_packages = _base_packages
cache_packages = _cache_packages
extra_base_deps = [ "//build/input:system_image" ]
}
cmdline_deps = [ "//build/input:bootfs" ]
}
# Select the correct vbmeta and salt depending on if it is bootfs_only or not.
if (use_vbmeta) {
if (bootfs_only) {
vbmeta_label = "//build/images/bringup:bringup.vbmeta"
vbmeta_file = "$root_build_dir/bringup.vbmeta"
} else {
vbmeta_label = "//build/images:fuchsia.vbmeta"
vbmeta_file = "$root_build_dir/fuchsia.vbmeta"
}
vbmeta_salt = rebase_path("${vbmeta_file}.salt", root_build_dir)
}
generated_board_config("board_config") {
testonly = true
board_name = board_name
output_path = files.board_config
recovery = recovery_label
use_esp = target_cpu != "arm64" && !use_vboot
# minfs arguments
if (!bootfs_only) {
minfs =
rebase_path("$root_build_dir/obj/build/images/data.blk", root_build_dir)
if (minfs_product_minimum_inodes != false) {
minfs_minimum_inodes = minfs_product_minimum_inodes
} else if (minfs_board_minimum_inodes != false) {
minfs_minimum_inodes = minfs_board_minimum_inodes
}
if (minfs_product_minimum_data_bytes != false) {
minfs_minimum_data_bytes = minfs_product_minimum_data_bytes
} else if (minfs_board_minimum_data_bytes != false) {
minfs_minimum_data_bytes = minfs_board_minimum_data_bytes
}
if (minfs_product_maximum_bytes != false) {
minfs_maximum_bytes = minfs_product_maximum_bytes
} else if (minfs_board_maximum_bytes != false) {
minfs_maximum_bytes = minfs_board_maximum_bytes
}
}
# blobfs arguments
blob_layout_format = blob_layout_format
compress_blobs = compress_blobs
if (!bootfs_only) {
if (blobfs_product_minimum_inodes != false) {
blobfs_minimum_inodes = blobfs_product_minimum_inodes
} else if (blobfs_board_minimum_inodes != false) {
blobfs_minimum_inodes = blobfs_board_minimum_inodes
}
if (blobfs_product_minimum_data_bytes != false) {
blobfs_minimum_data_bytes = blobfs_product_minimum_data_bytes
} else if (blobfs_board_minimum_data_bytes != false) {
blobfs_minimum_data_bytes = blobfs_board_minimum_data_bytes
}
if (blobfs_product_maximum_bytes != false) {
blobfs_maximum_bytes = blobfs_product_maximum_bytes
} else if (blobfs_board_maximum_bytes != false) {
blobfs_maximum_bytes = blobfs_board_maximum_bytes
}
}
# fvm arguments
if (!bootfs_only) {
fvm_slice_size = fvm_slice_size
}
# zbi arguments
if (custom_signing_script != "") {
zbi_signing_script = custom_signing_script
} else if (use_vboot) {
zbi_signing_script = vboot_action.script
zbi_signing_args = vboot_action.args
}
if (use_vbmeta) {
deps = [ vbmeta_label ]
salt_file = vbmeta_salt
}
}
# Determine if a fastboot-supported FVM should be generated.
build_fastboot_fvm = false
if (fvm_partition != "" && !bootfs_only &&
(fvm_emmc_partition_size != false || fvm_ftl_nand_block_count != false)) {
build_fastboot_fvm = true
}
#####
# Create the images themselves using `ffx assembly`
#
#
ffx_action("images") {
# TODO(fxbug.dev/77290) - Add depfile support and then remove the following
hermetic_deps = false
testonly = true
deps = [
":board_config",
":product_config",
]
if (use_vbmeta) {
deps += [ vbmeta_label ]
}
args = []
if (verbose_image_assembly) {
args += [ "-v" ]
}
args += [
"--config",
"assembly_enabled=true",
"assembly",
"image",
"--product",
file_args.assembly_config,
"--board",
file_args.board_config,
"--gendir",
file_args.gendir,
"--outdir",
file_args.outdir,
]
inputs = [
files.assembly_config,
files.board_config,
]
outputs = []
# Base package outputs, if this configuration uses them
if (uses_base_package) {
outputs += [
files.base_pkg,
files.blobfs,
files.fvm,
files.sparse_fvm,
files.sparse_blob_fvm,
# intermediate outputs that are in gendir:
files.gen_base_static_packages,
files.gen_base_cache_packages,
files.gen_base_meta_package,
files.gen_update_meta_package,
]
if (build_fastboot_fvm) {
outputs += [ files.fastboot_fvm ]
}
}
# zbi outputs
outputs += [
files.zbi,
files.zbi_manifest,
files.update_pkg,
]
if (use_vbmeta) {
inputs += [ files.fuchsia_vbmeta_salt ]
outputs += [ files.vbmeta ]
}
# These are from custom signing of the ZBI.
if (use_vboot) {
deps += vboot_action.deps
inputs += vboot_action.inputs
outputs += [ files.zbi_unsigned ]
}
}
#####
#
# Validation that the inputs generated for the ffx assembly match those of the
# current implementation in //build/images/BUILD.gn
#
# NOTE: For consistency, the //build/images/BUILD.gn inputs and outputs are
# always listed as the "first" file, and the files generated in this
# BUILD.gn file are listed as the "second" file, to keep the diff view
# of the files consistent (left=first=original, right=second=new)
#
group("input_validation_checks") {
testonly = true
deps = []
if (uses_base_package) {
deps += [
":cache_index.matches",
":pkgsvr_index.matches",
]
}
}
if (uses_base_package) {
verify_files_match("pkgsvr_index.matches") {
testonly = true
deps = [
":images",
"//build/images:pkgsvr_index",
]
first = "$root_build_dir/obj/build/images/pkgsvr_index"
second = files.gen_base_static_packages
display_text_diff_on_failure = true
}
verify_files_match("cache_index.matches") {
testonly = true
deps = [
":images",
"//build/images:cache_index",
]
first = "$root_build_dir/obj/build/images/cache_index"
second = files.gen_base_cache_packages
display_text_diff_on_failure = true
}
}
#####
#
# Validation checks that the base package contents matches the system-image
# package contents
group("output_validation_checks") {
testonly = true
deps = []
if (uses_base_package) {
deps += [
":base_pkg_meta_contents_matches",
":base_pkg_meta_far_matches",
# Even though assembly always creates this, if there is a ZBI, the
# previous implementation didn't if it was making a bootfs-only image, so
# only attempt the comparison if there's a base package (which is inverse
# of bootfs-only).
":blobfs_matches",
":fvm_matches",
":sparse_blob_fvm_matches",
":sparse_fvm_matches",
":update_matches",
":update_pkg_meta_contents_matches",
":update_pkg_meta_package_matches",
]
}
if (build_fastboot_fvm) {
deps += [ ":fastboot_fvm_matches" ]
}
deps += [
":zbi_manifest_matches",
":zbi_matches",
]
if (use_vbmeta) {
deps += [ ":vbmeta_matches" ]
}
}
if (uses_base_package) {
# Extract system-image's package's contents for inspection
compiled_action("extract_system_image_pkg") {
testonly = true
tool = "//src/sys/pkg/bin/far:bin"
tool_output_name = "far"
args = [
"extract",
"--archive=${file_args.system_image_pkg}",
"--output=${file_args.extracted_sysimg_pkg}",
]
inputs = [ files.system_image_pkg ]
outputs = [
files.extracted_sysimg_meta_contents,
files.extracted_sysimg_meta_package,
]
deps = [ "//build/images:system_image.meta" ]
}
# Extract base package's contents for inspection
compiled_action("extract_base_pkg") {
testonly = true
tool = "//src/sys/pkg/bin/far:bin"
tool_output_name = "far"
args = [
"extract",
"--archive=${file_args.base_pkg}",
"--output=${file_args.extracted_base_pkg}",
]
inputs = [ files.base_pkg ]
outputs = [
files.extracted_base_meta_contents,
files.extracted_base_meta_package,
]
deps = [ ":images" ]
}
verify_files_match("base_pkg_meta_contents_matches") {
testonly = true
deps = [
":extract_base_pkg",
":extract_system_image_pkg",
]
first = files.extracted_sysimg_meta_contents
second = files.extracted_base_meta_contents
display_text_diff_on_failure = true
}
verify_files_match("base_pkg_meta_far_matches") {
testonly = true
deps = [
":images",
"//build/images:system_image.meta",
]
first = files.system_image_pkg
second = files.base_pkg
}
}
verify_files_match("zbi_matches") {
testonly = true
deps = [
":images",
dep_labels.fuchsia_zbi,
]
first = files.zbi
second = files.fuchsia_zbi
}
verify_files_match("zbi_manifest_matches") {
testonly = true
deps = [
":images",
dep_labels.fuchsia_zbi_manifest,
]
first = files.fuchsia_zbi_manifest
second = files.zbi_manifest
display_text_diff_on_failure = true
}
if (use_vbmeta) {
verify_files_match("vbmeta_matches") {
testonly = true
deps = [
":images",
dep_labels.fuchsia_vbmeta,
]
first = files.fuchsia_vbmeta
second = files.vbmeta
}
}
if (uses_base_package) {
verify_files_match("update_matches") {
testonly = true
deps = [
":images",
dep_labels.prev_update_pkg,
]
first = files.prev_update_pkg
second = files.update_pkg
}
# Extract update package's contents for inspection
compiled_action("extract_update_pkg") {
testonly = true
tool = "//src/sys/pkg/bin/far:bin"
tool_output_name = "far"
args = [
"extract",
"--archive=${file_args.update_pkg}",
"--output=${file_args.extracted_update_pkg}",
]
inputs = [ files.update_pkg ]
outputs = [
files.extracted_update_meta_contents,
files.extracted_update_meta_package,
]
deps = [ ":images" ]
}
# Extract update package's contents for inspection
compiled_action("extract_prev_update_pkg") {
testonly = true
tool = "//src/sys/pkg/bin/far:bin"
tool_output_name = "far"
args = [
"extract",
"--archive=${file_args.prev_update_pkg}",
"--output=${file_args.extracted_prev_update_pkg}",
]
inputs = [ files.prev_update_pkg ]
outputs = [
files.extracted_prev_update_meta_contents,
files.extracted_prev_update_meta_package,
]
deps = [ dep_labels.prev_update_pkg ]
}
verify_files_match("update_pkg_meta_contents_matches") {
testonly = true
deps = [
":extract_prev_update_pkg",
":extract_update_pkg",
]
first = files.extracted_prev_update_meta_contents
second = files.extracted_update_meta_contents
display_text_diff_on_failure = true
}
verify_files_match("update_pkg_meta_package_matches") {
testonly = true
deps = [
":extract_prev_update_pkg",
":extract_update_pkg",
]
first = files.extracted_prev_update_meta_package
second = files.extracted_update_meta_package
display_text_diff_on_failure = true
}
verify_files_match("blobfs_matches") {
testonly = true
deps = [
":images",
dep_labels.prev_blobfs,
]
first = files.prev_blobfs
second = files.blobfs
}
verify_files_match("fvm_matches") {
testonly = true
deps = [
":images",
dep_labels.prev_fvm,
]
first = files.prev_fvm
second = files.fvm
}
verify_files_match("sparse_fvm_matches") {
testonly = true
deps = [
":images",
dep_labels.prev_sparse_fvm,
]
first = files.prev_sparse_fvm
second = files.sparse_fvm
}
verify_files_match("sparse_blob_fvm_matches") {
testonly = true
deps = [
":images",
dep_labels.prev_sparse_blob_fvm,
]
first = files.prev_sparse_blob_fvm
second = files.sparse_blob_fvm
}
if (build_fastboot_fvm) {
verify_files_match("fastboot_fvm_matches") {
testonly = true
deps = [
":images",
dep_labels.prev_fastboot_fvm,
]
first = files.prev_fastboot_fvm
second = files.fastboot_fvm
}
}
}