| # Copyright 2021 The Fuchsia Authors. All rights reserved. |
| # Use of this source code is governed by a BSD-style license that can be |
| # found in the LICENSE file. |
| |
| import("//build/assembly/package_manifests_list.gni") |
| import("//build/compiled_action.gni") |
| import("//build/python/python_action.gni") |
| import("//src/sys/pkg/bin/pm/pm.gni") |
| |
| # Creates a Fuchsia Package for an Assembly Input Bundle. For the format |
| # of the created package, see the AssemblyInputBundle documentation at: |
| # //build/python/modules/assembly/assembly_input_bundle.py |
| # |
| # Parameters |
| # |
| # manifest |
| # [path] The path to the FINI manifest created by the assembly input bundle |
| # |
| # package_name (optional; default: target_name) |
| # [string] The name of the package, if not $target_name |
| # |
| # package_outdir (optional; default: target_out_dir) |
| # [path] A different directory to write the bundle into, if not to write it |
| # to '$target_out_dir/$bundle_name'. |
| # |
| # GN usual meanings |
| # deps, testonly, visibility |
| # |
| template("assembly_input_bundle_package") { |
| assert(defined(invoker.manifest), |
| "A manifest path must be specified: " + |
| get_label_info(target_name, "label_with_toolchain")) |
| |
| package_outdir = target_out_dir |
| if (defined(invoker.package_outdir)) { |
| package_outdir = invoker.package_outdir |
| } |
| |
| package_name = target_name |
| if (defined(invoker.bundle_name)) { |
| package_name = invoker.package_name |
| } |
| |
| labels = { |
| package_manifest_creation = "${target_name}.creation_manifest.fini" |
| package = target_name |
| } |
| |
| files = { |
| meta_package_file = "$package_outdir/meta_package" |
| creation_manifest = "$package_outdir/creation_manifest.fini" |
| } |
| |
| # Build a package CreationManifest that includes the contents in |
| # |invoker.manifest| and a generated meta/package file. |
| python_action(labels.package_manifest_creation) { |
| forward_variables_from(invoker, |
| [ |
| "deps", |
| "testonly", |
| ]) |
| visibility = [ ":${labels.package}" ] |
| binary_label = "//build/assembly/scripts:assembly_input_bundle_tool" |
| inputs = [ invoker.manifest ] |
| outputs = [ |
| files.creation_manifest, # must be the first output, for passing to |
| # pm_build |
| files.meta_package_file, |
| ] |
| args = [ |
| "generate-package-creation-manifest", |
| "--name", |
| package_name, |
| "--contents-manifest", |
| rebase_path(invoker.manifest, root_build_dir), |
| "--meta-package", |
| rebase_path(files.meta_package_file, root_build_dir), |
| "--output", |
| rebase_path(files.creation_manifest, root_build_dir), |
| ] |
| } |
| |
| pm_build(target_name) { |
| forward_variables_from(invoker, |
| [ |
| "deps", |
| "testonly", |
| "visibility", |
| ]) |
| package_name = package_name |
| package_out_dir = package_outdir |
| manifest = ":${labels.package_manifest_creation}" |
| metadata = { |
| if (defined(invoker.metadata)) { |
| forward_variables_from(invoker.metadata, "*") |
| } |
| |
| # These are a bunch of barriers to make sure that if this target gets |
| # included anywhere, it's dependencies don't end up getting gathered |
| # in metadata walks. |
| distribution_entries_barrier = [] |
| system_image_package_barrier = [] |
| system_image_extra_package_manifest_barrier = [] |
| test_component_manifest_barrier = [] |
| test_component_manifest_program_barrier = [] |
| } |
| } |
| } |
| |
| # Creates an archive for the Fuchsia Package for an Assembly Input Bundle. |
| # |
| # This is a tgz that contains the entire contents of the AIB, including the |
| # meta.far file as well. See the AssemblyInputBundle documentation at: |
| # //build/python/modules/assembly/assembly_input_bundle.py |
| # |
| # Parameters |
| # |
| # archive_name (optional; default: target_name) |
| # [string] A different name for the archive, if not the name of the target. |
| # |
| # archive_outdir (optional; default: target_out_dir) |
| # [path] A different directory to write the archive into. |
| # |
| # manifest |
| # [path] The path to the FINI manifest created for the |
| # assembly input bundle |
| # |
| # meta_far |
| # [path] The path to the meta far created for the assembly input bundle's package |
| # |
| template("assembly_input_bundle_archive") { |
| assert(defined(invoker.manifest), |
| "A manifest path must be specified: " + |
| get_label_info(target_name, "label_with_toolchain")) |
| |
| archive_outdir = target_out_dir |
| if (defined(invoker.archive_outdir)) { |
| archive_outdir = invoker.archive_outdir |
| } |
| |
| archive_name = target_name |
| if (defined(invoker.archive_name)) { |
| archive_name = invoker.archive_name |
| } |
| |
| labels = { |
| tarmaker = "//build/tools/tarmaker($host_toolchain)" |
| } |
| |
| files = { |
| tarmaker = host_out_dir + "/tarmaker" |
| |
| archive = "${archive_outdir}/${archive_name}.tgz" |
| archive_creation_manifest = "${archive}.creation_manifest.fini" |
| depfile = "${archive}.d" |
| } |
| |
| python_action(target_name) { |
| forward_variables_from(invoker, |
| [ |
| "testonly", |
| "visibility", |
| ]) |
| binary_label = "//build/assembly/scripts:assembly_input_bundle_tool" |
| inputs = [ |
| invoker.manifest, |
| files.tarmaker, |
| ] |
| outputs = [ |
| files.archive, |
| files.archive_creation_manifest, |
| ] |
| depfile = files.depfile |
| args = [ |
| "generate-archive", |
| "--tarmaker", |
| rebase_path(files.tarmaker, root_build_dir), |
| "--contents-manifest", |
| rebase_path(invoker.manifest, root_build_dir), |
| "--creation-manifest", |
| rebase_path(files.archive_creation_manifest, root_build_dir), |
| "--output", |
| rebase_path(files.archive, root_build_dir), |
| "--depfile", |
| rebase_path(files.depfile, root_build_dir), |
| ] |
| deps = [ labels.tarmaker ] |
| if (defined(invoker.deps)) { |
| deps += invoker.deps |
| } |
| if (defined(invoker.meta_far)) { |
| args += [ |
| "--meta-far", |
| rebase_path(invoker.meta_far, root_build_dir), |
| ] |
| } |
| metadata = { |
| assembly_input_archives = [ |
| { |
| path = rebase_path(files.archive, root_build_dir) |
| label = get_label_info(":$target_name", "label_with_toolchain") |
| }, |
| ] |
| } |
| } |
| } |
| |
| # Creates an Assembly Input Bundle from sets of deps. |
| # |
| # NOTE: This is not yet able to support all categories of inputs that are in an |
| # AIB. That support will be added in future CLs. See the parameters |
| # below for the categories that are currently supported. |
| # |
| # Parameters |
| # |
| # bundle_name (optional; default: target_name) |
| # [string] A different name for the bundle, if not the name of the target. |
| # |
| # bundle_dir (optional; default: target_out_dir) |
| # [path] A different directory to write the bundle into, if not to write it |
| # to '$target_out_dir/$bundle_name'. |
| # |
| # base_packages (optional; default: empty) |
| # [list of labels] A list of GN labels to walk for base packages. |
| # |
| # cache_packages (optional; default: empty) |
| # [list of labels] A list of GN labels to walk for cache packages. |
| # |
| # qemu_kernel (optional; default: false) |
| # [path] Path to the qemu kernel. |
| # |
| # create_aib_package (optional; default: false) |
| # [boolean] Set to true to also create a package that contains the contents |
| # of the AIB. |
| # target: '{$target_name}.pkg' |
| # outputs: [ |
| # '${bundle_dir}/${bundle_name}.pkg/meta.far', |
| # '${bundle_dir}/${bundle_name}.pkg/package_manifest.json', |
| # ] |
| # |
| # create_aib_archive (optional; default: false) |
| # [boolean] Set to true to create a tgz archive that contains the contents of |
| # the AIB. |
| # target: '{$target_name}.tgz' |
| # outputs: [ '${bundle_dir}/${bundle_name}.tgz' ] |
| # |
| # |
| # Outputs |
| # A directory structure and manifest that matches that documented in |
| # //build/python/modules/assembly/assembly_input_bundle.py. |
| # |
| # manifest path: |
| # $target_out_dir/$target_name/assembly_config.json |
| # |
| # |
| # GN usual meanings |
| # testonly, visibility |
| template("assembly_input_bundle") { |
| bundles_dir = target_out_dir |
| if (defined(invoker.bundles_dir)) { |
| bundles_dir = invoker.bundles_dir |
| } |
| |
| bundle_name = target_name |
| if (defined(invoker.bundle_name)) { |
| bundle_name = invoker.bundle_name |
| } |
| |
| labels = { |
| base_packages_list = "${target_name}.base_packages.list" |
| cache_packages_list = "${target_name}.cache_packages.list" |
| |
| # The AIB itself |
| assembly_input_bundle = "$target_name.bundle" |
| |
| # The assembly bundle package and archive labels |
| assembly_input_bundle_package = "${target_name}.pkg" |
| assembly_input_bundle_archive = "${target_name}.tgz" |
| } |
| |
| files = { |
| _gen_files = "${target_gen_dir}/${target_name}" |
| base_packages_list = "${_gen_files}/base_packages.list" |
| cache_packages_list = "${_gen_files}/cache_packages.list" |
| |
| # The directory where all the bundle contents are written to |
| assembly_input_bundle_dir = "${bundles_dir}/${bundle_name}" |
| |
| # The "official" outputs file that we create in that directory |
| assembly_input_bundle_config = |
| "${assembly_input_bundle_dir}/assembly_config.json" |
| |
| # The files that we create as book-keeping between our tasks. |
| assembly_input_bundle_depfile = "${assembly_input_bundle_dir}.d" |
| |
| # The manifest of all files in the AIB, used to create pkgs and archives. |
| assembly_input_bundle_manifest = |
| "${assembly_input_bundle_dir}.fini_manifest" |
| |
| # The AIB package's meta.far (optionally used) |
| assembly_input_bundle_package_metafar = |
| "${assembly_input_bundle_dir}.pkg/meta.far" |
| |
| # The AIB archive and the manifest used to create it (optionally used) |
| assembly_input_bundle_archive = "${assembly_input_bundle_dir}.tgz" |
| assembly_input_bundle_archive_manifest = |
| "${assembly_input_bundle_dir}.tgz.fini_manifest" |
| } |
| |
| create_aib_package = |
| defined(invoker.create_aib_package) && invoker.create_aib_package |
| create_aib_archive = |
| defined(invoker.create_aib_archive) && invoker.create_aib_archive |
| |
| creation_args = [] |
| creation_inputs = [] |
| creation_deps = [] |
| if (defined(invoker.deps)) { |
| creation_deps += invoker.deps |
| } |
| |
| # Only add the base packages list if it's non-empty |
| if (defined(invoker.base_packages) && invoker.base_packages != []) { |
| package_manifests_list(labels.base_packages_list) { |
| forward_variables_from(invoker, |
| [ |
| "testonly", |
| "visibiilty", |
| ]) |
| filename = files.base_packages_list |
| deps = invoker.base_packages |
| } |
| |
| creation_args += [ |
| "--base-pkg-list", |
| rebase_path(files.base_packages_list, root_build_dir), |
| ] |
| creation_inputs += [ files.base_packages_list ] |
| creation_deps += [ ":${labels.base_packages_list}" ] |
| } |
| |
| # Only add the cache packages list if it's non-empty |
| if (defined(invoker.cache_packages) && invoker.cache_packages != []) { |
| package_manifests_list(labels.cache_packages_list) { |
| forward_variables_from(invoker, |
| [ |
| "testonly", |
| "visibiilty", |
| ]) |
| filename = files.cache_packages_list |
| deps = invoker.cache_packages |
| } |
| |
| creation_args += [ |
| "--cache-pkg-list", |
| rebase_path(files.cache_packages_list, root_build_dir), |
| ] |
| creation_inputs += [ files.cache_packages_list ] |
| creation_deps += [ ":${labels.cache_packages_list}" ] |
| } |
| |
| if (defined(invoker.qemu_kernel)) { |
| creation_args += [ |
| "--qemu-kernel", |
| rebase_path(invoker.qemu_kernel, root_build_dir), |
| ] |
| } |
| |
| # Create the out-of-tree-usable Assembly Input Bundle |
| python_action(labels.assembly_input_bundle) { |
| forward_variables_from(invoker, |
| [ |
| "testonly", |
| "visibility", |
| ]) |
| |
| binary_label = "//build/assembly/scripts:assembly_input_bundle_tool" |
| |
| # The contents of these folders is dynamic, and managed entirely by this |
| # action. Further, this action will need to delete items from these |
| # directories that are not added back (on an incremental build, if an item |
| # is removed from one of these sets) |
| # |
| # These folders would grow in size forever, if it was not cleaned out on |
| # each incremental build. |
| hermetic_action_ignored_prefixes = [ |
| "${files.assembly_input_bundle_dir}/packages", |
| "${files.assembly_input_bundle_dir}/blobs", |
| "${files.assembly_input_bundle_dir}/config_data", |
| "${files.assembly_input_bundle_dir}/bootfs", |
| "${files.assembly_input_bundle_dir}/kernel", |
| ] |
| |
| outputs = [ files.assembly_input_bundle_config ] |
| depfile = files.assembly_input_bundle_depfile |
| |
| args = [ |
| "create", |
| "--outdir", |
| rebase_path(files.assembly_input_bundle_dir, root_build_dir), |
| "--depfile", |
| rebase_path(files.assembly_input_bundle_depfile, root_build_dir), |
| ] |
| args += creation_args |
| |
| # If packaging or archiving the AIB, write out the fini manifest needed to |
| # do so. |
| if (create_aib_package || create_aib_archive) { |
| args += [ |
| "--export-manifest", |
| rebase_path(files.assembly_input_bundle_manifest, root_build_dir), |
| ] |
| outputs += [ files.assembly_input_bundle_manifest ] |
| } |
| |
| inputs = creation_inputs |
| deps = creation_deps |
| |
| metadata = { |
| # We insert these barriers to prevent the dependencies of the input bundle |
| # from leaking into images "higher up" in the dependency chain. |
| package_barrier = [] |
| config_package_barrier = [] |
| distribution_entries_barrier = [] |
| } |
| } |
| |
| # Optionally create the fuchsia-pkg for the AIB. |
| if (create_aib_package) { |
| assembly_input_bundle_package(labels.assembly_input_bundle_package) { |
| forward_variables_from(invoker, |
| [ |
| "testonly", |
| "visibility", |
| ]) |
| package_name = bundle_name |
| package_outdir = "${bundles_dir}/${bundle_name}.pkg" |
| manifest = files.assembly_input_bundle_manifest |
| deps = [ ":${labels.assembly_input_bundle}" ] |
| } |
| } |
| |
| # Optionally create the archive for the AIB. |
| if (create_aib_archive) { |
| assembly_input_bundle_archive(labels.assembly_input_bundle_archive) { |
| forward_variables_from(invoker, |
| [ |
| "testonly", |
| "visibility", |
| ]) |
| archive_name = bundle_name |
| archive_outdir = bundles_dir |
| manifest = files.assembly_input_bundle_manifest |
| deps = [ ":${labels.assembly_input_bundle}" ] |
| |
| # If the package was created, include it in the archive. |
| if (create_aib_package) { |
| meta_far = files.assembly_input_bundle_package_metafar |
| deps += [ ":${labels.assembly_input_bundle_package}" ] |
| } |
| } |
| } |
| |
| group(target_name) { |
| forward_variables_from(invoker, |
| [ |
| "testonly", |
| "visibility", |
| ]) |
| public_deps = [ ":${labels.assembly_input_bundle}" ] |
| if (create_aib_package) { |
| public_deps += [ ":${labels.assembly_input_bundle_package}" ] |
| } |
| if (create_aib_archive) { |
| public_deps += [ ":${labels.assembly_input_bundle_archive}" ] |
| } |
| } |
| } |