blob: 0d8590b96b819d76934f55ea1a99ccb6bc04e333 [file] [log] [blame]
# Copyright 2020 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/host.gni")
import("//build/rust/rustc_binary.gni")
import("//build/sdk/sdk_atom.gni")
import("//src/developer/ffx/build/ffx_action.gni")
import("//src/developer/ffx/config.gni")
import("//src/developer/ffx/lib/version/build/ffx_apply_version.gni")
# Defines an ffx-compatible subtool in the form of a rust binary target
#
# All parameters to `rustc_binary` are available, along with the additional
# parameters below.
#
# Additional Parameters
#
# sdk_target_name (optional)
# The target name to generate for an sdk atom definition. If not
# set, no sdk target will be generated.
#
# sdk_category (required if `sdk_target_name` is set)
# The sdk category this will be installed to.
# See `sdk_atom`'s `category` argument for more information.
#
# sdk_area (optional)
# [string] The API area responsible for maintaining this tool.
# See //build/sdk/sdk_atom.gni.
#
# sdk_deps (optional, ignored if `sdk_target_name` not set)
# Dependencies for inclusion in the sdk. See `sdk_atom` for more
# information on this.
#
# The following targets will be produced, in addition to any from `rustc_binary`:
#
# `<target_name>`
# The rust binary before applying build version information to it.
# Output: `<output_name>_unversioned`
#
# `<target_name>_versioned`
# The rust binary after applying build version information to it.
# Output: `<output_name>`
#
# `<target_name>_metadata`
# The json metadata for this tool that allows ffx to discover it
# and determine compatibility information.
# Output: `<output_name>.json`
#
# `<target_name>_host_tool`
# Installation of the versioned binary and metadata as a host tool.
# Output: `host-tools/<output_name>`, `host-tools/<output_name>.json`
#
# `<target_name>_test_data`
# A `host_test_data` target that includes the files necessary to make sure
# this tool is available to tests.
#
# The following target will be produced only if `sdk_target_name` is set:
#
# `<sdk_target_name>`
# Include the tool in the sdk as a host tool with metadata attached.
# Output: (see `sdk_atom` for more information)
#
template("ffx_tool") {
if (!defined(invoker.output_name)) {
output_name = target_name
} else {
output_name = invoker.output_name
}
# targets that are part of the 'public interface' of ffx_tool
target_versioned = "${target_name}_versioned"
target_unversioned = target_name
target_metadata = "${target_name}_metadata"
target_host_tool = "${target_name}_host_tool"
target_test_data = "${target_name}_test_data"
# targets that are part of the private interface of ffx_tool
# (prefixed with _ to differentiate).
target_versioned_bin = "_${target_name}_versioned_bin"
output_versioned = output_name
output_unversioned = "${output_name}_unversioned"
output_metadata = "${output_name}.json"
assert_no_deps = []
if (defined(invoker.assert_no_deps)) {
assert_no_deps += invoker.assert_no_deps
}
# TODO(b/314822328): improve this logic to cascade properly
if (defined(invoker.sdk_category) && invoker.sdk_category != "internal") {
assert_no_deps += [
"//sdk:marker-cts",
"//sdk:marker-excluded",
"//sdk:marker-experimental",
"//sdk:marker-internal",
"//sdk:marker-unknown",
]
}
# Make the rust binary
rustc_binary(target_unversioned) {
output_name = output_unversioned
forward_variables_from(invoker,
"*",
[
"output_name",
"sdk_target_name",
"sdk_category",
"sdk_area",
"sdk_deps",
"assert_no_deps",
])
}
# Replace the special linker sections containing the version information with the real values
ffx_apply_version(target_versioned_bin) {
output_name = output_versioned
ffx_unversioned_binary_path = "${root_out_dir}/${output_unversioned}"
runtime_files = [ "$root_out_dir/$output_metadata" ]
deps = [
":$target_metadata",
":$target_unversioned",
]
}
# Create the metadata file for in-tree discovery
ffx_action(target_metadata) {
# Use the unversion-stamped binary to generate the metadata file. The
# ffx_action() template will convert these names to the correct ones by
# adding the '_unversioned' suffix to the 'output_name'.
#
# This is the default, but it's set here for extra clarity.
use_versioned_binary = false
ffx_tool = ":$target_unversioned"
ffx_tool_output_name = output_versioned # without _unversioned suffix
needs_sdk = false
inputs = []
outputs = [ "$root_out_dir/$output_metadata" ]
args = [
"metadata",
rebase_path("$root_out_dir/$output_metadata", root_build_dir),
]
}
# Combine those into a target that represents both the versioned binary
# and the metadata.
group(target_versioned) {
public_deps = [
":$target_metadata",
":$target_versioned_bin",
]
}
# Install host tool
install_host_tools(target_host_tool) {
deps = [ ":$target_versioned" ]
outputs = [
output_name,
output_metadata,
]
}
# Install host tool and metadata as test data
host_test_data(target_test_data) {
forward_variables_from(invoker, [ "testonly" ])
data_deps = [ ":$target_host_tool" ]
sources = [
"${host_tools_dir}/${output_metadata}",
"${host_tools_dir}/${output_name}",
]
}
if (defined(invoker.sdk_target_name)) {
# Add to the sdk
file_base_root = "tools/ffx_tools"
if (host_os == "linux" || host_os == "mac") {
file_base_root = "tools/$current_cpu/ffx_tools"
}
file_base = "$file_base_root/$output_name"
file_base_metadata = "$file_base_root/$output_metadata"
assert(
defined(invoker.sdk_category),
"Must specify an sdk category if generating an sdk target for ffx tool")
# for the moment this goes directly to sdk_atom because this is a 'weird'
# host tool that includes a json metadata file.
sdk_atom(invoker.sdk_target_name) {
forward_variables_from(invoker, [ "sdk_area" ])
id = "sdk://$file_base"
category = invoker.sdk_category
_target_files = {
executable = file_base
executable_metadata = file_base_metadata
}
meta = {
dest = "$file_base-meta.json"
schema = "ffx_tool"
sources = [ "//build/sdk/meta/host_tool.json" ]
value = {
type = "ffx_tool"
name = output_name
root = "tools"
files = {
}
target_files = {
}
if (current_cpu == "arm64") {
target_files.arm64 = _target_files
} else if (current_cpu == "x64") {
target_files.x64 = _target_files
} else if (current_cpu == "riscv64") {
target_files.riscv64 = _target_files
} else {
assert(false, "Unknown CPU type: $current_cpu")
}
}
}
files = [
{
source = "$root_out_dir/$output_versioned"
dest = file_base
},
{
source = "$root_out_dir/$output_metadata"
dest = file_base_metadata
},
]
if (defined(invoker.sdk_deps)) {
deps = invoker.sdk_deps
}
non_sdk_deps = [
":$target_metadata",
":$target_versioned",
]
}
}
}