| # Copyright 2024 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/product_assembly_config_file_impl.gni") |
| import("//build/python/python_action.gni") |
| |
| # Define developer overrides for product assembly |
| # |
| # Params (all are optional): |
| # |
| # developer_only_options |
| # [scope] This is a set of flags and settings for product assembly that are |
| # only available as developer overrides, they are not available to products |
| # via the 'product_assembly_configuration()' template. It's a scope with |
| # the following fields (all optional): |
| # |
| # all_packages_in_base (optional; default=false) |
| # [bool] If set to true, all packages are moved from cache to base, and |
| # all platform-defined universe packages (such as shell commands) are as |
| # well. |
| # |
| # platform |
| # [scope] This is a set of values to override / overlay onto the platform |
| # configuration. |
| # |
| # kernel |
| # [scope] This is a set of flags and settings specifically for the kernel. |
| # It's a scope with the following fields (all optional): |
| # |
| # command_line_args (optional; defauilt = []) |
| # [list, strings] A list of kernel command-line arguments to add to the |
| # zbi that's created by assembly. |
| # |
| # base_packages [optional] |
| # [list, GN labels] A list of GN labels of fuchsia_package targets to |
| # include in the base package set. |
| # |
| # Note: These are direct labels for specific targets, not deps to walk for |
| # metadata. If the target isn't a package target, it will cause an error |
| # like: |
| # "no dependency provides the input <package_name>/package_manifest.json" |
| # |
| # cache_packages [optional] |
| # [list, GN labels] A list of GN labels of fuchsia_package targets to |
| # include in the cache package set. |
| # |
| # flexible_packages [optional] |
| # [list, GN labels] A list of GN labels of fuchsia_package targets that |
| # assembly may choose to put in base, cache, or elsewhere depending on the |
| # assembly context. |
| # |
| # bootfs_packages [optional] |
| # [list, GN labels] A list of GN labels of fuchsia_package targets to |
| # include in the bootfs package set. |
| # |
| # Note: These are direct labels for specific targets, not deps to walk for |
| # metadata. If the target isn't a package target, it will cause an error |
| # like: |
| # "no dependency provides the input <package_name>/package_manifest.json" |
| # |
| # Note: These are direct labels for specific targets, not deps to walk for |
| # metadata. If the target isn't a bootfs_files_for_assembly target, it will |
| # cause an error like: |
| # "no dependency provides the input <package_name>/bootfs_files.json" |
| # |
| # shell_commands (optional; default: empty) |
| # [list of scopes] A list of scopes that describe the shell commands for each |
| # listed package (the packages need to be separately included in the desired |
| # package set). |
| # |
| # Example: |
| # shell_commands = [ |
| # { |
| # "package_name = "//third_party/sbase" |
| # components = [ "ls" ] |
| # }, |
| # ] |
| # |
| # compiled_packages [optional] |
| # [list of GN scopes] List of GN scopes of `CompiledPackageDefinition`s |
| # that describe packages that are to be built dynamically by Assembly, for |
| # example, the `core` package. This is passed directly through to the AIB |
| # config so all paths should be rebased by the caller. |
| # |
| # Example: |
| # |
| # # Add a core shard |
| # compiled_packages = [ |
| # { |
| # name = "core" |
| # components = [ |
| # { |
| # component_name = "core" |
| # shards = [ |
| # "//src/sys/process-resolver/meta/process_resolver.core_shard.cml", |
| # ] |
| # }, |
| # ... |
| # ], |
| # contents = [ { |
| # label = "//some/gn/label" |
| # source = "//som/gn/file/path" |
| # destination = "foo/bar" |
| # } ] |
| # }, |
| # ] |
| # |
| # shards [optional] |
| # [list of GN file paths] List of CML files to merge together when |
| # compiling the component. |
| # |
| # contents [optional] |
| # [list of GN scopes] List of GN scopes that describe a source/destination |
| # pair for a file to include in the package when it's compiled. An |
| # optional 'label' field is required when the file is created by the |
| # build, and is the label of the target that creates the file. |
| # |
| template("assembly_developer_overrides") { |
| labels = { |
| # So it can be reused. |
| target_name = target_name |
| |
| assembly_overrides_intermediate = |
| "${target_name}.product_assembly_overrides.intermediate.json" |
| |
| # This is a second target created by the product_assembly_config_file() |
| # template that wraps up all the input file labels found in the product and |
| # platform config with the deps that are passed to this template. |
| assembly_overrides_intermediate_inputs = |
| "${assembly_overrides_intermediate}.inputs" |
| } |
| |
| files = { |
| outdir = "$target_out_dir/$target_name" |
| assembly_config_file = "$outdir/product_assembly_overrides.json" |
| assembly_config_file_intermediate = |
| "$outdir/product_assembly_overrides.intermediate.json" |
| } |
| |
| creation_inputs = [] |
| creation_deps = [] |
| |
| # Gather up all the developer-specified packages |
| _packages = [] |
| |
| foreach(package_set, |
| [ |
| "base", |
| "cache", |
| "flexible", |
| "bootfs", |
| ]) { |
| package_set_varname = "${package_set}_packages" |
| if (defined(invoker[package_set_varname])) { |
| foreach(package_target, invoker[package_set_varname]) { |
| _package_out_dir = get_label_info(package_target, "target_out_dir") |
| _package_name = get_label_info(package_target, "name") |
| _manifest_path = |
| "${_package_out_dir}/${_package_name}/package_manifest.json" |
| |
| _packages += [ |
| { |
| package = rebase_path(_manifest_path, root_build_dir) |
| set = package_set |
| }, |
| ] |
| creation_inputs += [ _manifest_path ] |
| creation_deps += [ package_target ] |
| } |
| } |
| } |
| |
| _compiled_packages = [] |
| if (defined(invoker.compiled_packages)) { |
| foreach(package, invoker.compiled_packages) { |
| _package = { |
| } |
| _package = { |
| forward_variables_from(package, |
| "*", |
| [ |
| "contents", |
| "components", |
| "component_includes", |
| ]) |
| } |
| |
| # Rebase and gather inputs for the contents and component shards |
| |
| # Gather the deps and inputs files for the package contents. |
| if (defined(package.contents)) { |
| _contents = [] |
| foreach(entry, package.contents) { |
| creation_inputs += [ entry.source ] |
| creation_deps += [ entry.label ] |
| |
| _contents += [ |
| { |
| destination = entry.destination |
| source = rebase_path("${entry.source}", root_build_dir) |
| }, |
| ] |
| } |
| _package.contents = _contents |
| } |
| |
| # Gather the core shards as input files |
| if (defined(package.components)) { |
| _components = [] |
| foreach(entry, package.components) { |
| creation_inputs += entry.shards |
| _components += [ |
| { |
| forward_variables_from(entry, "*", [ "shards" ]) |
| shards = rebase_path(entry.shards, root_build_dir) |
| }, |
| ] |
| } |
| _package.components = _components |
| } |
| |
| _compiled_packages += [ _package ] |
| } |
| } |
| |
| _shell_commands = [] |
| if (defined(invoker.shell_commands)) { |
| foreach(shell_command, invoker.shell_commands) { |
| assert( |
| defined(shell_command.package), |
| "shell_command entries must specify a package name: ${shell_command}") |
| assert( |
| defined(shell_command.components), |
| "shell_command components must be a list of strings pointing to binaries that are components in the package that make up the package: ${shell_command}") |
| _package_name = get_label_info(shell_command.package, "name") |
| _shell_commands += [ |
| { |
| package = _package_name |
| components = shell_command.components |
| }, |
| ] |
| } |
| } |
| |
| _assembly_overrides = { |
| target_name = get_label_info(":$target_name", "label_no_toolchain") |
| forward_variables_from(invoker, |
| [ |
| "developer_only_options", |
| "platform", |
| "kernel", |
| ]) |
| packages = _packages |
| packages_to_compile = _compiled_packages |
| shell_commands = _shell_commands |
| } |
| |
| # Generate the overrides configuration file itself. |
| # |
| # This uses the product_assembly_config_file() template to properly convert |
| # any file paths in the 'platform' and 'product' sections that need to be |
| # converted from GN paths into rebased file paths. See the template's file |
| # for more information on those paths. |
| # |
| product_assembly_config_file(labels.assembly_overrides_intermediate) { |
| forward_variables_from(invoker, |
| [ |
| "deps", |
| "public_deps", |
| "testonly", |
| ]) |
| visibility = [ ":${labels.target_name}" ] |
| outputs = [ files.assembly_config_file_intermediate ] |
| product_assembly_config = _assembly_overrides |
| } |
| |
| python_action(labels.target_name) { |
| forward_variables_from(invoker, |
| [ |
| "testonly", |
| "visibility", |
| ]) |
| binary_label = "//build/assembly/scripts:developer_overrides" |
| |
| public_deps = [ |
| ":${labels.assembly_overrides_intermediate_inputs}", |
| ":${labels.assembly_overrides_intermediate}", |
| ] |
| |
| inputs = creation_inputs + [ files.assembly_config_file_intermediate ] |
| deps = creation_deps |
| outputs = [ files.assembly_config_file ] |
| |
| args = [ |
| "--input", |
| rebase_path(files.assembly_config_file_intermediate, root_build_dir), |
| "--output", |
| rebase_path(files.assembly_config_file, root_build_dir), |
| ] |
| |
| # Block all metadata walks for packages, distribution entries, etc. These |
| # inputs should not exist in metadata walks, as they are added via the paths |
| # in the assembly config itself. |
| metadata = { |
| package_barrier = [] |
| assembly_package_barrier = [] |
| config_package_barrier = [] |
| driver_package_barrier = [] |
| system_image_package_barrier = [] |
| distribution_entries_barrier = [] |
| } |
| } |
| } |
| |
| declare_args() { |
| # This GN arg enables developer overrides for the given assembly targets |
| # |
| # This is a list of scopes that take two fields: |
| # - assembly: (GN label pattern) the GN label(s) to apply the overrides to |
| # - overrides (GN label) the label of a set of developer overrides |
| # |
| # Example: |
| # |
| # product_assembly_overrides = [ |
| # { |
| # assembly = "//build/images/fuchsia/*" |
| # overrides = "//local:my_assembly_overrides" |
| # } |
| # ] |
| product_assembly_overrides = [] |
| } |
| |
| foreach(overrides_def, product_assembly_overrides) { |
| assert( |
| defined(overrides_def.assembly), |
| "'product_assembly_overrides' must specify an assembly target to override using 'assembly'") |
| assert( |
| defined(overrides_def.overrides), |
| "'product_assembly_overrides' must specify an overrides target using 'overrides'") |
| } |