| # Copyright 2017 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/images/args.gni") | 
 | import("//build/images/manifest.gni") | 
 | import("//build/testing/test_spec.gni") | 
 | import("//build/unification/zbi/resource.gni") | 
 | import("//src/sys/component_index/component_index.gni") | 
 | import("//src/sys/pkg/bin/pm/pm.gni") | 
 | import("//tools/cmc/build/cml.gni") | 
 | import("//tools/cmc/build/cmx.gni") | 
 | import("//tools/cmc/build/validate_component_manifest_references.gni") | 
 |  | 
 | # Defines a package | 
 | # | 
 | # The package template is used to define a unit of related code and data. | 
 | # A package always has a name (defaulting to the target name) and lists of | 
 | # scopes describing the components of the package. | 
 | # | 
 | # Parameters | 
 | # | 
 | #   meta (optional) | 
 | #     [list of scopes] Defines the metadata entries in the package. A metadata | 
 | #     entry is typically a source file and is placed in the `meta/` directory of | 
 | #     the assembled package. | 
 | # | 
 | #     Entries in a scope in the meta list: | 
 | # | 
 | #       path (required) | 
 | #         [path] Location of entry in source or build directory. If the | 
 | #         resource is checked in, this will typically be specified as a | 
 | #         path relative to the BUILD.gn file containing the `package()` | 
 | #         target. If the resource is generated, this will typically be | 
 | #         specified relative to `$target_gen_dir`. | 
 | # | 
 | #       dest (required) | 
 | #         [path] Location the resource will be placed within `meta/`. | 
 | # | 
 | #   binaries (optional) | 
 | #     [list of scopes] Defines the binaries in the package. A binary is | 
 | #     typically produced by the build system and is placed in the `bin/` | 
 | #     directory of the assembled package. | 
 | # | 
 | #     Entries in a scope in the binaries list: | 
 | # | 
 | #       name (required) | 
 | #         [string] Name of the binary. | 
 | # | 
 | #       source (optional) | 
 | #         [path] Location of the binary in the build directory if it is not | 
 | #         at `$root_out_dir/$name`. | 
 | # | 
 | #       dest (optional) | 
 | #         [path] Location the binary will be placed within `bin/`. | 
 | # | 
 | #       shell (optional) | 
 | #         [boolean] (default: false) When true, the binary is runnable from the shell. | 
 | #         Shell binaries are run in the shell namespace and are not run as components. | 
 | # | 
 | #   tests (optional) | 
 | #     [list of scopes] Defines the test binaries in the package. A test is | 
 | #     typically produced by the build system and is placed in the `test/` | 
 | #     directory of the assembled package. | 
 | # | 
 | #     Entries in a scope in the tests list: | 
 | # | 
 | #       name (required) | 
 | #         [string] Name of the test. | 
 | # | 
 | #       dest (optional, default: name) | 
 | #         [path] Location the binary will be placed within `test/`. | 
 | # | 
 | #       disabled (optional) | 
 | #         [bool] Whether to disable the test on continuous integration | 
 | #         jobs. This can be used when a test is temporarily broken, or if | 
 | #         it is too flaky or slow for CI. The test will also be skipped by | 
 | #         the `runtests` command. | 
 | # | 
 | #       environments (optional, default: [ { dimensions = { device_type = "QEMU" } } ]) | 
 | #         [list of scopes] Device environments in which the test should run. | 
 | # | 
 | #         Each scope in $environments contains: | 
 | # | 
 | #           dimensions (required) | 
 | #             [scope] Dimensions of bots to target. Valid dimensions are | 
 | #             element-wise subsets of the test platform entries defined in | 
 | #             //build/testing/platforms.gni. | 
 | # | 
 | #           tags (optional) | 
 | #             [list of strings] Keys on which tests may be grouped. Tests with | 
 | #             given keys will be run (1) together, and (2) only with support | 
 | #             from the Infrastructure team. Labels are used as an escape hatch | 
 | #             from the default testing pipeline for special tests or environments. | 
 | # | 
 | #      log_settings (optional, default: see below properties) | 
 | #        [json] Properties of logs produced by this test run. | 
 | # | 
 | #        Following properties are supported: | 
 | # | 
 | #        max_severity (optional, default: WARN) | 
 | #          [string] Defines maximum severity of logs which can be produced by test | 
 | #          environment. This can only be defined for test components. Test will fail | 
 | #          if any component in its environment produces log with greater severity | 
 | #          than defined here. | 
 | # | 
 | #     parallel (optional) | 
 | #       [int] Defines maximum concurrent test cases to run. This only works with v2 tests. | 
 | #             If not defined, test runner will decide the default value. | 
 | # | 
 | #   drivers (optional) | 
 | #     [list of scopes] Defines the drivers in the package. A driver is | 
 | #     typically produced by the build system and is placed in the `driver/` | 
 | #     directory of the assembled package. | 
 | # | 
 | #     Entries in a scope in the drivers list: | 
 | # | 
 | #       name (required) | 
 | #         [string] Name of the driver. | 
 | # | 
 | #   loadable_modules (optional) | 
 | #     [list of scopes] Defines the loadable modules in the package.  These | 
 | #     are produced by `loadable_module()` GN targets, and are typically | 
 | #     placed in the `lib/` directory of the assembled packaged. | 
 | # | 
 | #     Entries in a scope in the loadable_modules list: | 
 | # | 
 | #       name (required) | 
 | #         [string] Name of the loadable_module. | 
 | # | 
 | #       dest (optional, default: "lib") | 
 | #         [string] Location the binary will be placed in the package. | 
 | # | 
 | #   libraries (optional, *DEPRECATED*) | 
 | #     [list of scopes] Defines the (shared) libraries in the package. A library | 
 | #     is placed in the `lib/` directory of the assembled package. | 
 | # | 
 | #     This is deprecated but is necessary in some `system_image` packages | 
 | #     that install libraries used by things that don't properly isolate | 
 | #     their dependencies.  Do not use it unless you are sure you have to. | 
 | # | 
 | #     Entries in a scope in the libraries list: | 
 | # | 
 | #       name (required) | 
 | #         [string] Name of the library | 
 | # | 
 | #       source (optional) | 
 | #         [path] Location of the binary in the build directory if it is not at | 
 | #         `$root_out_dir/$name` | 
 | # | 
 | #       dest (optional) | 
 | #         [path] Location the binary will be placed within `lib/` | 
 | # | 
 | #   resources (optional) | 
 | #     [list of scopes] Defines the resources in the package. A resource is a | 
 | #     data file that may be produced by the build system, checked in to a | 
 | #     source repository, or produced by another system that runs before the | 
 | #     build. Resources are placed in the `data/` directory of the assembled | 
 | #     package. | 
 | # | 
 | #     Entries in a scope in the resources list: | 
 | # | 
 | #       path (required) | 
 | #         [path] Location of resource in source or build directory. If the | 
 | #         resource is checked in, this will typically be specified as a | 
 | #         path relative to the BUILD.gn file containing the `package()` | 
 | #         target. If the resource is generated, this will typically be | 
 | #         specified relative to `$target_gen_dir`. | 
 | # | 
 | #       dest (required) | 
 | #         [path] Location the resource will be placed within `data/`. | 
 | # | 
 | #   extra (optional) | 
 | #     [list of paths] Manifest files containing extra entries, which | 
 | #     might be generated by the build. | 
 | # | 
 | #   deps (optional) | 
 | #   public_deps (optional) | 
 | #   data_deps (optional) | 
 | #   testonly (optional) | 
 | #     Usual GN meanings. | 
 | # | 
 | template("package") { | 
 |   if (current_toolchain == target_toolchain) { | 
 |     pkg_target_name = target_name | 
 |     pkg = { | 
 |       package_version = "0"  # placeholder | 
 |       forward_variables_from( | 
 |           invoker, | 
 |           [ | 
 |             "binaries", | 
 |             "data_deps", | 
 |             "deprecated_system_image",  # TODO(bwb) remove after soft-transition | 
 |             "__deprecated_system_image", | 
 |             "deps", | 
 |             "public_deps", | 
 |             "drivers", | 
 |             "extra", | 
 |             "libraries", | 
 |             "loadable_modules", | 
 |             "meta", | 
 |             "package_name", | 
 |             "resources", | 
 |             "visibility", | 
 |             "tests", | 
 |             "testonly", | 
 |           ]) | 
 |       if (!defined(binaries)) { | 
 |         binaries = [] | 
 |       } | 
 |       if (!defined(__deprecated_system_image) && | 
 |           !defined(deprecated_system_image)) { | 
 |         __deprecated_system_image = false | 
 |       } | 
 |       if (defined(deprecated_system_image)) { | 
 |         __deprecated_system_image = deprecated_system_image | 
 |       } | 
 |       if (!defined(deps)) { | 
 |         deps = [] | 
 |       } | 
 |       if (!defined(data_deps)) { | 
 |         data_deps = [] | 
 |       } | 
 |       if (!defined(public_deps)) { | 
 |         public_deps = [] | 
 |       } | 
 |       if (!defined(extra)) { | 
 |         extra = [] | 
 |       } | 
 |       if (!defined(drivers)) { | 
 |         drivers = [] | 
 |       } | 
 |       if (!defined(loadable_modules)) { | 
 |         loadable_modules = [] | 
 |       } | 
 |       if (!defined(libraries)) { | 
 |         libraries = [] | 
 |       } | 
 |       if (!defined(meta)) { | 
 |         meta = [] | 
 |       } | 
 |       if (!defined(package_name)) { | 
 |         package_name = pkg_target_name | 
 |       } | 
 |       if (!defined(resources)) { | 
 |         resources = [] | 
 |       } | 
 |       if (!defined(tests)) { | 
 |         tests = [] | 
 |       } | 
 |     } | 
 |  | 
 |     assert(pkg.package_name != "tests" && pkg.package_name != "app" && | 
 |                pkg.package_name != "bin" && pkg.package_name != "pkg" && | 
 |                pkg.package_name != "lib" && pkg.package_name != "package" && | 
 |                pkg.package_name != "binary" && pkg.package_name != "service" && | 
 |                pkg.package_name != "svc" && pkg.package_name != "component", | 
 |            "${pkg.package_name} is too generic a name for a package") | 
 |  | 
 |     pkg_label = get_label_info(":$pkg_target_name", "label_no_toolchain") | 
 |     pkg_desc = "Package ${pkg_label} (${pkg.package_name}):" | 
 |     if (pkg.__deprecated_system_image) { | 
 |       assert( | 
 |           pkg.meta == [], | 
 |           "$pkg_desc __deprecated_system_image (likely from driver_package) incompatible with meta") | 
 |  | 
 |       # No package should contribute to /system/bin. | 
 |       assert(pkg.binaries == [], | 
 |              "no new packages are allowed to add binaries to /system/bin") | 
 |  | 
 |       assert(pkg.tests == [], "tests are not allowed in /system") | 
 |     } else { | 
 |       if (!defined(pkg.testonly) || !pkg.testonly) { | 
 |         assert(pkg.drivers == [], | 
 |                "$pkg_desc drivers requires __deprecated_system_image") | 
 |       } | 
 |       assert(pkg.libraries == [], | 
 |              "$pkg_desc libraries requires __deprecated_system_image") | 
 |     } | 
 |  | 
 |     formatted_manifest = [] | 
 |     meta_deps = [] | 
 |     foreach(meta, pkg.meta) { | 
 |       manifest_target = pkg_target_name + "_" + get_path_info(meta.dest, "file") | 
 |       manifest_output = [] | 
 |  | 
 |       if (get_path_info(meta.dest, "extension") == "cmx") { | 
 |         cmx(manifest_target) { | 
 |           manifest = meta.path | 
 |           forward_variables_from(pkg, | 
 |                                  [ | 
 |                                    "deps", | 
 |                                    "testonly", | 
 |                                  ]) | 
 |         } | 
 |  | 
 |         component_index_target = "${manifest_target}_component_index" | 
 |         add_to_component_index(component_index_target) { | 
 |           package_name = pkg.package_name | 
 |           manifest = "meta/${meta.dest}" | 
 |         } | 
 |         pkg.deps += [ ":$component_index_target" ] | 
 |  | 
 |         manifest_output = get_target_outputs(":$manifest_target") | 
 |         meta.path = manifest_output[0] | 
 |         pkg.deps += [ ":$manifest_target" ] | 
 |       } else if (get_path_info(meta.path, "extension") == "cml") { | 
 |         cm(manifest_target) { | 
 |           manifest = meta.path | 
 |           forward_variables_from(pkg, | 
 |                                  [ | 
 |                                    "deps", | 
 |                                    "testonly", | 
 |                                  ]) | 
 |         } | 
 |  | 
 |         manifest_output = get_target_outputs(":$manifest_target") | 
 |         meta.path = manifest_output[0] | 
 |         pkg.deps += [ ":$manifest_target" ] | 
 |       } else { | 
 |         manifest_target = false | 
 |       } | 
 |  | 
 |       formatted_manifest += [ meta ] | 
 |  | 
 |       resource_target = | 
 |           pkg_target_name + "_resource_" + get_path_info(meta.dest, "file") | 
 |       resource(resource_target) { | 
 |         forward_variables_from(pkg, [ "testonly" ]) | 
 |         if (manifest_target != false) { | 
 |           deps = [ ":$manifest_target" ] | 
 |         } | 
 |         sources = [ meta.path ] | 
 |         outputs = [ "meta/${meta.dest}" ] | 
 |       } | 
 |       meta_deps += [ ":$resource_target" ] | 
 |     } | 
 |  | 
 |     # Collect the package's primary manifest.  For a system_image package, | 
 |     # this is its contributions to the /system manifest.  For an isolated | 
 |     # package, this is the manifest for the package's `pkg/` filesystem. | 
 |     pkg_manifest = [] | 
 |     foreach(meta, formatted_manifest) { | 
 |       pkg_manifest += [ | 
 |         { | 
 |           dest = "meta/${meta.dest}" | 
 |           source = rebase_path(meta.path) | 
 |         }, | 
 |       ] | 
 |     } | 
 |     shell_binaries = [] | 
 |     foreach(binary, pkg.binaries) { | 
 |       if (defined(binary.dest)) { | 
 |         dest = binary.dest | 
 |       } else { | 
 |         dest = binary.name | 
 |       } | 
 |       dest = "bin/${dest}" | 
 |  | 
 |       if (defined(binary.shell) && binary.shell) { | 
 |         shellfile = target_gen_dir + "/" + dest + ".shell" | 
 |         write_file( | 
 |             shellfile, | 
 |             [ "#!resolve fuchsia-pkg://fuchsia.com/${pkg.package_name}#${dest}" ]) | 
 |         shell_binaries += | 
 |             [ "${dest}=" + rebase_path(shellfile, root_build_dir) ] | 
 |  | 
 |         # The shell environment is not intended for production use. | 
 |         pkg.deps += [ "//build/validate:non_production_tag" ] | 
 |       } | 
 |  | 
 |       pkg_manifest += [ | 
 |         { | 
 |           dest = dest | 
 |  | 
 |           if (defined(binary.source)) { | 
 |             source = binary.source | 
 |           } else { | 
 |             source = binary.name | 
 |           } | 
 |           source = rebase_path(source, "", root_out_dir) | 
 |         }, | 
 |       ] | 
 |     } | 
 |  | 
 |     foreach(test, pkg.tests) { | 
 |       assert(!defined(test.tags), | 
 |              "tags are only valid within an environment scope") | 
 |  | 
 |       # It's a common mistake to specify "tags" in the scope of the test | 
 |       # instead of in an environment scope. | 
 |       is_disabled = defined(test.disabled) && test.disabled | 
 |  | 
 |       if (defined(test.dest)) { | 
 |         dest = test.dest | 
 |       } else { | 
 |         dest = test.name | 
 |       } | 
 |       if (is_disabled) { | 
 |         dest = "disabled/${dest}" | 
 |       } | 
 |  | 
 |       if (bootfs_only) { | 
 |         dest = "test/$dest" | 
 |         path = "/boot/$dest" | 
 |       } else { | 
 |         url = "fuchsia-pkg://fuchsia.com" | 
 |         dest = "test/$dest" | 
 |         if (pkg.__deprecated_system_image) { | 
 |           url_pkg_name = "system" | 
 |           path = "/system/$dest" | 
 |         } else { | 
 |           url_pkg_name = pkg.package_name | 
 |           path = "" | 
 |         } | 
 |         url += "/${url_pkg_name}" | 
 |       } | 
 |  | 
 |       dest_name = get_path_info(dest, "name") | 
 |       not_needed([ "dest_name" ]) | 
 |  | 
 |       # Check that all tests are components with cmx/cm files at the expected path. | 
 |       if (!pkg.__deprecated_system_image && !bootfs_only && !is_disabled && | 
 |           (!defined(require_bare_tests_allowlist) || | 
 |            !require_bare_tests_allowlist)) { | 
 |         require_bare_tests_allowlist = true | 
 |         url_resource_path = "" | 
 |         foreach(meta, pkg.meta) { | 
 |           extension = get_path_info(meta.dest, "extension") | 
 |           if (extension == "cmx" || extension == "cm") { | 
 |             meta_name = get_path_info(meta.dest, "name") | 
 |             if (dest_name == meta_name) { | 
 |               require_bare_tests_allowlist = false | 
 |               url_resource_path = "#meta/${meta.dest}" | 
 |             } | 
 |           } | 
 |         } | 
 |         url += url_resource_path | 
 |       } | 
 |  | 
 |       if (!is_disabled) { | 
 |         test_spec_name = "${pkg.package_name}_${dest}_test_spec" | 
 |         pkg.deps += [ ":$test_spec_name" ] | 
 |  | 
 |         test_spec(test_spec_name) { | 
 |           target = ":${invoker.target_name}" | 
 |           path = path | 
 |           if (!bootfs_only) { | 
 |             package_url = url | 
 |             forward_variables_from(test, | 
 |                                    [ | 
 |                                      "log_settings", | 
 |                                      "parallel", | 
 |                                    ]) | 
 |           } | 
 |           forward_variables_from(test, [ "environments" ]) | 
 |         } | 
 |       } else { | 
 |         not_needed([ | 
 |                      "path", | 
 |                      "url", | 
 |                    ]) | 
 |       } | 
 |  | 
 |       pkg_manifest += [ | 
 |         { | 
 |           dest = dest | 
 |           source = rebase_path(test.name, "", root_out_dir) | 
 |         }, | 
 |       ] | 
 |     } | 
 |  | 
 |     foreach(module, pkg.loadable_modules) { | 
 |       pkg_manifest += [ | 
 |         { | 
 |           if (defined(module.dest)) { | 
 |             dest = module.dest | 
 |           } else { | 
 |             dest = "lib" | 
 |           } | 
 |           dest += "/${module.name}" | 
 |           source = rebase_path(module.name, "", root_out_dir) | 
 |         }, | 
 |       ] | 
 |     } | 
 |     foreach(driver, pkg.drivers) { | 
 |       pkg_manifest += [ | 
 |         { | 
 |           dest = "driver/${driver.name}" | 
 |           source = rebase_path(driver.name, "", root_out_dir) | 
 |         }, | 
 |       ] | 
 |     } | 
 |  | 
 |     resources_deps = [] | 
 |  | 
 |     foreach(resource, pkg.resources) { | 
 |       resource_entry = { | 
 |       } | 
 |       resource_entry = { | 
 |         dest = "data/${resource.dest}" | 
 |         source = rebase_path(resource.path) | 
 |       } | 
 |       pkg_manifest += [ resource_entry ] | 
 |  | 
 |       resource_name = string_replace(resource.dest, "/", "_") | 
 |       resource_target = "$target_name.resource.resource.$resource_name" | 
 |       resource(resource_target) { | 
 |         forward_variables_from(pkg, [ "testonly" ]) | 
 |         deps = pkg.deps | 
 |         sources = [ resource_entry.source ] | 
 |         outputs = [ resource_entry.dest ] | 
 |       } | 
 |       resources_deps += [ ":$resource_target" ] | 
 |     } | 
 |  | 
 |     library_deps = [] | 
 |  | 
 |     # TODO(mcgrathr): Remove this when we can!  Packages installing | 
 |     # libraries in the system image is all kinds of wrong. | 
 |     foreach(library, pkg.libraries) { | 
 |       library_entry = { | 
 |       } | 
 |       library_entry = { | 
 |         if (defined(library.dest)) { | 
 |           dest = library.dest | 
 |         } else { | 
 |           dest = library.name | 
 |         } | 
 |         dest = "lib/${dest}" | 
 |         if (defined(library.source)) { | 
 |           source = library.source | 
 |         } else { | 
 |           # TODO(mcgrathr): This breaks when everything is a variant so | 
 |           # that only this here is using the non-variant shlib build. | 
 |           source = get_label_info(shlib_toolchain, "name") | 
 |           source += "/${library.name}" | 
 |         } | 
 |         source = rebase_path(source, "", root_out_dir) | 
 |       } | 
 |       pkg_manifest += [ library_entry ] | 
 |  | 
 |       resource_target = "$target_name.library.resource.${library.name}" | 
 |       resource(resource_target) { | 
 |         forward_variables_from(pkg, [ "testonly" ]) | 
 |         deps = pkg.deps | 
 |         sources = [ library_entry.source ] | 
 |         outputs = [ library_entry.dest ] | 
 |       } | 
 |       library_deps += [ ":$resource_target" ] | 
 |     } | 
 |  | 
 |     # Collect all the arguments describing input manifest files | 
 |     # and all the entries we've just synthesized in `pkg_manifest`. | 
 |     manifest_sources = pkg.extra | 
 |     manifest_args = [] | 
 |     foreach(manifest_file, pkg.extra) { | 
 |       manifest_file = rebase_path(manifest_file, root_build_dir) | 
 |       manifest_args += [ "--manifest=${manifest_file}" ] | 
 |     } | 
 |     manifest_args += [ "--entry-manifest=${pkg_label}" ] | 
 |     foreach(entry, pkg_manifest) { | 
 |       manifest_sources += [ entry.source ] | 
 |       manifest_args += [ "--entry=${entry.dest}=${entry.source}" ] | 
 |     } | 
 |  | 
 |     pkg.metadata = { | 
 |       if (defined(invoker.metadata)) { | 
 |         forward_variables_from(invoker.metadata, "*") | 
 |       } | 
 |       shell_binary_entries = shell_binaries | 
 |     } | 
 |  | 
 |     if (defined(pkg.visibility)) { | 
 |       pkg.visibility += [ | 
 |         ":$target_name", | 
 |  | 
 |         # TODO(raggi): tighten build/images visibility once we've | 
 |         # finished doing large scale cleanups. | 
 |         "//build/images:*", | 
 |         "//build/packages/*", | 
 |         "//bundles/*", | 
 |         "//garnet/packages/*", | 
 |         "//src/modular/bundles/*", | 
 |         "//topaz/packages/*", | 
 |         "//vendor/*", | 
 |       ] | 
 |     } | 
 |  | 
 |     # An empty package() target doesn't actually generate a package at all. | 
 |     # Conveniently, an empty system_image package has exactly that effect. | 
 |     if (manifest_sources == []) { | 
 |       pkg.__deprecated_system_image = true | 
 |     } | 
 |  | 
 |     if (pkg.__deprecated_system_image || bootfs_only) { | 
 |       system_rsp_label = pkg_target_name + ".system.rsp" | 
 |  | 
 |       # System image packages just donate manifest arguments | 
 |       generate_response_file(system_rsp_label) { | 
 |         forward_variables_from(pkg, | 
 |                                [ | 
 |                                  "testonly", | 
 |                                  "visibility", | 
 |                                ]) | 
 |         deps = pkg.deps | 
 |         data_deps = pkg.data_deps | 
 |         public_deps = pkg.public_deps | 
 |         output_name = "${pkg_target_name}.system.rsp" | 
 |         response_file_contents = manifest_args | 
 |         metadata = { | 
 |           forward_variables_from(pkg.metadata, "*") | 
 |  | 
 |           system_image_rsps = [ "@" + | 
 |                                 rebase_path(target_out_dir + "/" + output_name, | 
 |                                             root_build_dir) ] | 
 |  | 
 |           system_image_barrier = [] | 
 |         } | 
 |       } | 
 |       not_needed([ "component_indices" ]) | 
 |     } | 
 |  | 
 |     # Synthesize the meta/package file. | 
 |     pkg_meta_generated = "${pkg_target_name}_meta_package.json" | 
 |     pkg_meta_output = "$target_out_dir/${pkg_target_name}_meta_package.json" | 
 |     generated_file(pkg_meta_generated) { | 
 |       contents = "{\"name\":\"${pkg.package_name}\",\"version\":\"${pkg.package_version}\"}" | 
 |       outputs = [ pkg_meta_output ] | 
 |       output_conversion = "string" | 
 |     } | 
 |  | 
 |     # Fuchsia package aggregates a manifest from its arguments and builds a | 
 |     # metadata archive. | 
 |     manifest = "${pkg_target_name}.manifest" | 
 |     generate_manifest(manifest) { | 
 |       forward_variables_from(pkg, [ "testonly" ]) | 
 |       visibility = [ ":*" ] | 
 |       sources = manifest_sources + [ pkg_meta_output ] | 
 |       args = | 
 |           manifest_args + [ "--entry=meta/package=" + | 
 |                             rebase_path(pkg_meta_output, "", target_out_dir) ] | 
 |       deps = pkg.deps + [ ":$pkg_meta_generated" ] | 
 |       public_deps = pkg.public_deps | 
 |     } | 
 |     manifest_file = get_target_outputs(":$manifest") | 
 |     manifest_file = manifest_file[0] | 
 |  | 
 |     # Validate component manifests against package manifest | 
 |     foreach(meta, pkg.meta) { | 
 |       validate_target = pkg_target_name + "_validate_manifests_" + | 
 |                         get_path_info(meta.dest, "file") | 
 |       validate_component_manifest_references(validate_target) { | 
 |         forward_variables_from(pkg, | 
 |                                [ | 
 |                                  "deps", | 
 |                                  "testonly", | 
 |                                ]) | 
 |         visibility = [ ":*" ] | 
 |         deps += [ ":$manifest" ] | 
 |         package_manifest = manifest_file | 
 |         component_manifest = meta.path | 
 |       } | 
 |       pkg.deps += [ ":$validate_target" ] | 
 |     } | 
 |  | 
 |     # Next generate a sealed package file. | 
 |     pm_build(pkg_target_name) { | 
 |       forward_variables_from(pkg, [ "testonly" ]) | 
 |       if (defined(pkg.visibility)) { | 
 |         visibility = pkg.visibility | 
 |       } | 
 |       package_name = pkg.package_name | 
 |       manifest = ":$manifest" | 
 |       metadata = { | 
 |         forward_variables_from(pkg.metadata, "*") | 
 |       } | 
 |  | 
 |       deps = pkg.deps + meta_deps + resources_deps + library_deps | 
 |       data_deps = pkg.data_deps | 
 |       public_deps = pkg.public_deps | 
 |  | 
 |       if (pkg.__deprecated_system_image || bootfs_only) { | 
 |         public_deps += [ ":" + system_rsp_label ] | 
 |       } | 
 |  | 
 |       if (!bootfs_only) { | 
 |         # Prevent the contents of this package from getting picked up in a zbi. | 
 |         # See fxb/45680 for more information. | 
 |         metadata.distribution_entries_barrier = [] | 
 |       } | 
 |  | 
 |       # Add the dep on the allowlist here rather than in pkg.deps earlier so that we can allow | 
 |       # specific targets by the package target's name using visibility. | 
 |       if (defined(require_bare_tests_allowlist) && | 
 |           require_bare_tests_allowlist) { | 
 |         deps += [ "//build:deprecated_bare_tests_allowlist" ] | 
 |       } | 
 |     } | 
 |   } else { | 
 |     # A reference from a different toolchain, e.g. a variant toolchain, is | 
 |     # just an indirect way to get the package into the system images. | 
 |     # Redirect it as data_deps on the $target_toolchain package.  This | 
 |     # really ought to be a pure redirect, i.e. public_deps.  But using | 
 |     # data_deps here avoids problems in case some dependency on a package() | 
 |     # target is not in data_deps as it (almost surely) should be. | 
 |     group(target_name) { | 
 |       forward_variables_from(invoker, | 
 |                              [ | 
 |                                "visibility", | 
 |                                "testonly", | 
 |                              ]) | 
 |       data_deps = [ ":$target_name($target_toolchain)" ] | 
 |     } | 
 |  | 
 |     # Suppress unused variable warnings. | 
 |     not_needed(invoker, "*") | 
 |   } | 
 | } |