| # Copyright 2023 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/config/fuchsia/platform_version.gni") |
| import("//build/sdk/sdk_atom.gni") |
| import("//build/sdk/sdk_noop_atom.gni") |
| import("//tools/cmc/build/expect_includes.gni") |
| |
| # Defines an in-tree package for distribution in the SDK, landing |
| # the end package manifest at |
| # `sdk://packages/{arch}/release/${distribution_name}/package_manifest.json`. |
| # |
| # Example: |
| # ``` |
| # fuchsia_package("my-package") { |
| # deps = [ |
| # ":main_component", |
| # ] |
| # } |
| # |
| # sdk_fuchsia_package("my-sdk-package") { |
| # distribution_name = "my-package" |
| # package_label = ":my-package" |
| # category = "public" |
| # expected_files_exact = [ |
| # "relative/path/to/file_a", |
| # ] |
| # } |
| # ``` |
| # |
| # Parameters |
| # |
| # package_label |
| # The fuchsia_package to distribute. Must point to a fuchsia_package() target, or |
| # one of its wrappers (e.g. fuchsia_test_package()). |
| # Type: label. |
| # |
| # distribution_name |
| # Distribution name of the package. The package manifest will be edited to use this |
| # name. |
| # Type: string. |
| # |
| # category |
| # The SDK category for the package. Must be either "public" or "partner". |
| # See //build/sdk/sdk_atom.gni for more. |
| # Type: string. |
| # |
| # api_level (optional) |
| # API level at which the package was added to the SDK. API level defined at: |
| # https://fuchsia.dev/fuchsia-src/contribute/governance/rfcs/0002_platform_versioning#sdk |
| # Default is current development API level. |
| # Type: unsigned integer. |
| # |
| # expected_files_exact (optional) |
| # List of paths, relative to the package's root, for all files that |
| # participate in that package's content checklist file. Their content hash will be |
| # compared to the ones in |
| # //sdk/packages/${distribution_name}/${target_cpu}/release/content_checklist.api. |
| # Any paths specified in this list that are not found, or do not have hashes that match |
| # their golden content checklist file equivalent, will cause an error during checklist |
| # file generation. |
| # Type: list of relative package paths. |
| # |
| # expected_files_present (optional) |
| # List of paths, relative to the package's root, for all files that |
| # do not participate in that package's content checklist file. Their content |
| # does not matter for verification, but these paths must appear in |
| # the golden |
| # //sdk/packages/${distribution_name}/${target_cpu}/release/content_checklist.api file |
| # and in the same order. |
| # Any paths specified in this list that are not found in the specified |
| # manifest will cause an error during checklist file generation. |
| # Type: list of relative package paths. |
| # |
| template("sdk_fuchsia_package") { |
| if (defined(invoker.api_level)) { |
| assert(invoker.api_level == platform_version.in_development_api_level, |
| "Only the current development API level is supported.") |
| api_level = invoker.api_level |
| } else { |
| api_level = platform_version.in_development_api_level |
| } |
| |
| # Determine whether this package can be built for the current API level. |
| if (override_target_api_level != -1) { |
| current_api_level = override_target_api_level |
| } else { |
| current_api_level = platform_version.in_development_api_level |
| } |
| current_api_level_supported = current_api_level >= api_level |
| |
| if (current_api_level_supported && current_toolchain == target_toolchain) { |
| assert(defined(invoker.package_label), |
| "Must define a package to distribute.") |
| assert(defined(invoker.distribution_name), |
| "Must define a distribution name for this package.") |
| assert(defined(invoker.category), |
| "Must define an SDK category for this package.") |
| valid_categories = [ |
| "excluded", |
| "experimental", |
| "internal", |
| "cts", |
| "partner_internal", |
| "partner", |
| "public", |
| ] |
| assert( |
| valid_categories + [ invoker.category ] - [ invoker.category ] != |
| valid_categories, |
| "Invalid SDK category ${invoker.category}, must be one of ${valid_categories}") |
| |
| if (defined(invoker.expected_files_exact)) { |
| expected_files_exact = invoker.expected_files_exact |
| } else { |
| expected_files_exact = [] |
| } |
| if (defined(invoker.expected_files_present)) { |
| expected_files_present = invoker.expected_files_present |
| } else { |
| expected_files_present = [] |
| } |
| |
| # Label of package to be included in the SDK. Used for tracking `package_manifest.json` |
| _full_package_label = |
| get_label_info(invoker.package_label, "label_no_toolchain") |
| package_manifest_file = |
| get_label_info(_full_package_label, "target_out_dir") + "/" + |
| get_label_info(_full_package_label, "name") + "/package_manifest.json" |
| |
| # End output directory, different for each arch and API level. |
| if (override_target_api_level == -1) { |
| base = "$target_cpu" |
| } else { |
| base = "${target_cpu}-api-${override_target_api_level}" |
| } |
| |
| _sdk_package_dir = "${target_out_dir}/sdk_packages/${base}/release" |
| _distribution_name = invoker.distribution_name |
| |
| # Note: Golden file does not support multiple API level currently. |
| golden_content_checklist_file = |
| "//sdk/packages/${_distribution_name}/release/content_checklist.api" |
| computed_content_checklist_file = |
| "${_sdk_package_dir}/content_checklist.api" |
| _content_checklist_target = "${target_name}.content_checklist" |
| _content_checklist_depfile = |
| "${target_gen_dir}/${_content_checklist_target}.d" |
| |
| _ffx_package_bin = "${host_out_dir}/ffx-package_unversioned" |
| _ffx_package_dep = |
| "//src/developer/ffx/plugins/package:ffx_package_tool($host_toolchain)" |
| |
| _far_tool_dep = "//src/sys/pkg/bin/far:host" |
| _far_tool_bin = "$root_build_dir/host-tools/far" |
| |
| # Generates content checklist file using input package manifest, and runs checks |
| # against golden. See |
| # `//build/packages/generate_sdk_package_content_checklist.py` for more. |
| action(_content_checklist_target) { |
| forward_variables_from(invoker, [ "testonly" ]) |
| |
| script = "//build/packages/generate_sdk_package_content_checklist.py" |
| |
| inputs = [ |
| package_manifest_file, |
| _ffx_package_bin, |
| _far_tool_bin, |
| ] |
| outputs = [ computed_content_checklist_file ] |
| deps = [ |
| _far_tool_dep, |
| _ffx_package_dep, |
| _full_package_label, |
| ] |
| depfile = _content_checklist_depfile |
| |
| args = [ |
| "--manifest", |
| rebase_path(package_manifest_file, root_build_dir), |
| "--output", |
| rebase_path(computed_content_checklist_file, root_build_dir), |
| "--reference", |
| rebase_path("${golden_content_checklist_file}", root_build_dir), |
| "--ffx-bin", |
| rebase_path(_ffx_package_bin, root_build_dir), |
| "--far-bin", |
| rebase_path(_far_tool_bin, root_build_dir), |
| "--depfile", |
| rebase_path(depfile, root_build_dir), |
| ] |
| |
| # FIXME(https://fxbug.dev/132644) |
| if (is_coverage) { |
| args += [ "--is-coverage" ] |
| } |
| |
| foreach(exact_file, expected_files_exact) { |
| args += [ |
| "--expected-files-exact", |
| exact_file, |
| ] |
| } |
| foreach(present_file, expected_files_present) { |
| args += [ |
| "--expected-files-present", |
| present_file, |
| ] |
| } |
| } |
| |
| _sdk_package_file_list = "${_sdk_package_dir}/file_list.fini" |
| _sdk_package_metadata = "${_sdk_package_dir}/metadata" |
| _sdk_manifest_target = "${target_name}.sdk_manifest" |
| _sdk_package_depfile = "${target_gen_dir}/${_sdk_manifest_target}.d" |
| |
| # Generates SDK primitives, including `file_list`, `metadata`, and |
| # package manifests (both target package and subpackages) with |
| # files structured relative to SDK directories. See |
| # `//build/packages/generate_sdk_package_manifest.py` for more. |
| action(_sdk_manifest_target) { |
| forward_variables_from(invoker, [ "testonly" ]) |
| |
| script = "//build/packages/generate_sdk_package_manifest.py" |
| |
| inputs = [ |
| package_manifest_file, |
| computed_content_checklist_file, |
| ] |
| outputs = [ |
| _sdk_package_file_list, |
| _sdk_package_metadata, |
| ] |
| deps = [ |
| ":${_content_checklist_target}", |
| _full_package_label, |
| ] |
| depfile = _sdk_package_depfile |
| |
| args = [ |
| "--manifest", |
| rebase_path(package_manifest_file, root_build_dir), |
| "--sdk-package-content-checklist-path", |
| rebase_path(computed_content_checklist_file, root_build_dir), |
| "--output", |
| rebase_path(_sdk_package_dir, root_build_dir), |
| "--api-level", |
| "${api_level}", |
| "--target-cpu", |
| "${target_cpu}", |
| "--depfile", |
| rebase_path(depfile, root_build_dir), |
| "--distribution-name", |
| _distribution_name, |
| ] |
| } |
| |
| sdk_atom(target_name) { |
| forward_variables_from(invoker, [ "testonly" ]) |
| |
| id = "sdk://packages/${_distribution_name}" |
| category = invoker.category |
| |
| meta = { |
| schema = "package" |
| dest = "packages/${_distribution_name}/meta.json" |
| source = "${_sdk_package_metadata}" |
| } |
| |
| file_list = _sdk_package_file_list |
| |
| non_sdk_deps = [ ":${_sdk_manifest_target}" ] |
| |
| # Barrier enforced to prevent assembly from adding to `base` set, |
| # keeping this target as an SDK-only addition. |
| metadata = { |
| package_barrier = [] |
| } |
| } |
| } else if (!current_api_level_supported) { |
| # Current API level is not supported, so create an empty atom. |
| sdk_noop_atom(target_name) { |
| forward_variables_from(invoker, [ "testonly" ]) |
| |
| id = "sdk://packages/${invoker.distribution_name}" |
| category = invoker.category |
| type = "fuchsia_package" |
| } |
| |
| # Suppress unused variable warnings. |
| not_needed(invoker, "*") |
| } else { |
| # Fuchsia SDK 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 sdk_fuchsia_package expand to nothing. |
| group(target_name) { |
| forward_variables_from(invoker, |
| [ |
| "testonly", |
| "visibility", |
| ]) |
| } |
| |
| # Suppress unused variable warnings. |
| not_needed(invoker, "*") |
| } |
| } |