blob: 9ebaee0ebc3c165eb4acda25b199792d2c0372e5 [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("//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 = []
# }
}
}