blob: 4e332d3e4c1a129ecfa3a71856bcdac5fd4a6db0 [file] [log] [blame]
# Copyright 2018 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/config/clang/clang.gni")
import("//build/config/fuchsia/zbi.gni")
import("//build/config/fuchsia/zircon.gni")
import("//build/gn/packages.gni")
import("//build/images/boot.gni")
import("//build/images/crashpad.gni")
import("//build/images/manifest.gni")
import("//build/package.gni")
import("//build/sdk/sdk_atom.gni")
import("//build/sdk/sdk_molecule.gni")
import("//garnet/go/src/amber/amber.gni")
declare_args() {
# Groups to include from the Zircon /boot manifest into /boot.
# This is either "all" or a comma-separated list of one or more of:
# core -- necessary to boot
# misc -- utilities in /bin
# test -- test binaries in /bin and /test
zircon_boot_groups = "core"
}
declare_args() {
# Groups to include from the Zircon /boot manifest into /system
# (instead of into /boot like Zircon's own bootdata.bin does).
# Should not include any groups that are also in zircon_boot_groups,
# which see. If zircon_boot_groups is "all" then this should be "".
# **TODO(mcgrathr)**: _Could default to "" for `!is_debug`, or "production
# build". Note including `"test"` here places all of Zircon's tests into
# `/system/test`, which means that Fuchsia bots run those tests too._
zircon_system_groups = "misc,test"
if (zircon_boot_groups == "all") {
zircon_system_groups = ""
}
}
if (zircon_boot_groups == "all") {
assert(zircon_system_groups == "",
"zircon_boot_groups already has everything")
} else {
assert(zircon_system_groups != "all" && zircon_system_groups != "core",
"zircon_system_groups cannot include core (or all)")
}
# This will collect a list of scopes describing each image exported.
# Each scope contains:
#
# default (optional)
# [bool] Include image in the default group (default: true).
# It is preferred that very large images that are rarely used are not in the
# default group. Absence of a value is equivalent to true.
#
# deps (required)
# [list of labels] Target that generates the image file.
# If `sources` is not specified, this must be an action in this file.
#
# installer (optional)
# [string] Put this image into the installer image under this name.
#
# public (optional)
# [list of strings] Each is "IMAGE_{NAME}_{TYPE}" where `TYPE` can be:
# `SPARSE` (sparse FVM), `RAW` (block image for any FS), `ZBI`
# (bootable zircon image), `RAM` (ramdisk without kernel--obsolete),
# `VBOOT` (ZBI in a vboot container). "IMAGE_{NAME}_{TYPE}={FILE}"
# will be written out (with `FILE` relative to `root_build_dir`), to be
# consumed by //scripts and various tools to find the relevant images.
#
# json (optional)
# [scope] Content for images.json; `path` is added automatically.
# Other fields should match TODO(mcgrathr): some JSON schema.
#
# sdk (optional)
# [string] Put this image into the SDK under this name.
#
# sources (optional)
# [list of files] The image file.
#
# updater (optional)
# [string] Put this image into the update manifest under this name.
#
images = []
# Write a JSON metadata file about the packages in the build.
_packages_json = {
_all = []
monolith = []
foreach(pkg, monolith_packages) {
monolith += [ get_label_info(pkg, "name") ]
_all += [ pkg ]
_all -= [ pkg ]
_all += [ pkg ]
}
preinstall = []
foreach(pkg, preinstall_packages) {
preinstall += [ get_label_info(pkg, "name") ]
_all += [ pkg ]
_all -= [ pkg ]
_all += [ pkg ]
}
available = []
foreach(pkg, available_packages) {
available += [ get_label_info(pkg, "name") ]
_all += [ pkg ]
_all -= [ pkg ]
_all += [ pkg ]
}
packages = []
foreach(pkg, _all) {
packages += [
{
dir = get_label_info(pkg, "dir")
name = get_label_info(pkg, "name")
build_dir =
rebase_path(get_label_info(pkg, "target_out_dir"), root_build_dir)
},
]
}
}
write_file("$root_build_dir/packages.json",
{
forward_variables_from(_packages_json, "*", [ "_all" ])
},
"json")
# TODO(mcgrathr): Temporary until scripts and recipes get updated.
legacy_images_dir = "$root_out_dir/images"
board = "qemu"
if (target_cpu == "x64") {
board = "pc"
}
###
### Fuchsia system image. This aggregates contributions from all the
### package() targets enabled in the build.
###
pm_binary_label = "//garnet/go/src/pm:pm_bin($host_toolchain)"
pm_out_dir = get_label_info(pm_binary_label, "root_out_dir")
pm_binary = "$pm_out_dir/pm"
# This just runs `pm -k $system_package_key genkey` if the file doesn't exist.
# Every package() target depends on this.
action("system_package_key_check") {
visibility = [ "*" ]
deps = [
pm_binary_label,
]
outputs = [
"$target_out_dir/system_package_key_check_ok.stamp",
]
script = "//build/gn_run_binary.sh"
inputs = [
"system_package_key_check.py",
pm_binary,
]
args =
[ clang_prefix ] + rebase_path(inputs + outputs + [ system_package_key ])
}
# The pkgsvr index is a manifest mapping `package_name/package_version` to
# the merkleroot of the package's meta.far file.
pkgsvr_index = "$target_out_dir/pkgsvr_index"
action("pkgsvr_index") {
visibility = [
":system_image.manifest",
":update_packages.manifest",
]
testonly = true
script = "manifest.py"
args = [ "--contents" ]
outputs = [
"$target_out_dir/$target_name",
]
args += [ "--output=" + rebase_path(outputs[0], root_build_dir) ]
sources = []
deps = []
foreach(pkg_label, monolith_packages) {
# Find the response file written by package().
pkg_target_name = get_label_info(pkg_label, "name")
pkg_target_out_dir = get_label_info(pkg_label, "target_out_dir")
pkg_rspfile = "$pkg_target_out_dir/${pkg_target_name}.pkgsvr_index.rsp"
deps += [ "${pkg_label}.pkgsvr_index.rsp" ]
sources += [ pkg_rspfile ]
args += [ "@" + rebase_path(pkg_rspfile, root_build_dir) ]
}
}
# The /boot and /system manifests have to be generated in concert. Things
# like drivers going into /system can affect what needs to go into /boot.
boot_manifest = "$target_out_dir/boot.manifest"
# The system_image "package" manifest is everything that appears in /system.
generate_manifest("system_image.manifest") {
visibility = [ ":*" ]
testonly = true
# Create the /boot manifest that gets packed into BOOTFS in the ZBI.
# /system manifest files can assume that the /boot files are visible at
# runtime, so dependencies already in /boot won't be copied into /system.
bootfs_manifest = boot_manifest
bootfs_zircon_groups = zircon_boot_groups
# Collect whatever we want from Zircon that didn't go into /boot.
zircon_groups = zircon_system_groups
# Now each package() target in the build contributes manifest entries.
# For system_image packages, these contain binaries that need their
# references resolved from the auxiliary manifests or /boot (above).
args = []
deps = []
sources = []
foreach(pkg_label, monolith_packages) {
# Find the response file written by package().
pkg_target_name = get_label_info(pkg_label, "name")
pkg_target_out_dir = get_label_info(pkg_label, "target_out_dir")
pkg_system_rsp = "$pkg_target_out_dir/${pkg_target_name}.system.rsp"
deps += [ pkg_label ]
sources += [ pkg_system_rsp ]
args += [ "@" + rebase_path(pkg_system_rsp, root_build_dir) ]
}
args += [ "--entry-manifest=" +
get_label_info(":$target_name", "label_no_toolchain") ]
# Add the meta/package JSON file that makes this the "system_image" package.
json = "system_meta_package.json"
sources += [ json ]
args += [ "--entry=meta/package=" + rebase_path(json, root_build_dir) ]
# Add the static packages (pkgsvr) index.
deps += [ ":pkgsvr_index" ]
sources += [ pkgsvr_index ]
args += [ "--entry=data/static_packages=" +
rebase_path(pkgsvr_index, root_build_dir) ]
}
system_manifest_outputs = get_target_outputs(":system_image.manifest")
assert(boot_manifest == system_manifest_outputs[2])
system_manifest = system_manifest_outputs[0]
system_build_id_map = system_manifest_outputs[1]
# Generate, sign, and seal the system_image package file.
pm_build_package("system_image.meta") {
visibility = [ ":*" ]
testonly = true
manifest = ":system_image.manifest"
}
# Now generate the blob manifest. This lists all the source files
# that need to go into the blobfs image. That is everything from the
# system_image manifest, everything from each package manifest, and
# all the synthesized meta.far files.
blob_manifest = "$root_build_dir/blob.manifest"
action("blob.manifest") {
visibility = [ ":*" ]
testonly = true
deps = [
":system_image.manifest",
":system_image.meta",
]
outputs = [
blob_manifest,
]
inputs = [
system_manifest,
]
script = "manifest.py"
args = [ "@{{response_file_name}}" ]
response_file_contents = [
"--sources",
"--output=" + rebase_path(blob_manifest, root_build_dir),
"--manifest=" + rebase_path(system_manifest, root_build_dir),
"--entry=system_image/meta.far=" +
rebase_path("$target_out_dir/system_image.meta/meta.far",
root_build_dir),
]
foreach(pkg_label, monolith_packages + preinstall_packages) {
pkg_target_name = get_label_info(pkg_label, "name")
pkg_target_out_dir = get_label_info(pkg_label, "target_out_dir")
pkg_blob_rsp = "$pkg_target_out_dir/${pkg_target_name}.blob.rsp"
deps += [ "${pkg_label}.blob.rsp" ]
inputs += [ pkg_blob_rsp ]
response_file_contents +=
[ "@" + rebase_path(pkg_blob_rsp, root_build_dir) ]
}
}
# Pack up all the blobs!
zircon_tool_action("blob.blk") {
visibility = [ ":*" ]
testonly = true
deps = [
":blob.manifest",
]
blob_image_path = "$target_out_dir/$target_name"
outputs = [
blob_image_path,
]
depfile = blob_image_path + ".d"
inputs = [
blob_manifest,
]
tool = "blobfs"
args = [
"--depfile",
rebase_path(blob_image_path, root_build_dir),
"create",
"--manifest",
rebase_path(blob_manifest, root_build_dir),
]
}
images += [
{
deps = [
":blob.blk",
]
public = [
"IMAGE_BLOB_RAW",
]
},
]
###
### Zircon Boot Images
###
declare_args() {
# List of arguments to add to /boot/config/devmgr.
# These come after synthesized arguments to configure blobfs and pkgfs,
# and the one generated for [`enable_crashpad`](#enable_crashpad).
devmgr_config = []
# List of kernel command line arguments to bake into the boot image.
# See also //zircon/docs/kernel_cmdline.md and
# [`devmgr_config`](#devmgr_config).
kernel_cmdline_args = []
# Files containing additional kernel command line arguments to bake into
# the boot image. The contents of these files (in order) come after any
# arguments directly in [`kernel_cmdline_args`](#kernel_cmdline_args).
# These can be GN `//` source pathnames or absolute system pathnames.
kernel_cmdline_files = []
# List of extra manifest entries for files to add to the BOOTFS.
# Each entry can be a "TARGET=SOURCE" string, or it can be a scope
# with `sources` and `outputs` in the style of a copy() target:
# `outputs[0]` is used as `TARGET` (see `gn help source_expansion`).
bootfs_extra = []
}
images += [
{
# This is the file to give QEMU's `-kernel` switch with a complete
# ZBI (some `IMAGE_*_ZBI` file) for its `-initrd` switch.
public = [
"IMAGE_QEMU_KERNEL_RAW",
]
json = {
name = "qemu-kernel"
type = "kernel"
}
deps = []
if (current_cpu == "arm64") {
sources = [
"$zircon_build_dir/qemu-boot-shim.bin",
]
} else if (current_cpu == "x64") {
sources = [
"$zircon_build_dir/multiboot.bin",
]
}
},
]
# Generate the /boot/config/devmgr file. This looks like a kernel command
# line file, but is read by devmgr (in addition to kernel command line
# arguments), not by the kernel or boot loader.
action("devmgr_config.txt") {
visibility = [ ":fuchsia" ]
testonly = true
script = "manifest.py"
outputs = [
"$target_out_dir/$target_name",
]
pkgfs_label = "//garnet/go/src/pmd:pkgsvr"
pkgfs = "bin/" + get_label_info(pkgfs_label, "name")
pkgfs_label += ".meta"
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/system_image.meta/meta.far.merkle"
deps = [
":system_image.meta",
pkgfs_label,
]
sources = [
pkgfs_blob_manifest,
system_image_merkleroot,
]
args = [
"--output=" + rebase_path(outputs[0], root_build_dir),
# Start with the fixed options.
"--entry=devmgr.require-system=true",
]
# Add the pkgfs command line, embedding the merkleroot of the system image.
args += [
"--contents",
"--rewrite=*=zircon.system.pkgfs.cmd={target}+{source}",
"--entry=${pkgfs}=" + rebase_path(system_image_merkleroot, root_build_dir),
"--no-contents",
"--reset-rewrite",
]
# Embed the pkgfs blob manifest with the "zircon.system.pkgfs.file."
# prefix on target file names.
args += [
"--rewrite=*=zircon.system.pkgfs.file.{target}={source}",
"--manifest=" + rebase_path(pkgfs_blob_manifest, root_build_dir),
"--reset-rewrite",
]
if (enable_crashpad) {
args += [ "--entry=crashsvc.analyzer=from-appmgr" ]
}
foreach(entry, devmgr_config) {
args += [ "--entry=$entry" ]
}
# If there were any ASan drivers in the build, bin/devhost.asan
# should have been brought into the boot manifest. devmgr needs to
# be told to use it in case there are ASan drivers in /system but
# none in /boot. If there were any non-ASan drivers in the build,
# bin/devhost.asan will load them and needs to know to moderate the
# checking for interacting with uninstrumented code.
deps += [ ":system_image.manifest" ]
sources += [ boot_manifest ]
args += [
"--include=bin/devhost.asan",
"--include=bin/devhost",
"--rewrite=bin/devhost.asan=devmgr.devhost.asan=true",
"--rewrite=bin/devhost=devhost.asan.strict=false",
"--manifest=" + rebase_path(boot_manifest, root_build_dir),
]
}
# The main bootable image, which requires `blob.blk` to appear on some
# attached storage device at runtime.
zbi("fuchsia") {
testonly = true
deps = [
":devmgr_config.txt",
":system_image.manifest",
]
inputs = [
"${zircon_build_dir}/kernel.zbi",
boot_manifest,
]
manifest = [
{
outputs = [
"config/devmgr",
]
sources = get_target_outputs(":devmgr_config.txt")
},
]
cmdline = kernel_cmdline_args
cmdline_inputs = kernel_cmdline_files
manifest += bootfs_extra
}
images += [
{
deps = [
":fuchsia",
]
sdk = "bootdata-blob.bin"
updater = "zbi"
json = {
name = "zircon-a"
type = "zbi"
}
public = [
"IMAGE_ZIRCONA_ZBI",
# TODO(mcgrathr): The complete ZBI can be used with a separate
# kernel too, the kernel image in it will just be ignored. So
# just use the primary ZBI for this until all uses are
# converted to using the ZBI alone. Then remove this as
# IMAGE_BOOT_RAM variable should no longer be in use.
"IMAGE_BOOT_RAM",
]
legacy_copy = "bootdata-blob-${board}.bin"
legacy_copy_dir = root_out_dir
},
]
###
### Complete images for booting and installing the whole system.
###
declare_args() {
# The size of the minfs data partition image to create. Normally this image
# is added to FVM, and can therefore expand as needed. It must be at least
# 10mb (the default) in order to be succesfully initialized.
data_image_size = "10m"
# The size in bytes of the FVM partition image to create. Normally this is
# computed to be just large enough to fit the blob and data images. The
# default value is "", which means to size based on inputs. Specifying a size
# that is too small will result in build failure.
fvm_image_size = ""
# Build boot images that prefer Zedboot over local boot.
always_zedboot = false
}
template("generate_fvm") {
zircon_tool_action(target_name) {
visibility = [ ":*" ]
forward_variables_from(invoker, [ "testonly" ])
tool = "fvm"
outputs = [
invoker.output_name,
]
sources = []
deps = invoker.deps
foreach(label, deps) {
sources += get_target_outputs(label)
}
args = rebase_path(outputs, root_build_dir) + invoker.args +
rebase_path(sources, root_build_dir)
}
}
fvm_create_args = [ "create" ]
fvm_sparse_args = [
"sparse",
"--compress",
"lz4",
]
# fvm.blk creates a non-sparse FVM partition image containing the blob
# partition produced by blob.blk. fvm.blk is primarily invoked and used
# by the qemu run, via `fx run-fvm`.
generate_fvm("fvm.blk") {
testonly = true
output_name = "$target_out_dir/fvm.blk"
deps = [
":blob.blk",
]
args = fvm_create_args
if (fvm_image_size != "") {
args += [
"--length",
fvm_image_size,
]
}
args += [ "--blob" ]
}
images += [
{
deps = [
":fvm.blk",
]
json = {
name = "storage-full"
type = "blk"
}
sdk = "fvm.blk"
public = [
"IMAGE_FVM_RAW",
]
legacy_copy = "fvm.blk"
legacy_copy_dir = legacy_images_dir
},
]
# fvm.sparse.blk creates a sparse FVM partition image containing the blob
# partition produced by blob.blk. fvm.sparse.blk is primarily invoked and
# used by the paver boot, via `fx boot-paver`.
generate_fvm("fvm.sparse.blk") {
testonly = true
output_name = "$target_out_dir/fvm.sparse.blk"
deps = [
":blob.blk",
]
args = fvm_sparse_args + [ "--blob" ]
}
images += [
{
deps = [
":fvm.sparse.blk",
]
json = {
name = "storage-sparse"
type = "blk"
}
installer = "fvm.sparse.blk"
sdk = "fvm.sparse.blk"
public = [
"IMAGE_FVM_SPARSE",
]
legacy_copy = "fvm.sparse.blk"
legacy_copy_dir = legacy_images_dir
},
]
# data.blk creates an empty but initialized minfs data partition.
# The partition is included in fvm.data.sparse.blk.
zircon_tool_action("data.blk") {
tool = "minfs"
data_image_path = "$target_out_dir/$target_name"
outputs = [
data_image_path,
]
args = [
rebase_path(data_image_path, root_build_dir) + "@${data_image_size}",
"create",
]
}
images += [
{
public = [
"IMAGE_DATA_RAW",
]
deps = [
":data.blk",
]
},
]
# fmv.data.sparse.blk is an FVM image containing only data.blk. It is
# used to pave new data partitions to a device.
generate_fvm("fvm.data.sparse.blk") {
output_name = "$target_out_dir/fvm.data.sparse.blk"
deps = [
":data.blk",
]
args = fvm_sparse_args + [
"--zxcrypt",
"--data",
]
}
images += [
{
json = {
name = "data-template"
type = "blk"
}
deps = [
":fvm.data.sparse.blk",
]
installer = "fvm.data.sparse.blk"
public = [
"IMAGE_DATA_FVM_RAW",
]
legacy_copy = "fvm.data.sparse.blk"
legacy_copy_dir = legacy_images_dir
},
]
# This rolls the primary ZBI together with a compressed RAMDISK image of
# fvm.blk into a fat ZBI that boots the full system without using any real
# storage. The system decompresses the fvm.blk image into memory and then
# sees that RAM disk just as if it were a real disk on the device.
zbi("netboot") {
testonly = true
deps = [
":fuchsia",
":fvm.blk",
]
inputs = get_target_outputs(":fuchsia")
ramdisk_inputs = get_target_outputs(":fvm.blk")
}
images += [
{
default = false
json = {
name = "netboot"
type = "zbi"
}
public = [
"IMAGE_NETBOOT_ZBI",
# TODO(mcgrathr): The complete ZBI can be used with a separate kernel
# too, the kernel image in it will just be ignored. So just use the
# primary ZBI for this until all uses are converted to using the ZBI
# alone. Then remove this as IMAGE_BOOT_RAM variable should no
# longer be in use.
"IMAGE_NETBOOT_RAM",
]
deps = [
":netboot",
]
legacy_copy = "netboot.bin"
legacy_copy_dir = root_out_dir
},
]
# ChromeOS vboot images.
vboot("vboot") {
testonly = true
output_name = "fuchsia"
deps = [
":fuchsia",
]
}
images += [
{
deps = [
":vboot",
]
installer = "zircon.vboot"
sdk = "zircon.vboot"
updater = "kernc"
public = [
"IMAGE_ZIRCON_VBOOT",
]
legacy_copy = "zircon-${board}.vboot"
legacy_copy_dir = legacy_images_dir
},
]
# The installer also wants the zedboot vboot image.
images += [
{
deps = [
"zedboot:vboot",
]
sources = [
"$root_out_dir/zedboot.vboot",
]
installer = "zedboot.vboot"
},
]
if (target_cpu != "arm64") {
# EFI ESP images.
esp("esp") {
output_name = "fuchsia"
testonly = true
if (always_zedboot) {
cmdline = "zedboot/efi_cmdline.txt"
} else {
cmdline = "efi_local_cmdline.txt"
}
deps = [
":fuchsia",
"zedboot:zbi",
]
fuchsia_zbi_outputs = get_target_outputs(":fuchsia")
zircon_bin = fuchsia_zbi_outputs[0]
zedboot = "$root_out_dir/zedboot.zbi"
}
images += [
{
deps = [
":esp",
]
json = {
name = "efi"
type = "blk"
}
installer = "local.esp.blk"
sdk = "local.esp.blk"
updater = "efi"
public = [
"IMAGE_ESP_RAW",
]
legacy_copy = "local-${board}.esp.blk"
legacy_copy_dir = legacy_images_dir
},
{
deps = [
"zedboot:esp",
]
sources = [
"$root_out_dir/zedboot.esp.blk",
]
installer = "zedboot.esp.blk"
},
]
}
installer_label = "//garnet/bin/installer:install-fuchsia"
installer_out_dir = get_label_info(installer_label, "root_out_dir")
installer_path = "$installer_out_dir/install-fuchsia"
action("installer.manifest") {
script = "manifest.py"
outputs = [
"$target_out_dir/installer.manifest",
]
args = [
"--output=" + rebase_path(outputs[0], root_build_dir),
"--output-cwd=" + rebase_path(target_out_dir, root_build_dir),
"--entry=install-fuchsia=" + rebase_path(installer_path, root_build_dir),
]
foreach(image, images) {
if (defined(image.installer)) {
image_sources = []
if (defined(image.sources)) {
image_sources += image.sources
} else {
foreach(label, image.deps) {
image_sources += get_target_outputs(label)
}
}
assert(image_sources == [ image_sources[0] ])
args += [ "--entry=${image.installer}=" +
rebase_path(image_sources[0], root_build_dir) ]
}
}
}
# installer.blk is a minfs partition image that includes all of the
# images required to install a Fuchsia build.
zircon_tool_action("installer") {
testonly = true
tool = "minfs"
deps = [
":installer.manifest",
installer_label,
]
outputs = [
"$target_out_dir/installer.blk",
]
sources = []
foreach(image, images) {
if (defined(image.installer)) {
deps += image.deps
if (defined(image.sources)) {
sources += image.sources
} else {
foreach(label, image.deps) {
sources += get_target_outputs(label)
}
}
}
}
depfile = "$target_out_dir/installer.blk.d"
args = [
"--depfile",
rebase_path(outputs[0], root_build_dir),
"create",
"--manifest",
]
args += rebase_path(get_target_outputs(deps[0]), root_build_dir)
}
images += [
{
default = false
public = [
"IMAGE_INSTALLER_RAW",
]
deps = [
":installer",
]
},
]
group("images") {
testonly = true
deps = [
":default-legacy-images",
":ids.txt",
"zedboot",
]
foreach(image, images) {
if (!defined(image.default) || image.default) {
deps += image.deps
}
}
}
legacy_images = []
default_legacy_images = []
foreach(image, images) {
if (defined(image.legacy_copy)) {
copy("legacy_copy_" + image.legacy_copy) {
visibility = [ ":legacy-images" ]
if (!defined(image.default) || image.default) {
visibility += [ ":default-legacy-images" ]
}
testonly = true
deps = image.deps
outputs = [
"${image.legacy_copy_dir}/${image.legacy_copy}",
]
sources = get_target_outputs(deps[0])
}
legacy_target = ":legacy_copy_${image.legacy_copy}"
legacy_images += [ legacy_target ]
if (!defined(image.default) || image.default) {
default_legacy_images += [ legacy_target ]
}
}
}
group("legacy-images") {
visibility = [ ":images" ]
testonly = true
deps = legacy_images
}
group("default-legacy-images") {
visibility = [ ":images" ]
testonly = true
deps = default_legacy_images
}
# See definition of images (above) for purpose.
images_json = []
image_paths = []
foreach(image, images) {
image_sources = []
if (defined(image.sources)) {
image_sources += image.sources
} else {
foreach(label, image.deps) {
image_sources += get_target_outputs(label)
}
}
assert(image_sources == [ image_sources[0] ])
image_file = rebase_path(image_sources[0], root_build_dir)
if (defined(image.json)) {
images_json += [
{
forward_variables_from(image.json, "*")
path = image_file
},
]
}
if (defined(image.public)) {
foreach(name, image.public) {
image_paths += [ "${name}=${image_file}" ]
}
}
}
write_file("$root_build_dir/images.json", images_json, "json")
write_file("$root_build_dir/image_paths.sh", image_paths)
###
### Amber updates.
###
# update_packages.manifest contains the same entries as the pkgsvr_index but
# additionally includes the system_image package.
action("update_packages.manifest") {
visibility = [ ":update.manifest" ]
testonly = true
script = "manifest.py"
outputs = [
"$target_out_dir/$target_name",
]
args = [
"--contents",
"--output",
rebase_path(outputs[0], root_build_dir),
]
deps = []
sources = []
deps += [ ":system_image.meta" ]
args += [ "--entry=system_image/0=" +
rebase_path("$target_out_dir/system_image.meta/meta.far.merkle",
root_build_dir) ]
foreach(pkg_label, monolith_packages) {
# Find the response file written by package().
pkg_target_name = get_label_info(pkg_label, "name")
pkg_target_out_dir = get_label_info(pkg_label, "target_out_dir")
pkg_rspfile = "$pkg_target_out_dir/${pkg_target_name}.pkgsvr_index.rsp"
deps += [ "${pkg_label}.pkgsvr_index.rsp" ]
sources += [ pkg_rspfile ]
args += [ "@" + rebase_path(pkg_rspfile, root_build_dir) ]
}
}
# The update package manifest contains the pkgsvr_index and the target
# system kernel images.
action("update.manifest") {
visibility = [ ":*" ]
testonly = true
update_manifest = [
{
target = "packages"
deps = [
":update_packages.manifest",
]
},
# Add the meta/package JSON file that makes this the "update" package.
{
target = "meta/package"
sources = [
"update_package.json",
]
},
]
foreach(image, images) {
if (defined(image.updater)) {
update_manifest += [
{
target = image.updater
forward_variables_from(image,
[
"deps",
"sources",
])
},
]
}
}
script = "manifest.py"
outputs = [
"$target_out_dir/$target_name",
]
args = [ "--output=" + rebase_path(outputs[0], root_build_dir) ]
sources = []
deps = []
foreach(entry, update_manifest) {
entry_sources = []
if (defined(entry.deps)) {
deps += entry.deps
foreach(label, entry.deps) {
entry_sources += get_target_outputs(label)
}
}
if (defined(entry.sources)) {
entry_sources += entry.sources
}
foreach(source, entry_sources) {
source = rebase_path(source, root_build_dir)
args += [ "--entry=${entry.target}=${source}" ]
}
}
}
pm_build_package("update.meta") {
visibility = [ ":*" ]
testonly = true
manifest = ":update.manifest"
}
# XXX(raggi): The following manifests retain the "meta/" files, resulting in
# them being added as blobs, which they should not be. A likely better solution
# here is to teach pm_build_package to produce either a blob manifest or a
# manifest.py --contents compatible response file that excludes these files.
action("update.sources.manifest") {
visibility = [ ":*" ]
testonly = true
script = "manifest.py"
deps = [
":update.manifest",
]
outputs = [
"$target_out_dir/update.sources.manifest",
]
update_manifests = get_target_outputs(deps[0])
args = [
"--sources",
"--output=" + rebase_path(outputs[0], root_build_dir),
"--manifest=" + rebase_path(update_manifests[0]),
]
}
zircon_tool_action("update.blobs.manifest") {
testonly = true
visibility = [ ":amber_publish_blobs" ]
tool = "merkleroot"
deps = [
":update.sources.manifest",
]
outputs = [
"$target_out_dir/$target_name",
]
inputs = get_target_outputs(deps[0])
args = [
"-m",
rebase_path(outputs[0]),
"@" + rebase_path(inputs[0]),
]
}
# The amber index is the index of all requested packages, naming each meta.far
# file instead of its merkleroot. Additionally the amber_index has the system
# package itself, and the system update package.
amber_index = "$target_out_dir/amber_index"
action("amber_index") {
visibility = [ ":amber_publish_index" ]
testonly = true
script = "manifest.py"
args = [ "--absolute" ]
outputs = [
"$target_out_dir/$target_name",
]
args += [ "--output=" + rebase_path(outputs[0], root_build_dir) ]
sources = []
deps = []
foreach(pkg_label, available_packages) {
# Find the response file written by package().
pkg_target_name = get_label_info(pkg_label, "name")
pkg_target_out_dir = get_label_info(pkg_label, "target_out_dir")
pkg_rspfile = "$pkg_target_out_dir/${pkg_target_name}.amber_index.rsp"
deps += [ "${pkg_label}.amber_index.rsp" ]
sources += [ pkg_rspfile ]
args += [ "@" + rebase_path(pkg_rspfile, root_build_dir) ]
}
system_image_meta_dir =
get_label_info(":system_image.meta", "target_out_dir") +
"/system_image.meta"
system_image_meta_far = system_image_meta_dir + "/meta.far"
args += [
"--entry",
"system_image/0=" + rebase_path(system_image_meta_far, root_build_dir),
]
deps += [ ":system_image.meta" ]
update_meta_dir =
get_label_info(":update.meta", "target_out_dir") + "/update.meta"
update_meta_far = update_meta_dir + "/meta.far"
args += [
"--entry",
"update/0=" + rebase_path(update_meta_far, root_build_dir),
]
deps += [ ":update.meta" ]
}
# The blob.manifest that drives blob.blk is just a flat list of files.
# blob_merkleroot.manifest is a manifest file of "HEXDIGITS=FILENAME"
# lines. Note that this repeats all the same merkleroot computations
# that blobfs does while building blob.blk, which is wasteful if the
# build is doing both (though the computations can go in parallel and
# filesystem caching should mitigate the cost of reading the files
# twice). If we're always going to build blob.blk, we could teach
# blobfs to emit this manifest on the side rather than recomputing it
# here. But if someone tells ninja to build `updates` without `images`,
# then this computation alone should be faster than building blob.blk.
zircon_tool_action("blob_merkleroot.manifest") {
testonly = true
visibility = [ ":amber_publish_blobs" ]
tool = "merkleroot"
deps = [
":blob.manifest",
]
outputs = [
"$target_out_dir/$target_name",
]
inputs = [
blob_manifest,
]
args = [
"-m",
rebase_path(outputs[0]),
"@" + rebase_path(blob_manifest),
]
}
# Populate the repository directory with content ID-named copies.
action("amber_publish_blobs") {
testonly = true
outputs = [
"$amber_repository_dir.stamp",
]
deps = [
":blob_merkleroot.manifest",
":update.blobs.manifest",
]
inputs = []
foreach(dep, deps) {
inputs += get_target_outputs(dep)
}
script = "manifest.py"
args = [
"--copytree",
"--output=" + rebase_path(amber_repository_blobs_dir),
"--stamp=" + rebase_path("$amber_repository_dir.stamp"),
]
foreach(manifest, inputs) {
args += [ "--manifest=" + rebase_path(manifest, root_build_dir) ]
}
}
# Sign and publish the package index.
amber_publish("amber_publish_index") {
testonly = true
deps = [
":amber_index",
]
inputs = [
amber_index,
]
}
group("updates") {
testonly = true
deps = [
":amber_publish_blobs",
":amber_publish_index",
":ids.txt",
]
}
###
### Build ID maps.
###
# Combine the /boot, /system, and package build ID maps into one.
# Nothing in the build uses this, but top-level targets always update
# it so that debugging tools can rely on it.
action("ids.txt") {
testonly = true
deps = [
":system_image.manifest",
":vdso-ids.txt",
]
sources = [
"$target_out_dir/vdso-ids.txt",
system_build_id_map,
]
foreach(pkg_label, available_packages) {
# Find the ids.txt file written by package().
manifest = get_label_info(pkg_label, "label_no_toolchain") + ".manifest"
manifest_target_name = get_label_info(manifest, "name")
manifest_target_out_dir = get_label_info(manifest, "target_out_dir")
deps += [ manifest ]
sources += [ "$manifest_target_out_dir/${manifest_target_name}.ids.txt" ]
}
script = "/usr/bin/sort"
outputs = [
"$root_out_dir/ids.txt",
]
args = [
"-u",
"-o",
] + rebase_path(outputs + sources, root_build_dir)
}
# The vDSO doesn't appear in any package and so doesn't get into any
# ids.txt file produced by generate_manifest(). But it appears in memory
# at runtime and in backtraces, so it should be in the aggregated ids.txt
# for symbolization. The vDSO doesn't appear in zircon_boot_manifests, so
# fetching it out of Zircon's own ids.txt by name is the only thing to do.
action("vdso-ids.txt") {
script = "manifest.py"
sources = [
"$zircon_build_dir/ids.txt",
]
outputs = [
"$target_out_dir/vdso-ids.txt",
]
args = [
"--separator= ",
"--output=" + rebase_path(outputs[0], root_build_dir),
"--include-source=*/libzircon.so",
"--manifest=" + rebase_path(sources[0], root_build_dir),
]
}
###
### SDK
###
sdk_images = []
foreach(image, images) {
if (defined(image.sdk)) {
image_target_name = "${image.sdk}_sdk"
sdk_images += [ ":$image_target_name" ]
sdk_atom(image_target_name) {
domain = "image"
name = image.sdk
id = "sdk://images/${image.sdk}"
category = "partner"
testonly = true
file_content = "target/$target_cpu/${image.sdk}"
meta = {
dest = "images/${image.sdk}-meta.json"
schema = "image"
value = {
type = "image"
name = "${image.sdk}"
root = "images"
file = {
if (target_cpu == "x64") {
x64 = file_content
} else if (target_cpu == "arm64") {
arm64 = file_content
} else {
assert(false, "Unsupported target architecture: $target_cpu")
}
}
}
}
image_sources = []
if (defined(image.sources)) {
image_sources += image.sources
} else {
foreach(label, image.deps) {
image_sources += get_target_outputs(label)
}
}
assert(image_sources == [ image_sources[0] ])
files = [
{
source = image_sources[0]
dest = image.sdk
},
]
new_files = [
{
source = image_sources[0]
dest = "target/$target_cpu/${image.sdk}"
},
]
non_sdk_deps = image.deps
}
}
}
# TODO(alainv): Add dependency to zircon.bin when such a target exists.
zircon_bin_sdk_target_name = "zircon.bin_sdk"
sdk_images += [ ":$zircon_bin_sdk_target_name" ]
sdk_atom(zircon_bin_sdk_target_name) {
domain = "image"
name = "zircon.bin"
id = "sdk://images/zircon.bin"
category = "partner"
testonly = true
file_content = "target/$target_cpu/zircon.bin"
meta = {
dest = "images/zircon.bin-meta.json"
schema = "image"
value = {
type = "image"
name = "zircon.bin"
root = "images"
file = {
if (target_cpu == "x64") {
x64 = file_content
} else if (target_cpu == "arm64") {
arm64 = file_content
} else {
assert(false, "Unsupported target architecture: $target_cpu")
}
}
}
}
files = [
{
source = "${zircon_build_dir}/zircon.bin"
dest = "zircon.bin"
},
]
new_files = [
{
source = "${zircon_build_dir}/zircon.bin"
dest = "target/$target_cpu/zircon.bin"
},
]
}
if (target_cpu == "arm64") {
qemu_zircon_bin_sdk_target_name = "qemu-zircon.bin_sdk"
sdk_images += [ ":$qemu_zircon_bin_sdk_target_name" ]
sdk_atom(qemu_zircon_bin_sdk_target_name) {
domain = "image"
name = "qemu-zircon.bin"
id = "sdk://images/qemu-zircon.bin"
category = "partner"
testonly = true
file_content = "target/$target_cpu/qemu-zircon.bin"
meta = {
dest = "images/qemu-zircon.bin-meta.json"
schema = "image"
value = {
type = "image"
name = "qemu-zircon.bin"
root = "images"
file = {
if (target_cpu == "x64") {
x64 = file_content
} else if (target_cpu == "arm64") {
arm64 = file_content
} else {
assert(false, "Unsupported target architecture: $target_cpu")
}
}
}
}
files = [
{
source = "${zircon_build_dir}/qemu-zircon.bin"
dest = "qemu-zircon.bin"
},
]
new_files = [
{
source = "${zircon_build_dir}/qemu-zircon.bin"
dest = "target/$target_cpu/qemu-zircon.bin"
},
]
}
}
sdk_molecule("images_sdk") {
testonly = true
deps = sdk_images
}