| # 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/developer_overrides.gni") |
| import("//build/assembly/hermetic_inputs_for_image_assembly.gni") |
| import("//build/assembly/kernel_aib.gni") |
| import("//build/assembly/legacy_assembly_input_bundle.gni") |
| import("//build/bazel/bazel_inputs.gni") |
| import("//build/board.gni") |
| import("//build/python/python_action.gni") |
| import("//build/zircon/tools.gni") |
| import("//bundles/assembly/platform_aibs.gni") |
| import("//src/developer/ffx/build/ffx_action.gni") |
| |
| # Assembles a Fuchsia system. |
| # |
| # Given base, cache, and universe packages, assembles a Fuchsia system |
| # containing those packages. |
| # |
| # Metadata parameters: |
| # |
| # 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_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. |
| # |
| # include_assembly_inputs (optional; default=false) |
| # [bool] Whether to declare the assembly inputs metadata. |
| # |
| # Production code assertions: |
| # |
| # testonly (optional) |
| # [bool] Usual GN meanings. |
| # |
| # check_production_tag (default: false) |
| # [bool] Whether to check there is no non_production_tag dependencies. |
| # |
| # Product Assembly parameters: |
| # |
| # board_config_label (required if board_config is not used) |
| # [label] The board_configuration() target to use as the board to assemble the |
| # product for. |
| # |
| # product_assembly_config_label (optional) |
| # [label] A label for the product assembly config, should be a |
| # `product_assembly_configuration` target. This is required if |
| # legacy_bundle_only=false. |
| # |
| # 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) |
| # |
| # Legacy Bundle parameters: |
| # |
| # legacy_bundle_only (optional) |
| # [bool] When true, this template is reduced to provide the legacy bundle |
| # only. This can be set in Bazel assembly to ensure the build graph don't |
| # accidentally pick up deps on targets other than legacy bundles. |
| # |
| # base_packages (optional) |
| # [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. |
| # |
| # boot_driver_packages (optional) |
| # [list of labels] The driver packages to include in the bootfs 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 (optional) |
| # [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. |
| # |
| # 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. |
| # |
| # 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_shell_commands (default: true) |
| # [bool] Whether to include shell commands. Should be set to false for |
| # build without shell access. |
| # |
| # 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 |
| # |
| # |
| # Image Assembly parameters: |
| # |
| # assembly_include_account_in_fvm (optional; default: false) |
| # [bool] Whether to include an account partition in the FVM image. |
| # |
| # ramdisk_in_zbi (optional) |
| # [bool] Whether the FVM or Fxfs image should be embedded into the ZBI as a ramdisk. |
| # |
| # |
| # Outputs: |
| # |
| # These arguments help inform GN what to put in `outputs = []`. |
| # These do not actually cause the images to get generated. |
| # `product_assembly_config_label` is the config that declares what images to |
| # generate. |
| # |
| # 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. |
| # |
| # generate_signed_zbi (optional; default: false) |
| # [bool] Whether a signed zbi will be generated. |
| # |
| # generate_vbmeta (optional; default: false) |
| # [bool] Whether a vbmeta will be generated. |
| # |
| # generate_fvm (optional; default: false) |
| # [bool] Whether a fvm will be generated |
| # |
| # generate_fvm_fastboot (optional; default: false) |
| # [bool] Whether a fastboot fvm will be generated. |
| # |
| # generate_fvm_nand (optional; default: false) |
| # [bool] Whether a nand fvm will be generated. |
| # |
| # generate_fxfs (optional; default: false) |
| # [bool] Whether a fxfs image will be generated. |
| # Exclusive with generate_fvm and generate_fvm_*. EXPERIMENTAL. |
| # |
| # |
| # Optional copy() for the images: |
| # |
| # 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. |
| # |
| template("assembled_system") { |
| _image_name = target_name |
| if (defined(invoker.image_name)) { |
| _image_name = invoker.image_name |
| } |
| |
| _namespace = _image_name |
| if (defined(invoker.namespace)) { |
| _namespace = invoker.namespace |
| } |
| |
| _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 |
| } |
| |
| _include_assembly_inputs = false |
| if (defined(invoker.include_assembly_inputs)) { |
| _include_assembly_inputs = invoker.include_assembly_inputs |
| } |
| |
| _supports_blobs = _generate_fvm || _generate_fxfs |
| |
| _base_packages = [] |
| _base_driver_packages = [] |
| _boot_driver_packages = [] |
| _cache_packages = [] |
| _universe_packages = [] |
| |
| if (defined(invoker.base_packages)) { |
| _base_packages = invoker.base_packages |
| } |
| if (defined(invoker.cache_packages)) { |
| _cache_packages = invoker.cache_packages |
| } |
| if (defined(invoker.universe_packages)) { |
| _universe_packages = invoker.universe_packages |
| } |
| |
| # Split out driver packages into a separate list so that we |
| # can generate a driver-manager-base-config manifest. |
| # We do not generate the manifest 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 |
| } |
| |
| if (defined(invoker.boot_driver_packages) && _supports_blobs) { |
| _boot_driver_packages = invoker.boot_driver_packages |
| } |
| |
| _additional_boot_args = [] |
| if (defined(invoker.additional_boot_args)) { |
| _additional_boot_args = invoker.additional_boot_args |
| } |
| |
| # 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" ]) |
| } |
| |
| labels = { |
| legacy_assembly_input_bundle = "${_namespace}.legacy_input_bundle" |
| bazel_legacy_aib = "${_namespace}.bazel_legacy_aib" |
| } |
| |
| files = { |
| outdir = "$target_out_dir/$_namespace" |
| legacy_assembly_input_bundle_dir = "${outdir}/legacy" |
| } |
| |
| # Create the legacy assembly input bundle. |
| legacy_assembly_input_bundle(labels.legacy_assembly_input_bundle) { |
| forward_variables_from(invoker, |
| [ |
| "testonly", |
| "visibility", |
| "include_config_data", |
| "bootfs_package_labels", |
| "bootfs_labels", |
| "cmdline_deps", |
| "cmdline", |
| "fshost_config", |
| ]) |
| 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 |
| boot_driver_packages = _boot_driver_packages |
| |
| if (_include_shell_commands) { |
| shell_command_packages = |
| _base_packages + _universe_packages + _cache_packages |
| } |
| |
| supports_blobs = _supports_blobs |
| base_packages = _base_packages |
| cache_packages = _cache_packages |
| additional_boot_args = _additional_boot_args |
| include_assembly_inputs = _include_assembly_inputs |
| } |
| |
| bazel_input_directory(labels.bazel_legacy_aib) { |
| forward_variables_from(invoker, [ "testonly" ]) |
| generator = ":${labels.legacy_assembly_input_bundle}" |
| output_directory = "${files.legacy_assembly_input_bundle_dir}" |
| gn_targets_name = labels.bazel_legacy_aib |
| } |
| |
| _legacy_bundle_only = false |
| if (defined(invoker.legacy_bundle_only)) { |
| _legacy_bundle_only = invoker.legacy_bundle_only |
| } |
| |
| if (_legacy_bundle_only) { |
| not_needed(invoker, "*", []) |
| not_needed([ "_generate_fxfs" ]) # Not used if it's short-circuited above. |
| } else { |
| assert(defined(invoker.product_assembly_config_label), |
| "Need to define product_assembly_config_label") |
| |
| # TODO(b/295031019): Remove once all clients have stopped providing. |
| not_needed(invoker, |
| [ |
| "include_component_id_index", |
| "skip_fshost_validator", |
| ]) |
| |
| # This is necessary in order to _run_ assembly, but some of the builders have |
| # configurations that don't define any board, yet also end up with targets |
| # that are defined, but unbuilt, which depend on assembly. So we skip the |
| # assert in that situation, and try to make this template tolerant of being |
| # processed in a case where a board isn't defined, but we know that it will |
| # fail at build time. |
| if (has_board) { |
| assert(defined(invoker.board_config_label) && |
| invoker.board_config_label != false, |
| "'board_config_label' must be defined.") |
| } |
| |
| _generate_image_metadata = true |
| if (defined(invoker.generate_image_metadata)) { |
| _generate_image_metadata = invoker.generate_image_metadata |
| } |
| |
| _generate_vbmeta = false |
| if (defined(invoker.generate_vbmeta)) { |
| _generate_vbmeta = invoker.generate_vbmeta |
| } |
| _generate_fvm_fastboot = false |
| if (defined(invoker.generate_fvm_fastboot)) { |
| _generate_fvm_fastboot = invoker.generate_fvm_fastboot |
| } |
| _generate_fvm_nand = false |
| if (defined(invoker.generate_fvm_nand)) { |
| _generate_fvm_nand = invoker.generate_fvm_nand |
| } |
| assert(!(_generate_fvm || _generate_fvm_fastboot || _generate_fvm_nand) || |
| !_generate_fxfs, |
| "Only one of Fxfs and FVM can host blobs") |
| |
| ramdisk_in_zbi = false |
| if (defined(invoker.ramdisk_in_zbi)) { |
| ramdisk_in_zbi = invoker.ramdisk_in_zbi && _supports_blobs |
| } |
| |
| forward_variables_from(invoker, [ "image_metadata_overrides" ]) |
| if (defined(image_metadata_overrides)) { |
| _generate_signed_zbi = defined(invoker.zbi_signing_script) |
| if (defined(invoker.generate_signed_zbi)) { |
| _generate_signed_zbi = invoker.generate_signed_zbi |
| } |
| if (!_generate_signed_zbi) { |
| assert( |
| !defined(image_metadata_overrides.zbi_signed), |
| "No signed ZBI will be built: no metadata override should be provided") |
| } |
| if (!_generate_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_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") |
| } |
| |
| 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" |
| |
| # Internal labels used for Image Assembly. |
| |
| # Inherit labels from outer scope. |
| _outer_labels = labels |
| labels = { |
| } |
| |
| labels = { |
| forward_variables_from(_outer_labels, "*") |
| |
| base_packages_group = "${_namespace}.base_packages" |
| cache_packages_group = "${_namespace}.cache_packages" |
| all_packages_group = "${_namespace}.packages" |
| fshost = "${legacy_assembly_input_bundle}.fshost" |
| fshost_validator = "${_namespace}.fshost_validator" |
| image_assembly_inputs = "${_namespace}.image_assembly_inputs" |
| product_assembler = "${_namespace}.product_assembler" |
| image_assembler = "${_namespace}.image_assembler" |
| 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" |
| 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 |
| } |
| } |
| |
| validation_legacy_aib = |
| "${_namespace}.validation_legacy_assembly_input_bundle" |
| |
| # This is defined here to save against needing to check against |
| # invoker.board_config_label being false elsewhere in this template. It can |
| # just be checked for having been defined. |
| if (defined(invoker.board_config_label) && |
| invoker.board_config_label != false) { |
| board_config_label = invoker.board_config_label |
| } |
| |
| if (defined(invoker.kernel_zbi)) { |
| custom_kernel_aib = "${_namespace}.custom_kernel_aib" |
| } |
| } |
| |
| # Intermediate files produced for Image Assembly. |
| |
| # Inherit files from outer scope. |
| _outer_files = files |
| files = { |
| } |
| |
| files = { |
| forward_variables_from(_outer_files, "*") |
| |
| product_assembly_config = |
| get_label_info(invoker.product_assembly_config_label, |
| "target_out_dir") + "/" + |
| get_label_info(invoker.product_assembly_config_label, "name") + |
| "/product_assembly_config.json" |
| |
| image_assembly_inputs = |
| "$target_out_dir/${_namespace}.image_assembly_inputs" |
| |
| # 'files.board_config' will not be defined if it these don't exist. That's |
| # ok, and is checked for when constructing the product assembly action. |
| # Assembly will fail without it, but this template is still being invoked in |
| # configurations that don't define a board. |
| if (defined(labels.board_config_label)) { |
| board_config = |
| get_label_info(labels.board_config_label, "target_out_dir") + "/" + |
| get_label_info(labels.board_config_label, "name") + |
| "/board_configuration.json" |
| } |
| |
| gendir = "$outdir/gen" |
| |
| # The cmc_merge() template this is used with prepends $target_out_dir. |
| fshost_merged_cml = |
| "${labels.legacy_assembly_input_bundle}/fshost.merged.cml" |
| |
| 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" |
| zbi_unsigned = "${zbi}.unsigned" |
| vbmeta = "${outdir}/${_image_name}.vbmeta" |
| |
| if (_generate_fvm || _generate_fvm_fastboot || _generate_fvm_nand) { |
| blobfs = "${outdir}/blob.blk" |
| } |
| if (_generate_fvm) { |
| fvm = "${outdir}/fvm.blk" |
| fvm_sparse = "${outdir}/fvm.sparse.blk" |
| } |
| if (_generate_fvm_fastboot || _generate_fvm_nand) { |
| fvm_fastboot = "${outdir}/fvm.fastboot.blk" |
| } |
| if (_generate_fvm_nand) { |
| fvm_fastboot_tmp = "${outdir}/fvm.fastboot.tmp.blk" |
| } |
| if (_generate_fxfs) { |
| fxfs = "${outdir}/fxfs.blk" |
| fxfs_sparse = "${outdir}/fxfs.sparse.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}/system_image/data/static_packages" |
| cache_packages = "${gendir}/system_image/data/cache_packages.json" |
| base_meta_package = "${gendir}/system_image/meta/package" |
| base_pkg_abi_revision = |
| "${gendir}/system_image/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" |
| |
| # 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 |
| } |
| } |
| |
| if (defined(labels.custom_kernel_aib)) { |
| custom_kernel_aib = "${outdir}/custom_kernel_aib" |
| custom_kernel_aib_manifest = "${custom_kernel_aib}/assembly_config.json" |
| } |
| } |
| |
| # 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 |
| } |
| |
| ####### |
| # Build the images using the Image Assembler. |
| # |
| |
| if (defined(_must_exist)) { |
| legacy_assembly_input_bundle(labels.validation_legacy_aib) { |
| forward_variables_from(invoker, |
| [ |
| "testonly", |
| "visibility", |
| "kernel_zbi", |
| "kernel_image_name", |
| "bootfs_package_labels", |
| "bootfs_labels", |
| "cmdline_deps", |
| "cmdline", |
| ]) |
| include_config_data = true |
| supports_blobs = _supports_blobs |
| base_packages = _must_exist.base_packages |
| cache_packages = _must_exist.cache_packages |
| |
| additional_boot_args = [] |
| |
| bundle_name = "must_exist" |
| |
| bundles_dir = files.outdir |
| create_package = false |
| create_package_archive = false |
| } |
| } |
| |
| check_production_tag = false |
| if (defined(invoker.check_production_tag)) { |
| check_production_tag = invoker.check_production_tag |
| } |
| |
| # Create the AIB for a custom kernel zbi, if one was provided. |
| if (defined(labels.custom_kernel_aib)) { |
| kernel_assembly_input_bundle(labels.custom_kernel_aib) { |
| forward_variables_from(invoker, |
| [ |
| "kernel_zbi", |
| "kernel_image_name", |
| "testonly", |
| ]) |
| bundles_dir = files.outdir |
| bundle_name = "custom_kernel_aib" |
| } |
| } |
| |
| # Run product assembly. |
| ffx_action(labels.product_assembler) { |
| forward_variables_from(invoker, |
| [ |
| "deps", |
| "testonly", |
| "visibility", |
| ]) |
| if (!defined(deps)) { |
| deps = [] |
| } |
| |
| # 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), |
| ] |
| |
| if (ramdisk_in_zbi) { |
| args += [ |
| "--mode", |
| "embed-in-zbi", |
| ] |
| } else if (!_supports_blobs) { |
| args += [ |
| "--mode", |
| "bootfs", |
| ] |
| } |
| |
| args += [ |
| "--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), |
| ] |
| |
| deps += [ |
| ":${labels.legacy_assembly_input_bundle}", |
| invoker.product_assembly_config_label, |
| ] + labels.platform_common_aibs |
| |
| inputs = [ |
| files.legacy_assembly_input_bundle_manifest, |
| files.product_assembly_config, |
| ] + files.platform_common_aibs |
| |
| if (defined(files.board_config)) { |
| args += [ |
| "--board-info", |
| rebase_path(files.board_config, root_build_dir), |
| ] |
| inputs += [ files.board_config ] |
| } |
| if (defined(labels.board_config_label)) { |
| deps += [ labels.board_config_label ] |
| } |
| |
| if (defined(labels.custom_kernel_aib)) { |
| args += [ |
| "--custom-kernel-aib", |
| rebase_path(files.custom_kernel_aib_manifest, root_build_dir), |
| ] |
| deps += [ ":${labels.custom_kernel_aib}" ] |
| inputs += [ files.custom_kernel_aib_manifest ] |
| } |
| |
| 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 ] |
| } |
| |
| metadata = { |
| assembly_input_archives_barrier = [] |
| } |
| |
| # See if there are any developer overrides enabled for this target, and |
| # if so, pass them to assembly. |
| foreach(overrides_def, product_assembly_overrides) { |
| # This is done by seeing if the target_name matches each of the defined |
| # label patterns that are to have overrides. |
| if (label_matches(":$target_name", [ overrides_def.assembly ])) { |
| # The overrides are given by label, which is used to compute the path |
| # to the file created by the developer overrides template. |
| overrides_file = |
| get_label_info(overrides_def.overrides, "target_out_dir") + "/" + |
| get_label_info(overrides_def.overrides, "name") + |
| "/product_assembly_overrides.json" |
| |
| args += [ |
| "--developer-overrides", |
| rebase_path(overrides_file, root_build_dir), |
| ] |
| inputs += [ overrides_file ] |
| deps += [ overrides_def.overrides ] |
| } |
| } |
| } |
| |
| hermetic_inputs_for_image_assembly(labels.image_assembly_inputs) { |
| forward_variables_from(invoker, |
| [ |
| "testonly", |
| "visibility", |
| ]) |
| deps = [ ":${labels.product_assembler}" ] |
| |
| image_assembly_config = files.regenerated_image_assembly_config |
| output = files.image_assembly_inputs |
| } |
| |
| 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), |
| "--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.product_assembler}" ] |
| |
| inputs = [ 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, |
| ] |
| |
| _generate_signed_zbi = defined(invoker.zbi_signing_script) |
| if (defined(invoker.generate_signed_zbi)) { |
| _generate_signed_zbi = invoker.generate_signed_zbi |
| } |
| |
| if (_generate_signed_zbi) { |
| outputs += [ |
| files.zbi_signed, |
| files.zbi_unsigned, |
| ] |
| } |
| |
| if (_generate_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, |
| ] |
| } |
| if (_generate_fvm_fastboot || _generate_fvm_nand) { |
| outputs += [ files.fvm_fastboot ] |
| } |
| if (_generate_fvm_nand) { |
| outputs += [ files.fvm_fastboot_tmp ] |
| } |
| if (_generate_fxfs) { |
| outputs += [ |
| files.fxfs, |
| files.fxfs_sparse, |
| ] |
| } |
| } |
| |
| 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_fastboot = { |
| } |
| fxfs = { |
| } |
| fxfs_sparse = { |
| } |
| |
| 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 = _namespace |
| 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 = "${_namespace}.blob" |
| path = rebase_path(files.blobfs, root_build_dir) |
| type = "blk" |
| forward_variables_from(_common_metadata, "*") |
| forward_variables_from(_image_overrides["blobfs"], "*") |
| }, |
| |
| # FVM |
| { |
| name = "${_namespace}.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 = "${_namespace}.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 = "${_namespace}.fxfs" |
| path = rebase_path(files.fxfs, root_build_dir) |
| type = "fxfs-blk" |
| forward_variables_from(_common_metadata, "*") |
| forward_variables_from(_image_overrides["fxfs"], "*") |
| }, |
| { |
| name = "${_namespace}.fxfs_sparse" |
| path = rebase_path(files.fxfs_sparse, root_build_dir) |
| type = "blk" |
| forward_variables_from(_common_metadata, "*") |
| forward_variables_from(_image_overrides["fxfs_sparse"], "*") |
| }, |
| ] |
| } |
| |
| # Optionally add the signed images. |
| if (_generate_signed_zbi) { |
| images += [ |
| { |
| name = _namespace |
| 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, "file"), |
| root_build_dir) |
| } else { |
| path = rebase_path(files.zbi, root_build_dir) |
| } |
| forward_variables_from(_image_overrides["zbi_signed"], "*") |
| }, |
| ] |
| } |
| |
| # Optionally add the vbmeta image. |
| if (_generate_vbmeta) { |
| images += [ |
| { |
| name = _namespace |
| 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 fastboot FVM. |
| if (_generate_fvm_fastboot || _generate_fvm_nand) { |
| images += [ |
| { |
| name = "${_namespace}.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}" ] |
| } |
| |
| _generate_signed_zbi = defined(invoker.zbi_signing_script) |
| if (defined(invoker.generate_signed_zbi)) { |
| _generate_signed_zbi = invoker.generate_signed_zbi |
| } |
| if (_generate_signed_zbi) { |
| copy(labels.copy_zbi_signed) { |
| forward_variables_from(invoker, |
| [ |
| "testonly", |
| "visibility", |
| ]) |
| sources = [ files.zbi ] |
| outputs = [ "${invoker.output_dir}/${output_name}.zbi.signed" ] |
| deps = [ ":${labels.image_assembler}" ] |
| } |
| } |
| |
| if (_generate_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 (_generate_signed_zbi) { |
| public_deps += [ ":${labels.copy_zbi_signed}" ] |
| } |
| if (_generate_vbmeta) { |
| public_deps += [ ":${labels.copy_vbmeta}" ] |
| } |
| } |
| } |
| |
| ####### |
| # Check the golden files. |
| # |
| # TODO(https://fxbug.dev/42052091): 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", |
| ]) |
| |
| 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.image_assembler}" ] |
| if (defined(invoker.output_dir)) { |
| public_deps += [ ":${labels.copy_images}" ] |
| } |
| if (defined(_must_exist)) { |
| public_deps += [ ":${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") |
| }, |
| ] |
| } |
| } |
| } |
| } |