| # Copyright 2018 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/compiled_action.gni") |
| import("//build/json/validate_json.gni") |
| import("//build/python/python_action.gni") |
| import("config.gni") |
| import("meta/version.gni") |
| import("sdk_molecule.gni") |
| |
| # Prepare a collection of elements to be published in an IDK. |
| # |
| # This creates the $BUILD_DIR/sdk/exported/{sdk_name}/ directory, which will |
| # follow the standard IDK layout, including a top-level meta/manifest.json |
| # file describing all atoms in the collection using the standard IDK schema. |
| # |
| # It also writes the $BUILD_DIR/sdk/manifest/{sdk_name} file, as an internal |
| # SDK manifest describing all atoms as well. Note that this format is internal |
| # to the build system, and should not be used outside of it (though it is |
| # ok for `ffx` to use that from a Fuchsia checkout). |
| # |
| # If `generate_archive` is true, this will also create a compressed tarball |
| # under $BUILD_DIR/sdk/archive/{sdk_name}.tar.gz, which will store the same |
| # files as the exported directory described above. |
| # |
| # This last feature is only provided for legacy reasons and will be removed |
| # soon. IDK archives should be generated with idk_archive() instead. |
| # |
| # Parameters |
| # |
| # id (optional) |
| # An opaque identifier for the SDK. |
| # Defaults to the empty string. |
| # |
| # category (required) |
| # Describes the minimum category that atoms in this SDK must have. |
| # See //build/sdk/sdk_atom.gni for possible values. |
| # |
| # generate_archive (optional) |
| # Boolean. Set to true to generate a compressed archive for this collection. |
| # This feature is deprecated and will be removed when all clients |
| # will rely on IDK archives instead. Defaults to false. |
| # |
| # deps |
| # A list of sdk_atom() and sdk_molecule() targets that will be walked to |
| # collect all SDK atom dependencies for this collection. |
| # |
| # testonly |
| # Usual GN meaning. |
| # |
| template("sdk_collection") { |
| assert(defined(invoker.category), "Must define an SDK category") |
| |
| # Compute target and host triples, which will be written to the |
| # top-level meta/manifest.json file for this collection. |
| target_triple = target_cpu |
| if (host_cpu == "x64") { |
| host_triple_cpu = "x86_64" |
| } else if (host_cpu == "arm64") { |
| host_triple_cpu = "aarch64" |
| } else { |
| assert(false, "Unrecognized host CPU: $host_cpu") |
| } |
| if (host_os == "linux") { |
| host_triple_os = "linux-gnu" |
| } else if (host_os == "mac") { |
| host_triple_os = "apple-darwin" |
| } else if (host_os == "fuchsia") { |
| host_triple_os = "fuchsia" |
| } else { |
| assert(false, "Unrecognized host OS: $host_os") |
| } |
| host_triple = "$host_triple_cpu-$host_triple_os" |
| |
| # The name used for this collection's output directory and archives. |
| sdk_name = target_name |
| |
| # Labels and file paths for all targets generated by this template. |
| labels = { |
| export = "${target_name}_export" |
| final_archive = "${target_name}_archive" |
| final_manifest = "${target_name}_final_manifest" |
| local_archive = "${target_name}_local_archive" |
| local_manifest = "${target_name}_molecule" |
| main = target_name |
| sdk_meta = "${target_name}_sdk_meta" |
| tarmaker_manifest = "${target_name}_tarmaker_manifest" |
| verify_manifest = "${target_name}_verify_manifest" |
| verify_sdk_meta = "${target_name}_verify_sdk_meta" |
| } |
| |
| files = { |
| final_archive = "${root_out_dir}/sdk/archive/${sdk_name}.tar.gz" |
| final_manifest = "$root_out_dir/sdk/manifest/$sdk_name" |
| local_archive = "$target_gen_dir/$target_name.tar.gz" |
| local_manifest = "$target_gen_dir/${labels.main}.sdk" |
| sdk_meta = "$target_gen_dir/$sdk_name.sdk_meta.json" |
| tarmaker_manifest = "$target_gen_dir/${sdk_name}.tarmaker_manifest" |
| } |
| |
| # Generates an internal molecule target, which creates an internal SDK |
| # manifest file describing all atoms in it. |
| sdk_molecule(labels.local_manifest) { |
| # Do not expose this molecule to other labels. Depending directly on the |
| # contents of an SDK foregoes API verification, which is not desirable. |
| visibility = [ ":*" ] |
| |
| # Ensure the internal manifest is named foo.sdk instead of foo_molecule.sdk |
| output_name = labels.main |
| |
| forward_variables_from(invoker, |
| [ |
| "assert_no_deps", |
| "category", |
| "deps", |
| "testonly", |
| ]) |
| |
| if (!defined(deps)) { |
| deps = [] |
| } |
| deps += [ "//build/sdk/meta" ] |
| } |
| |
| # Copies the manifest to a central location + verify the collection API if |
| # needed. |
| copy(labels.final_manifest) { |
| forward_variables_from(invoker, [ "testonly" ]) |
| |
| sources = [ files.local_manifest ] |
| |
| outputs = [ files.final_manifest ] |
| |
| deps = [ ":${labels.local_manifest}" ] |
| |
| metadata = { |
| # Used by distribution_manifest() template. Ensure that dependencies are not |
| # installed into Fuchsia packages that depend on the current target. |
| distribution_entries_barrier = [] |
| } |
| } |
| |
| # Verifies that the manifest is valid. |
| validate_json(labels.verify_manifest) { |
| forward_variables_from(invoker, [ "testonly" ]) |
| |
| data = files.final_manifest |
| |
| schema = "//build/sdk/manifest_schema.json" |
| |
| deps = [ ":${labels.final_manifest}" ] |
| } |
| |
| # Generates a metadata file (meta/manifest.json) describing the various |
| # parts of the SDK collection. |
| python_action(labels.sdk_meta) { |
| forward_variables_from(invoker, [ "testonly" ]) |
| |
| binary_label = "//build/sdk:generate_meta" |
| |
| inputs = [ files.local_manifest ] |
| |
| outputs = [ files.sdk_meta ] |
| |
| args = [ |
| "--manifest", |
| rebase_path(files.local_manifest, root_build_dir), |
| "--meta", |
| rebase_path(files.sdk_meta, root_build_dir), |
| "--target-arch", |
| target_triple, |
| "--host-arch", |
| host_triple, |
| "--schema-version", |
| sdk_metadata_schema_version, |
| ] |
| |
| if (defined(invoker.id) && invoker.id != "") { |
| args += [ |
| "--id", |
| invoker.id, |
| ] |
| } |
| |
| public_deps = [ ":${labels.local_manifest}" ] |
| } |
| |
| # Verifies that the metadata manifest is valid. |
| validate_json(labels.verify_sdk_meta) { |
| forward_variables_from(invoker, [ "testonly" ]) |
| |
| data = files.sdk_meta |
| |
| schema = "//build/sdk/meta/manifest.json" |
| sources = [ |
| # This file is imported by all schemas. |
| "//build/sdk/meta/common.json", |
| ] |
| |
| public_deps = [ ":${labels.sdk_meta}" ] |
| } |
| |
| additional_archive_files = [ |
| { |
| source = files.sdk_meta |
| dest = "meta/manifest.json" |
| deps = [ ":${labels.sdk_meta}" ] |
| }, |
| ] |
| |
| # Generate an input tarmaker manifest that will be used to create |
| # a tarball archive from the content listed in final_manifest. |
| python_action(labels.tarmaker_manifest) { |
| forward_variables_from(invoker, [ "testonly" ]) |
| |
| binary_label = "//build/sdk:generate_archive_manifest" |
| |
| inputs = [ files.final_manifest ] |
| |
| outputs = [ files.tarmaker_manifest ] |
| |
| args = [ |
| "--manifest", |
| rebase_path(inputs[0], root_build_dir), |
| "--output", |
| rebase_path(outputs[0], root_build_dir), |
| ] |
| |
| deps = [ ":${labels.final_manifest}" ] |
| |
| foreach(file, additional_archive_files) { |
| inputs += [ file.source ] |
| args += [ |
| "--mapping", |
| file.dest, |
| rebase_path(file.source, root_build_dir), |
| ] |
| deps += file.deps |
| } |
| } |
| |
| # Populate the content of the $BUILD_DIR/sdk/exported/{name}/ |
| # directory from the content of the archive manifest. |
| action(labels.export) { |
| forward_variables_from(invoker, [ "testonly" ]) |
| |
| script = "//build/sdk/export_sdk.py" |
| |
| inputs = [ files.tarmaker_manifest ] |
| |
| _out_dir = "$root_out_dir/sdk/exported/$sdk_name" |
| _stamp_file = "$target_gen_dir/$target_name.exported" |
| |
| outputs = [ |
| _stamp_file, |
| "$_out_dir/meta/manifest.json", |
| ] |
| |
| depfile = "${_stamp_file}.d" |
| |
| args = [ |
| "--out-dir", |
| rebase_path(_out_dir, root_build_dir), |
| "--stamp-file", |
| rebase_path(_stamp_file, root_build_dir), |
| "--manifest", |
| rebase_path(files.tarmaker_manifest, root_build_dir), |
| "--depfile", |
| rebase_path(depfile, root_build_dir), |
| ] |
| |
| deps = [ ":${labels.tarmaker_manifest}" ] |
| } |
| |
| _generate_archive = |
| defined(invoker.generate_archive) && invoker.generate_archive |
| |
| # Generates the local archive, then copy it to its final location. |
| compiled_action(labels.local_archive) { |
| forward_variables_from(invoker, [ "testonly" ]) |
| |
| tool = "//build/tools/tarmaker" |
| |
| inputs = [ files.tarmaker_manifest ] |
| |
| outputs = [ files.local_archive ] |
| |
| args = [ |
| "-manifest", |
| rebase_path(inputs[0], root_build_dir), |
| "-output", |
| rebase_path(outputs[0], root_build_dir), |
| ] |
| |
| deps = [ ":${labels.tarmaker_manifest}" ] |
| } |
| |
| copy(labels.final_archive) { |
| forward_variables_from(invoker, [ "testonly" ]) |
| |
| sources = [ files.local_archive ] |
| |
| outputs = [ files.final_archive ] |
| |
| public_deps = [ ":${labels.local_archive}" ] |
| |
| metadata = { |
| sdk_archives = [ |
| { |
| name = sdk_name |
| os = current_os |
| cpu = current_cpu |
| label = get_label_info(":$target_name", "label_with_toolchain") |
| path = rebase_path(files.final_archive, root_build_dir) |
| }, |
| ] |
| } |
| } |
| |
| group(labels.main) { |
| forward_variables_from(invoker, |
| [ |
| "testonly", |
| "visibility", |
| ]) |
| |
| deps = [ |
| ":${labels.verify_manifest}", |
| ":${labels.verify_sdk_meta}", |
| ] |
| |
| public_deps = [ |
| ":${labels.export}", |
| ":${labels.final_manifest}", |
| ] |
| if (_generate_archive) { |
| public_deps += [ ":${labels.final_archive}" ] |
| } |
| |
| # TODO(https://fxbug.dev/42174965): Block all metadata traversals such as the following: |
| # metadata = { |
| # expect_includes_barrier = [] |
| # } |
| } |
| } |