| # Copyright 2020 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/dist/fini_manifest.gni") |
| import("//build/dist/verify_manifest_elf_binaries.gni") |
| import("//build/images/args.gni") |
| import("//build/packages/package_metadata.gni") |
| import("//src/sys/pkg/bin/pm/pm.gni") |
| import("//tools/cmc/build/cmc.gni") |
| |
| # Defines a Fuchsia package. |
| # See: https://fuchsia.dev/fuchsia-src/development/components/build |
| # |
| # Fuchsia packages are a collection of any number of files (or resources), each |
| # with a unique path that is relative to the package's root. |
| # Package targets collect resources via their dependencies. These dependencies |
| # are typically fuchsia_component() targets, which provide their component |
| # manifest and other files that the component needs (such as an executable). |
| # |
| # Packages can be defined as a collection of pairs each representing a file in |
| # the package. Each pair consists of the path in the package that is assigned |
| # to the file, and a path relative to the build system's output directory where |
| # the contents of the file will be sourced from. |
| # This mapping is generated at build time, and is known as the package |
| # manifest. |
| # |
| # To view the package manifest, For instance assume you have defined |
| # a package at `path/to/project:my_package` and built it: |
| # ``` |
| # $ fx build path/to/project:my_package |
| # ``` |
| # You can then find the path to the generated manifest: |
| # ``` |
| # $ fx gn outputs out/default path/to/project:my_package_manifest |
| # ``` |
| # |
| # The package name is defined by the target name. |
| # Some rules apply to package names. |
| # See: https://fuchsia.dev/fuchsia-src/concepts/packages/package_url#package-name |
| # |
| # It's recommended for a package to depend on one or more `fuchsia_component()` |
| # targets. Typically no other dependencies are required. |
| # |
| # Example: |
| # ``` |
| # fuchsia_package("my-package") { |
| # deps = [ |
| # ":first_component", |
| # ":second_component", |
| # ] |
| # } |
| # ``` |
| # |
| # Parameters |
| # |
| # package_name (optional) |
| # The name of the package. |
| # Type: string |
| # Default: target_name |
| # |
| # disable_elf_binaries_checks (optional) |
| # Set to true to disable ELF binaries verification checks. Useful |
| # if your package includes non-Fuchsia ELF binaries, or if some |
| # of them are unstripped. |
| # Type: boolean |
| # Default: false |
| # |
| # system_image_package_allowed_in_extra_deps (optional) |
| # Used internally to implement fuchsia_system_package(), do not use! |
| # If defined, this is a fuchsia_system_package(), and the argument value |
| # determines whether it is allowed in extra dependency trees beside |
| # the one from //build/input:system_image. |
| # Type: boolean |
| # |
| # deps |
| # testonly |
| # visibility |
| template("fuchsia_package") { |
| if (current_toolchain == target_toolchain) { |
| package_name = target_name |
| if (defined(invoker.package_name)) { |
| package_name = invoker.package_name |
| } |
| |
| # Generate the "meta/package" file |
| meta_package_target = "${target_name}_meta_package" |
| generate_meta_package(meta_package_target) { |
| forward_variables_from(invoker, [ "testonly" ]) |
| visibility = [ ":*" ] |
| package_name = package_name |
| } |
| |
| # Generate package manifest |
| package_manifest_target = "${target_name}_manifest" |
| package_manifest_file = "$target_out_dir/${target_name}_manifest" |
| fini_manifest(package_manifest_target) { |
| forward_variables_from(invoker, |
| [ |
| "deps", |
| "testonly", |
| ]) |
| if (!defined(deps)) { |
| deps = [] |
| } |
| deps += [ ":$meta_package_target" ] |
| visibility = [ ":*" ] |
| outputs = [ package_manifest_file ] |
| } |
| |
| # Verify ELF binaries |
| verify_elf = !(defined(invoker.disable_elf_binaries_checks) && |
| invoker.disable_elf_binaries_checks) |
| if (verify_elf) { |
| package_manifest_verify_target = "${target_name}.verify" |
| verify_manifest_elf_binaries(package_manifest_verify_target) { |
| forward_variables_from(invoker, [ "testonly" ]) |
| manifest = package_manifest_file |
| deps = [ ":$package_manifest_target" ] |
| } |
| } |
| |
| _is_system_package = false |
| if (defined(invoker.system_image_package_allowed_in_extra_deps)) { |
| _is_system_package = true |
| _is_system_package_allowed_in_extra_deps = |
| invoker.system_image_package_allowed_in_extra_deps |
| } |
| |
| # Build package |
| pm_build(target_name) { |
| forward_variables_from(invoker, |
| [ |
| "all_outputs_fresh", |
| "deps", |
| "testonly", |
| "visibility", |
| ]) |
| manifest = ":$package_manifest_target" |
| metadata = { |
| if (defined(invoker.metadata)) { |
| forward_variables_from(invoker.metadata, "*") |
| } |
| if (!bootfs_only && !_is_system_package) { |
| # Installing a Fuchsia package into another one should not also install |
| # its content to the root install location, which is why this metadata key |
| # is set to an empty list. However, there are two exceptions to this: |
| # |
| # - fuchsia_system_package() instances whose content must end up |
| # into either the system image (handled by system_image_package_info below) |
| # or the boot filesystem (handled through distribution_manifest(). |
| # |
| # - When 'bootfs_only' is set to true, which corresponds to the "bringup" |
| # configuration which requires subtle adjustments in the build graph. |
| # |
| distribution_entries_barrier = [] |
| } |
| |
| # Used by system_image_fuchsia_packages_list() to allow embedding |
| # the content of this package into the system image, if necessary. |
| # |
| # The schema is the following: |
| # |
| # label: GN label of this target (used for debugging only). |
| # fini_manifest: path to FINI manifest listing this package's content. |
| # system_image_packaged_allowed_in_extra_deps: (optional) |
| # If defined, this is a fuchsia_system_package() instance, and its |
| # value determines whether it is allowed in extra dependency trees |
| # (see fuchsia_system_package() description for details). If undefined, |
| # this is a regular fuchsia_package(). |
| # |
| system_image_package_info = [ |
| { |
| label = get_label_info(":$target_name", "label_with_toolchain") |
| fini_manifest = rebase_path(package_manifest_file, root_build_dir) |
| if (_is_system_package) { |
| system_image_package_allowed_in_extra_deps = |
| _is_system_package_allowed_in_extra_deps |
| } |
| }, |
| ] |
| system_image_package_barrier = [] |
| } |
| if (!defined(deps)) { |
| deps = [] |
| } |
| if (verify_elf) { |
| deps += [ ":$package_manifest_verify_target" ] |
| } |
| } |
| } else { |
| # Fuchsia packages should only be built with target_toolchain. However, it |
| # is possible for package targets to be expanded in other toolchains (host, |
| # variant, etc.). In these cases, make fuchsia_package expand to nothing. |
| group(target_name) { |
| } |
| |
| # Suppress unused variable warnings. |
| not_needed(invoker, "*") |
| } |
| } |