| # 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("config.gni") |
| import("meta/version.gni") |
| import("sdk_molecule.gni") |
| |
| # A collection of elements to be published in an SDK. |
| # |
| # Parameters |
| # |
| # name (optional) |
| # Name of the SDK. |
| # Defaults to the target's name. |
| # |
| # id (optional) |
| # An opaque identifier for the SDK. |
| # Defaults to the empty string. |
| # |
| # api (required) |
| # Path to the file representing the canonical contents of this SDK. |
| # This file is used to ensure modifications to the SDK contents are |
| # explicitly acknowledged. |
| # Mandatory for "public" or "partner" SDKs. |
| # |
| # category (required) |
| # Describes the minimum category that atoms in this SDK must have. |
| # See //build/sdk/sdk_atom.gni for possible values. |
| # |
| # export (optional) |
| # Whether to export the contents of this SDK to the output directory. |
| # This is useful when an SDK-like file structure is needed as part of the |
| # build, for example to port a language runtime which would otherwise rely |
| # on an official SDK. |
| # Defaults to false. |
| |
| template("sdk") { |
| assert(defined(invoker.category), "Must define an SDK category") |
| |
| if (invoker.category == "public" || invoker.category == "partner") { |
| assert(defined(invoker.api), "API file required for public/partner SDKs") |
| } |
| |
| main_target_name = target_name |
| generation_target_name = "${target_name}_molecule" |
| verify_api_target_name = "${target_name}_verify_api" |
| copy_target_name = "${target_name}_copy" |
| verification_target_name = "${target_name}_manifest_verify" |
| meta_target_name = "${target_name}_meta" |
| verify_meta_target_name = "${target_name}_meta_verify" |
| archive_manifest_target_name = "${target_name}_archive_manifest" |
| archive_target_name = "${target_name}_archive" |
| fidl_json_target_name = "${target_name}_fidl_json" |
| export_target_name = "${target_name}_export" |
| |
| 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" |
| |
| sdk_name = target_name |
| if (defined(invoker.name)) { |
| sdk_name = invoker.name |
| } |
| |
| # Generates the manifest. |
| sdk_molecule(generation_target_name) { |
| # Do not expose this molecule to other targets. Depending directly on the |
| # contents of an SDK foregoes API verification, which is not desirable. |
| visibility = [ ":$verify_api_target_name" ] |
| |
| forward_variables_from(invoker, |
| [ |
| "assert_no_deps", |
| "category", |
| "deps", |
| "testonly", |
| ]) |
| |
| if (!defined(deps)) { |
| deps = [] |
| } |
| deps += [ "//build/sdk/meta" ] |
| } |
| |
| intermediate_manifest_file = "$target_gen_dir/$generation_target_name.sdk" |
| |
| computed_api_file = "$root_out_dir/sdk/api/$sdk_name" |
| |
| # Verify that the contents of the SDK have not changed. |
| action(verify_api_target_name) { |
| forward_variables_from(invoker, [ "testonly" ]) |
| |
| script = "//build/sdk/verify_sdk_api.py" |
| |
| inputs = [ intermediate_manifest_file ] |
| |
| outputs = [ computed_api_file ] |
| |
| args = [ |
| "--manifest", |
| rebase_path(intermediate_manifest_file, root_build_dir), |
| "--updated", |
| rebase_path(computed_api_file, root_build_dir), |
| ] |
| |
| # TODO(fxbug.dev/5535): always set this argument. |
| if (defined(invoker.api)) { |
| inputs += [ invoker.api ] |
| args += [ |
| "--reference", |
| rebase_path(invoker.api, root_build_dir), |
| ] |
| } |
| |
| if (warn_on_sdk_changes) { |
| args += [ "--warn" ] |
| } |
| |
| public_deps = [ ":$generation_target_name" ] |
| } |
| |
| final_manifest_file = "$root_out_dir/sdk/manifest/$sdk_name" |
| |
| # Copies the manifest to a central location. |
| copy(copy_target_name) { |
| forward_variables_from(invoker, [ "testonly" ]) |
| |
| sources = [ intermediate_manifest_file ] |
| |
| outputs = [ final_manifest_file ] |
| |
| deps = [ ":$verify_api_target_name" ] |
| |
| 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(verification_target_name) { |
| forward_variables_from(invoker, [ "testonly" ]) |
| |
| data = final_manifest_file |
| |
| schema = "//build/sdk/manifest_schema.json" |
| |
| deps = [ ":$copy_target_name" ] |
| } |
| |
| sdk_meta_file = "$target_gen_dir/$sdk_name.sdk_meta.json" |
| |
| # Generates a metadata file describing the various parts of the SDK. |
| action(meta_target_name) { |
| forward_variables_from(invoker, [ "testonly" ]) |
| |
| script = "//build/sdk/generate_meta.py" |
| |
| inputs = [ |
| final_manifest_file, |
| "//build/sdk/sdk_common.py", |
| ] |
| |
| outputs = [ sdk_meta_file ] |
| |
| args = [ |
| "--manifest", |
| rebase_path(final_manifest_file, root_build_dir), |
| "--meta", |
| rebase_path(sdk_meta_file, 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 = [ |
| ":$copy_target_name", |
| ":$verification_target_name", |
| ] |
| } |
| |
| # Verifies that the manifest metadata is valid. |
| validate_json(verify_meta_target_name) { |
| forward_variables_from(invoker, [ "testonly" ]) |
| |
| data = sdk_meta_file |
| |
| schema = "//build/sdk/meta/manifest.json" |
| sources = [ |
| # This file is imported by all schemas. |
| "//build/sdk/meta/common.json", |
| ] |
| |
| public_deps = [ ":$meta_target_name" ] |
| } |
| |
| archive_manifest_file = "$target_gen_dir/$sdk_name.archive_manifest" |
| |
| additional_archive_files = [ |
| { |
| source = sdk_meta_file |
| dest = "meta/manifest.json" |
| }, |
| ] |
| |
| # From the manifest file representing the SDK, generates a list of the files |
| # going into the final archive. |
| action(archive_manifest_target_name) { |
| forward_variables_from(invoker, [ "testonly" ]) |
| |
| script = "//build/sdk/generate_archive_manifest.py" |
| |
| sources = [ "//build/sdk/sdk_common.py" ] |
| |
| inputs = [ final_manifest_file ] |
| |
| outputs = [ archive_manifest_file ] |
| |
| args = [ |
| "--manifest", |
| rebase_path(final_manifest_file, root_build_dir), |
| "--output", |
| rebase_path(archive_manifest_file, root_build_dir), |
| ] |
| |
| foreach(file, additional_archive_files) { |
| inputs += [ file.source ] |
| args += [ |
| "--mapping", |
| file.dest, |
| rebase_path(file.source, root_build_dir), |
| ] |
| } |
| |
| public_deps = [ ":$verify_meta_target_name" ] |
| } |
| |
| # Generates the final archive. |
| local_archive = "$target_gen_dir/$target_name.tar.gz" |
| output_archive = "${root_out_dir}/sdk/archive/${sdk_name}.tar.gz" |
| archive_generate_target_name = "${archive_target_name}_generate" |
| |
| compiled_action(archive_generate_target_name) { |
| forward_variables_from(invoker, [ "testonly" ]) |
| |
| tool = "//build/tools/tarmaker" |
| |
| inputs = [ archive_manifest_file ] |
| |
| outputs = [ local_archive ] |
| |
| args = [ |
| "-manifest", |
| rebase_path(archive_manifest_file, root_build_dir), |
| "-output", |
| rebase_path(local_archive, root_build_dir), |
| ] |
| |
| deps = [ ":$archive_manifest_target_name" ] |
| } |
| |
| copy(archive_target_name) { |
| forward_variables_from(invoker, [ "testonly" ]) |
| |
| sources = [ local_archive ] |
| |
| outputs = [ output_archive ] |
| |
| public_deps = [ ":$archive_generate_target_name" ] |
| |
| metadata = { |
| sdk_archives = [ |
| { |
| name = sdk_name |
| os = current_os |
| cpu = current_cpu |
| label = get_label_info(":$target_name", "label_with_toolchain") |
| path = rebase_path(output_archive, root_build_dir) |
| }, |
| ] |
| } |
| } |
| |
| fidl_json_file = "$target_gen_dir/$sdk_name.fidl_json.txt" |
| |
| # Generate a helpful list of all of the JSON for the fidl in this SDK |
| generated_file(fidl_json_target_name) { |
| testonly = true |
| deps = [ ":$main_target_name" ] |
| outputs = [ "$fidl_json_file" ] |
| data_keys = [ "fidl_json" ] |
| } |
| |
| stamp_file = "$target_gen_dir/$target_name.exported" |
| |
| action(export_target_name) { |
| forward_variables_from(invoker, [ "testonly" ]) |
| |
| script = "//build/sdk/export_sdk.py" |
| |
| inputs = [ archive_manifest_file ] |
| |
| outputs = [ stamp_file ] |
| depfile = "${stamp_file}.d" |
| |
| args = [ |
| "--out-dir", |
| rebase_path("$root_out_dir/sdk/exported/$sdk_name", root_build_dir), |
| "--stamp-file", |
| rebase_path(stamp_file, root_build_dir), |
| "--manifest", |
| rebase_path(archive_manifest_file, root_build_dir), |
| "--depfile", |
| rebase_path(depfile, root_build_dir), |
| ] |
| |
| deps = [ ":$archive_manifest_target_name" ] |
| } |
| |
| group(main_target_name) { |
| forward_variables_from(invoker, [ "testonly" ]) |
| |
| public_deps = [ ":$export_target_name" ] |
| |
| # The copy target needs to be in public deps so that targets can dep on |
| # $target_name, and list the file that's output from the copy as an input. |
| public_deps += [ ":$copy_target_name" ] |
| |
| if (build_sdk_archives) { |
| public_deps += [ ":$archive_target_name" ] |
| } |
| |
| # TODO(fxbug.dev/93205): Block all metadata traversals such as the following: |
| # metadata = { |
| # expect_includes_barrier = [] |
| # } |
| } |
| } |