| # 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" ] |
| } |
| } |
| } |