blob: 70e0af4e2cb409d0c03fac4abc78b84be31f7b53 [file] [log] [blame]
# 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}" ]
}
}
}