blob: 27d2dedf60701c5713a1233eda51212d49ddc455 [file] [log] [blame]
# 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),
]
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 = []
# }
}
}