blob: 08fd3b0437372de4c2ee76a2d9c67465122b6336 [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/compiled_action.gni")
import("//build/component/component_id_index.gni")
import("//build/config.gni")
import("//build/dist/generated_resource.gni")
import("//build/images/collect_blob_manifest.gni")
import("//build/images/fvm.gni")
import("//build/images/manifest.gni")
import("//build/images/pkgfs.gni")
import("//build/images/shell_commands.gni")
import("//build/images/system_image_fuchsia_packages.gni")
import("//build/info/info.gni")
import("//build/packages/package_metadata.gni")
import("//build/security/verify_build.gni")
import("//build/unification/future/images/devmgr_config.gni")
import("//build/zbi/zbi.gni")
import("//build/zbi/zbi_input.gni")
import("//src/sys/pkg/bin/pm/pm.gni")
# Assembles a Fuchsia system.
#
# Given base, cache, and universe packages, assembles a Fuchsia system
# containing those packages.
#
# Parameters
#
# base_packages (required)
# [list of labels] The 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.
#
# bootfs_labels (required)
# [list of labels] The objects installed on the bootfs partition of the
# generated ZBI.
#
# system_image_deps (optional)
# [list of labels] The objects installed in the system image.
#
# ramdisk_fvm_in_zbi (default: false)
# [boolean] Whether the generated ZBI should contain the system's FVM as a ramdisk.
#
# devmgr_config (default: [])
# [list of strings] List of arguments to add to /boot/config/devmgr.
# These arguments come after synthesized arguments to configure blobfs and
# pkgfs.
#
# sysmgr_golden, sysmgr_golden_warn (optional, default: false)
# [path, boolean] Passed directly to the config_package template, see //build/config.gni.
#
# cmdline (optional)
# [list of strings] Kernel command line text.
#
# cmdline_inputs (optional)
# [list of files] Input files treated as kernel command line text.
#
# compress_blobs (default: true)
# [boolean] Whether the blobs added to the blobfs image should be compressed.
#
# blob_layout_format (default: "padded")
# [string] The format blobfs should store blobs in. The valid values are "padded" and
# "compact".
#
# 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.
#
# cmdline_goldens (optional)
# [list of files] A list of possible kernel cmdline golden file to compare
# against. Verified if matches one of the goldens. At most two entries are
# supported for soft migration, if the content matches either of the entries,
# it is consider a match. Only one entry should be used for normal case.
#
# bootfs_goldens (optional)
# [list of files] A list of possible bootFS golden file to compare against.
# Verified if matches one of the goldens. At most two entries are
# supported for soft migration, if the content matches either of the entries,
# it is consider a match. Only one entry should be used for normal case.
#
# static_pkgs_goldens (optional)
# [list of files] A list of possible static pkgs golden file to compare
# against. Verified if matches one of the goldens. At most two entries are
# supported for soft migration, if the content matches either of the entries,
# it is consider a match. Only one entry should be used for normal case.
#
# include_component_id_index (default: false)
# [bool] Collect and merges a component id index from the base
# package set.
#
# check_production_tag (default: false)
# [bool] Whether to check there is no non_production_tag dependencies.
#
# testonly (optional)
# [bool] Usual GN meanings.
template("assemble_system") {
assert(defined(invoker.base_packages), "Need to define base_packages")
assert(defined(invoker.bootfs_labels), "Need to define bootfs_labels")
base_packages = invoker.base_packages
cache_packages = []
universe_packages = []
if (defined(invoker.cache_packages)) {
cache_packages = invoker.cache_packages
}
if (defined(invoker.universe_packages)) {
universe_packages = invoker.universe_packages
}
system_image_deps = []
if (defined(invoker.system_image_deps)) {
system_image_deps += invoker.system_image_deps
}
# Must be unique among assembled systems.
image_name = target_name
if (defined(invoker.output_name)) {
zbi_name = invoker.output_name
} else {
zbi_name = "${target_name}.zbi"
}
ramdisk_fvm_in_zbi = false
if (defined(invoker.ramdisk_fvm_in_zbi)) {
ramdisk_fvm_in_zbi = invoker.ramdisk_fvm_in_zbi
}
compress_blobs = true
if (defined(invoker.compress_blobs)) {
compress_blobs = invoker.compress_blobs
}
blob_layout_format = "compact"
if (defined(invoker.blob_layout_format)) {
blob_layout_format = invoker.blob_layout_format
}
devmgr_config = []
if (defined(invoker.devmgr_config)) {
devmgr_config = invoker.devmgr_config
}
shell_commands("${target_name}_shell-commands") {
package_name = "shell-commands"
forward_variables_from(invoker, [ "testonly" ])
visibility = [ ":*" ]
deps = base_packages + cache_packages + universe_packages
}
# For details, see //docs/development/components/component_id_index.md#system-assembly
component_id_index_config("${image_name}_component_id_index_config") {
forward_variables_from(invoker, [ "testonly" ])
# collect and merge component ID indicies from the base set.
deps = base_packages
}
component_id_index_dep = []
component_id_index_config_data_dep = []
if (defined(invoker.include_component_id_index) &&
invoker.include_component_id_index) {
component_id_index_dep = [ ":${image_name}_component_id_index_config" ]
component_id_index_config_data_dep =
[ ":${image_name}_component_id_index_config-config-data" ]
}
config_package("${image_name}_config-data") {
package_name = "config-data"
forward_variables_from(invoker, [ "testonly" ])
visibility = [ ":*" ]
deps = base_packages + cache_packages + universe_packages +
component_id_index_config_data_dep
if (defined(invoker.sysmgr_golden)) {
sysmgr_golden = invoker.sysmgr_golden
}
if (defined(invoker.sysmgr_golden_warn)) {
sysmgr_golden_warn = invoker.sysmgr_golden_warn
}
}
group("${image_name}_base_packages") {
forward_variables_from(invoker, [ "testonly" ])
visibility = [ ":*" ]
deps = base_packages + [
":${image_name}_config-data",
":${image_name}_shell-commands",
pkgfs_package_label,
] + component_id_index_dep
}
meta_far_merkle_index = "$target_out_dir/${image_name}_meta_far_merkle_index"
generate_package_metadata("${image_name}_meta_far_merkle_index") {
forward_variables_from(invoker, [ "testonly" ])
visibility = [ ":*" ]
outputs = [ meta_far_merkle_index ]
data_keys = [ "meta_far_merkle_index_entries" ]
deps = [ ":${image_name}_base_packages" ]
}
action("${image_name}_pkgsvr_index") {
visibility = [ ":*" ]
forward_variables_from(invoker, [ "testonly" ])
inputs = [ meta_far_merkle_index ]
outputs = [ "${target_out_dir}/${target_name}" ]
deps = [ ":${image_name}_meta_far_merkle_index" ]
depfile = "${target_out_dir}/${target_name}.d"
script = "//build/images/manifest_content_expand.sh"
args = rebase_path(inputs, root_build_dir) +
rebase_path(outputs, root_build_dir) +
[ rebase_path(depfile, root_build_dir) ]
}
system_image_fuchsia_system_packages("${image_name}_fuchsia_packages") {
forward_variables_from(invoker, [ "testonly" ])
deps = system_image_deps
filter_packages = "system_only"
}
generate_manifest("${image_name}_system_image.manifest") {
visibility = [ ":*" ]
forward_variables_from(invoker, [ "testonly" ])
deps = [
":${image_name}_fuchsia_packages",
":${image_name}_pkgsvr_index",
]
json = "//build/images/system_meta_package.json"
pkgsvr_index = get_target_outputs(":${image_name}_pkgsvr_index")
system_image_fuchsia_packages_list = get_target_outputs(deps[0])
system_image_fuchsia_packages_manifest =
system_image_fuchsia_packages_list[0]
sources = [
json,
pkgsvr_index[0],
system_image_fuchsia_packages_manifest,
]
args = [
"@" + rebase_path(system_image_fuchsia_packages_manifest, root_build_dir),
"--entry=meta/package=" + rebase_path(json, root_build_dir),
"--entry=data/static_packages=" +
rebase_path(pkgsvr_index[0], root_build_dir),
]
}
pm_build("${image_name}_system_image.meta") {
visibility = [ ":*" ]
forward_variables_from(invoker, [ "testonly" ])
manifest = ":${image_name}_system_image.manifest"
package_name = "system_image"
}
blob_manifest = "$target_out_dir/${image_name}_blob.manifest"
collect_blob_manifest("${image_name}_blob.manifest") {
forward_variables_from(invoker, [ "testonly" ])
visibility = [ ":*" ]
outputs = [ blob_manifest ]
public_deps = [
":${image_name}_base_packages",
":${image_name}_system_image.meta",
pkgfs_package_label,
]
}
compiled_action("${image_name}_blob.blk") {
visibility = [ ":*" ]
forward_variables_from(invoker, [ "testonly" ])
deps = [ ":${image_name}_blob.manifest" ]
blob_image_path = "$target_out_dir/$target_name"
blob_size_list = "$target_out_dir/${image_name}_blobs.json"
outputs = [
blob_image_path,
blob_size_list,
]
depfile = blob_image_path + ".d"
inputs = [ blob_manifest ]
tool = "//zircon/tools/blobfs"
args = [
"--depfile",
"--json-output",
rebase_path(blob_size_list, root_build_dir),
]
if (compress_blobs) {
args += [ "--compress" ]
}
args += [
rebase_path(blob_image_path, root_build_dir),
"create",
"--manifest",
rebase_path(blob_manifest, root_build_dir),
"--blob_layout_format",
blob_layout_format,
]
}
compiled_action("${image_name}_data.blk") {
data_image_path = "$target_out_dir/${target_name}"
visibility = [ ":*" ]
forward_variables_from(invoker, [ "testonly" ])
outputs = [ data_image_path ]
tool = "//zircon/tools/minfs"
args = [
rebase_path(data_image_path, root_build_dir),
"create",
]
}
generate_fvm("${image_name}_fvm.blk") {
# Referenced by guest_package.
forward_variables_from(invoker, [ "testonly" ])
output_name = "$target_out_dir/$target_name"
# This target is only ever used for a ram-based FVM, so the slice size chosen does not need
# to be the same as used in other places.
args = [
"create",
"--slice",
"1048576",
]
partitions = [
{
type = "blob"
dep = ":${image_name}_blob.blk"
},
{
type = "data"
dep = ":${image_name}_data.blk"
},
]
}
zbi_input("${image_name}_fvm.blk_ramdisk") {
forward_variables_from(invoker, [ "testonly" ])
type = "ramdisk"
args = [ "--compress=$zbi_compression" ]
# Use data_deps and not deps so that the contents of the fvm don't get
# included in the dependent zbi.
data_deps = [ ":${image_name}_fvm.blk" ]
sources = [ "$target_out_dir/${image_name}_fvm.blk" ]
}
action("${image_name}_devmgr_config.txt") {
visibility = [ ":*" ]
forward_variables_from(invoker, [ "testonly" ])
script = "//build/images/manifest.py"
inputs = [ build_info_files.minimum_utc_stamp ]
outputs = [ "$target_out_dir/$target_name" ]
args = [ "--output=" + rebase_path(outputs[0], root_build_dir) ]
sources = []
deps = [ ":${image_name}_system_image.manifest" ]
pkgfs = "bin/" + pkgfs_binary_name
pkgfs_label = pkgfs_package_label
pkgfs_pkg_out_dir = get_label_info(pkgfs_label, "target_out_dir") + "/" +
get_label_info(pkgfs_label, "name")
pkgfs_blob_manifest = "$pkgfs_pkg_out_dir/meta/contents"
system_image_merkleroot =
"$target_out_dir/${image_name}_system_image.meta/meta.far.merkle"
deps += [
":${image_name}_system_image.meta",
"//build/info:latest-commit-date",
pkgfs_label,
]
sources += [
pkgfs_blob_manifest,
system_image_merkleroot,
]
args += [
"--entry=devmgr.require-system=true",
"--contents",
"--rewrite=*=zircon.system.pkgfs.cmd={target}+{source}",
"--entry=${pkgfs}=" +
rebase_path(system_image_merkleroot, root_build_dir),
"--no-contents",
"--reset-rewrite",
"--rewrite=*=zircon.system.pkgfs.file.{target}={source}",
"--manifest=" + rebase_path(pkgfs_blob_manifest, root_build_dir),
"--reset-rewrite",
]
# Add the backstop UTC value from the integration repo latest commit
args += [
"--contents",
"--entry=clock.backstop=" +
rebase_path(build_info_files.minimum_utc_stamp, root_build_dir),
"--no-contents",
"--reset-rewrite",
]
foreach(entry, devmgr_config) {
args += [ "--entry=$entry" ]
}
}
devmgr_config("${image_name}_devmgr_config") {
label = ":${image_name}_devmgr_config.txt"
forward_variables_from(invoker, [ "testonly" ])
}
zbi_input("${image_name}_cmdline") {
type = "cmdline"
args = []
if (defined(invoker.cmdline)) {
foreach(arg, invoker.cmdline) {
args += [ "--entry=$arg" ]
}
}
if (defined(invoker.cmdline_inputs)) {
sources = invoker.cmdline_inputs
}
}
check_production_tag = false
if (defined(invoker.check_production_tag)) {
check_production_tag = invoker.check_production_tag
}
zbi("${image_name}_zbi") {
metadata = {
# We insert a package barrier because the packages inside this ZBI
# shouldn't leak to targets that depend on the ZBI. For example,
# suppose we store this ZBI inside a package() that is assembled into
# another Fuchsia system. We don't want the parent system to incorporate
# the packages from the ZBI into its own package list.
package_barrier = []
config_package_barrier = []
distribution_entries_barrier = []
if (defined(invoker.metadata)) {
forward_variables_from(invoker.metadata, "*")
}
}
if (defined(invoker.output_dir)) {
output_dir = invoker.output_dir
}
output_name = zbi_name
output_extension = ""
forward_variables_from(invoker,
[
"testonly",
"visibility",
])
deps = [
":${image_name}_cmdline",
":${image_name}_devmgr_config",
":${image_name}_system_image.manifest",
"//src/sys/base-resolver:bootfs",
"//zircon/kernel",
]
deps += invoker.bootfs_labels
if (ramdisk_fvm_in_zbi) {
deps += [
":${image_name}_fvm.blk_ramdisk",
"//src/storage/fshost:minfs_ramdisk",
]
}
if (check_production_tag) {
assert_no_deps = [ "//build/validate:non_production_tag" ]
}
}
if (defined(invoker.cmdline_goldens) || defined(invoker.bootfs_goldens) ||
defined(invoker.static_pkgs_golden)) {
zbi_outputs = get_target_outputs(":${image_name}_zbi")
}
if (defined(invoker.cmdline_goldens)) {
verify_kernel_cmdline("${image_name}_cmdline_verify_files") {
forward_variables_from(invoker, [ "testonly" ])
zbi = zbi_outputs[0]
goldens = invoker.cmdline_goldens
zbi_target = ":${image_name}_zbi"
}
}
if (defined(invoker.bootfs_goldens)) {
verify_bootfs_filelist("${image_name}_bootfs_verify_files") {
forward_variables_from(invoker, [ "testonly" ])
zbi = zbi_outputs[0]
goldens = invoker.bootfs_goldens
zbi_target = ":${image_name}_zbi"
}
}
if (defined(invoker.static_pkgs_goldens)) {
verify_static_pkgs("${image_name}_static_pkgs_verify_files") {
forward_variables_from(invoker, [ "testonly" ])
zbi = zbi_outputs[0]
zbi_target = ":${image_name}_zbi"
blobfs_manifest = blob_manifest
blobfs_manifest_target = ":${image_name}_blob.manifest"
goldens = invoker.static_pkgs_goldens
}
}
group(image_name) {
forward_variables_from(invoker, [ "testonly" ])
public_deps = [ ":${image_name}_zbi" ]
deps = []
if (defined(invoker.cmdline_goldens)) {
deps += [ ":${image_name}_cmdline_verify_files" ]
}
if (defined(invoker.bootfs_goldens)) {
deps += [ ":${image_name}_bootfs_verify_files" ]
}
if (defined(invoker.static_pkgs_goldens)) {
deps += [ ":${image_name}_static_pkgs_verify_files" ]
}
}
}