blob: de87d591312d19b95089ea1a770c32f30f20fa9d [file] [log] [blame]
# Copyright 2019 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("$zx/public/gn/build_api_module.gni")
import("$zx/public/gn/config/standard.gni")
import("$zx/public/gn/copied_files_dir.gni")
import("$zx/public/gn/prebuilt.gni")
import("$zx/public/gn/test/zbi_test.gni")
import("$zx/public/gn/toolchain/c_utils.gni")
import("$zx/public/gn/toolchain/environment_redirect.gni")
import("$zx/public/gn/zbi.gni")
declare_args() {
# Defines the `//:default` target: what `ninja` with no arguments does.
# TODO(BLD-353): This must be set by the controlling Fuchsia GN build.
default_deps = false
}
assert(default_deps != false,
"TODO(BLD-353): Zircon build must be driven by Fuchsia build")
###
### Build API modules.
###
# This is the top-level build API module that just lists all the others.
# Each element of the list is the simple name of the API module; the
# module's contents are found at "$root_build_dir/$target_name.json".
#
# TODO(BLD-353): Note this does not include build_api_module() uses meant
# just for legacy build integration. We don't consider those to be actual
# build API modules; using build_api_module() is just a convenience for
# creating them. Importantly, they are not part of the API contract with
# consumers of the overall build. They're purely implementation details of
# the temporary Frankenbuild arrangement.
#
# Type: list(string)
build_api_module("api") {
testonly = true
data_keys = [ "build_api_modules" ]
deps = [
":binaries",
":buildargs",
":generated_sources",
":images",
":packages",
":tool_paths",
]
}
# This just regurgitates the build arguments specified to `gn gen`. This is
# the exact JSON representation of the settings in "$root_build_dir/args.gn".
# It does not include build arguments left to their default values. So to
# reproduce the settings of this build, one could put in `args.gn`:
# ```
# forward_variables_from(read_file("buildargs.json", "json"), "*")
# ```
# Type: scope
build_api_module("buildargs") {
# The file does not exist at all if `gn gen` is run with no `--args`. But
# read_file() can't handle an optional file and there's no direct way to test
# for file existence from GN.
contents = exec_script("/bin/sh",
[
"-c",
"test ! -e args.gn || cat args.gn",
],
"scope")
}
# This describes all the binaries linked by the build.
#
# This enumerates each linked binary (executable, shared library, or
# loadable/"plug-in" module). This includes host tools, kernels, boot
# loaders, drivers, as well as normal executables. It does not yet include
# any non-native binary formats. This is meant to reach the entire
# dependency graph of all binaries that the build would ever produce. Not
# every binary described is necessary actually produced by any given Ninja
# run. Either the $debug or the $dist file for any individual binary can
# be passed to Ninja as a specific target argument to ensure it's built and
# up to date before making use of that binary. Like all build_api_module()
# targets, the top-level "binaries" target serves as a Ninja target to
# request that every binary described be built.
#
# Type: list(scope)
#
# cpu
# Required: CPU architecture the binary is for, e.g. "arm64" or "x64".
# Type: string
#
# os
# Required: OS the binary is for, e.g. "fuchsia", "linux", or "mac".
# Type: string
#
# environment
# Required: The ${toolchain.environment} name of what specific
# execution this was built for, e.g. "user", "host", "guest". The
# tuple of ($cpu, $os, $environment) should indicate what hardware and
# software environment this binary is compatible with.
# Type: string
#
# label
# Required: The GN label of the binary target.
# Type: label_with_toolchain
#
# type
# Required: The type of binary.
# Type: "executable" or "shared_library" or "loadable_module"
#
# debug
# Required: Path to where the unstripped or separate debug file is
# found, relative to $root_build_dir. If $dist is omitted, this
# is also the file that is used at runtime.
# Type: path relative to $root_build_dir
#
# dist
# Optional: Path to where the stripped binary for deployment/execution is
# found, relative to $root_build_dir. This binary may be required for
# some debugging tasks if $debug is a separate debug file rather than
# an unstripped file. It should exactly match the binary that will be
# seen on devices or run directly on hosts.
# Type: path relative to $root_build_dir
#
# elf_build_id
# Optional: Path to a file containing the lowercase ASCII hexadecimal
# representation of the ELF build ID in this binary. This is omitted
# for OS environments that don't use ELF. For an ELF binary that
# doesn't have a build ID note, this key will be present but point to
# an empty file.
# Type: path relative to $root_build_dir
#
build_api_module("binaries") {
testonly = true
deps = [ ":everything" ] + default_deps
data_keys = [ "binaries" ]
}
# This describes all the generated source files in the build.
#
# The intent is that telling Ninja to build all these individual files
# will be the minimal work sufficient for source code analysis of all
# the files described in the compilation database to be viable.
#
# Type: list(path relative to $root_build_dir)
#
build_api_module("generated_sources") {
testonly = true
deps = [
":everything",
]
data_keys = [ "generated_sources" ]
}
# This describes all the "image" files the build can produce.
#
# Consumers of the build should look here for the images to be built.
# The $cpu, $name, and $type fields identify the purpose of each image.
# Consumers are expected to ignore extra images they have no use for or
# whose fields they don't understand.
#
# The $path field indicates where the file is found in the build
# directory. The presence of an image in the list means that the build
# *can* produce it, not that the build *will* produce it. Hence,
# consumers should use $path as an explicit argument to Ninja to ensure
# that each needed image gets built.
#
# Type: list(scope)
#
# cpu
# Required: CPU architecture the image is for, e.g. "arm64" or "x64".
# Type: string
#
# name
# Required: The primary way that this image is known to consumers.
# Note that the name need not be unique within the images list.
# The tuple of ($name, $type, $cpu) should be unique.
# Type: string
#
# label
# Required: The GN label of the image target.
# Type: label_with_toolchain
#
# path
# Required: Path to where the file is found, relative to $root_build_dir.
# This is also the argument to Ninja that ensures this image will be built.
# Type: path relative to $root_build_dir
#
# testonly
# Optional: This image includes test code/data not meant for production.
# Type: bool
# Default: false
#
# tags
# Optional: Tags associated with the image. Certain tags may indicate
# to the build API consumer what should be done with the image.
# Type: list(string)
#
# type
# Required: Type of file, e.g. "zbi". This often corresponds to the
# extension used on the image file name, but not always. For many
# miscellaneous formats, this is just "bin" and the consumer is
# expected to understand what the particular format is for particular
# $name, $cpu combinations. Other types include:
# * "zbi": the ZBI (<zircon/boot/image.h>) format
# * "efi": an EFI executable that an EFI boot loader can load
# * "kernel": some other format loaded by a boot loader or emulator
# * "blk": contents to be written to a storage device or partition
# Type: string
#
build_api_module("images") {
testonly = true
data_keys = [ "images" ]
deps = [
":everything",
]
}
# Packages defined in the build.
#
# Type: list(scope)
#
# * name
# - Required: Name of the package.
# - Type: string
#
# * label
# - Required: GN label of the package() target.
# - Type: label_with_toolchain
#
# * cpu, os
# - Required: $current_cpu and $current_os values, respectively, for
# which this package is intended.
# - Type: string
#
# * manifest
# - Required: Manifest file of the package's sandbox filesystem contents.
# - Type: path relative to $root_build_dir
#
# * tags
# - Optional: List of tags to associate with the package.
# - Type: list(string)
#
# * testonly
# - Optional: True if this package should never be in a production build.
# - Type: bool
# - Default: false
#
build_api_module("packages") {
testonly = true
data_keys = [ "packages" ]
deps = [
":everything",
]
}
# Tools provided by the build or as prebuilts, to be used outside the build.
#
# Type: list(scope)
#
# * name
# - Required: Name of a host tool.
# - Type: string
#
# * label
# - Required: GN label associated with the tool.
# - Type: label_with_toolchain
#
# * path
# - Required: Path to the tool's executable for the build host.
# - Type: path relative to $root_build_dir
#
build_api_module("tool_paths") {
testonly = true
deps = [
":tool_paths.metadata",
"$zx/public/gn/toolchain:llvm-tools",
"tools",
]
data_keys = [ "tool_paths" ]
}
group("tool_paths.metadata") {
visibility = [ ":tool_paths" ]
_eponymous_3p_tools = [
"gn",
"ninja",
]
metadata = {
tool_paths = []
foreach(tool, _eponymous_3p_tools) {
tool_paths += [
{
label = get_label_info(":$target_name", "label_with_toolchain")
name = tool
path = rebase_path(
"$prebuilt_dir/third_party/$tool/$host_platform/$tool",
root_build_dir)
},
]
}
}
}
###
### Top-level targets.
###
# This collects all the top-level targets that should contribute to the
# "everything" target, which is the root of build_api_module() metadata walks.
_everything_deps = []
# Just building this constitutes a useful test that the build system and
# compiler configurations work as intended. It may also entail building a
# lot of stuff that is not actually useful to build and/or cannot be tested
# easily (or at all).
group("build-tests") {
testonly = true
deps = [
"$zx/public/gn/toolchain:noop-test",
]
}
_everything_deps += [ ":build-tests" ]
# Build the host tools intended for developer use. Install the tools for
# the running host platform in the "$root_build_dir/tools/" directory.
# Cross-built tools can be installed in "$root_build_dir/tools-$os-$cpu".
_tools_targets = [ "tools" ]
foreach(host, standard_build_hosts) {
_tools_targets += [ "tools-${host.os}-${host.cpu}" ]
environment_redirect("tools-${host.os}-${host.cpu}.redirect") {
visibility = [ ":*" ]
testonly = true
environment_label = "$zx/public/gn/toolchain:host"
cpu = host.cpu
os = host.os
direct = true
deps = [
"$zx/tools",
]
}
}
group("tools.redirect") {
visibility = [ ":*" ]
testonly = true
public_deps = [
":tools-${host_os}-${host_cpu}",
]
}
group("tools.all") {
testonly = true
deps = []
foreach(tools_target, _tools_targets) {
deps += [ ":$tools_target" ]
}
}
foreach(tools_target, _tools_targets) {
_everything_deps += [ ":$tools_target" ]
copied_files_dir(tools_target) {
testonly = true
data_keys = [ "tool_executables" ]
deps = [
":$tools_target.redirect",
]
}
}
# This is used in the top-level build_api_module() deps to reach "everything".
# Note that "all" is a magical target name to Ninja, hence this name instead.
group("everything") {
testonly = true
deps = _everything_deps
}
# This is the default target that Ninja builds when given no target arguments.
group("default") {
testonly = true
deps = default_deps
}
###
### TODO(BLD-353): Temporary hacks for integrating with the legacy Fuchsia
### GN build.
###
if (current_toolchain == default_toolchain) {
copied_files_dir("legacy-host_tests") {
testonly = true
output_dir = "$root_build_dir/host_tests"
data_keys = [ "link_output" ]
walk_keys = [ "link_barrier" ]
deps = [
"system/utest:host",
]
}
build_api_module("legacy_dirs") {
testonly = true
data_keys = [ "legacy_dirs" ]
walk_keys = [ "legacy_barrier" ]
deps = []
foreach(cpu, standard_fuchsia_cpus) {
deps += [ ":legacy-$cpu" ]
}
}
foreach(cpu, standard_fuchsia_cpus) {
# TODO(mcgrathr): This target name is used directly by the zircon.py
# recipe. The actual ZBI file is now built via zbi_test() and is deep
# down the deps tree from here. Remove this when the target name is no
# longer being used directly.
group("core-tests-$cpu") {
testonly = true
public_deps = [
":legacy-$cpu",
]
}
group("legacy-$cpu") {
testonly = true
deps = [
":legacy-aux-$cpu",
":legacy-host_tests",
":legacy-image-$cpu",
":legacy-tests-$cpu",
":legacy_targets-$cpu",
]
}
build_api_module("legacy_targets-$cpu") {
testonly = true
data_keys = [ "legacy_targets" ]
walk_keys = [ "legacy_barrier" ]
deps = [
":all-ulib-$cpu",
"$zx/system/banjo",
"$zx/system/fidl",
"tools",
]
}
build_api_module("legacy_sysroot-$cpu") {
testonly = true
data_keys = [ "legacy_sysroot" ]
walk_keys = [ "legacy_barrier" ]
deps = [
":all-ulib-$cpu",
]
}
build_api_module("legacy_fuzzers-$cpu") {
testonly = true
data_keys = [ "fuzzer" ]
deps = [
":legacy-tests-$cpu",
]
}
}
}
foreach(cpu, standard_fuchsia_cpus) {
if (current_toolchain == default_toolchain) {
zbi("legacy-image-$cpu") {
output_dir = root_build_dir
testonly = true
cpu = cpu
deps = [
":legacy-deps-$cpu",
]
metadata = {
# legacy-$cpu depends on this to get all these deps built.
# But they shouldn't contribute metadata to the build_api_module().
legacy_barrier = []
}
}
zbi_input("legacy-tests-$cpu") {
output_dir = root_build_dir
testonly = true
cpu = cpu
deps = [
":legacy-tests-deps-$cpu",
]
}
# The legacy Fuchsia GN build needs to consume a manifest of libraries
# built for ASan (and all the libraries themselves). When the main
# build is ASan, it needs to find the non-ASan libraries here too.
manifest_file("legacy-aux-$cpu") {
testonly = true
deps = [
":all-ulib-$cpu",
":driver-deps-$cpu",
":instrumented-ulib-$cpu",
# Include the tests so their libraries are in the aux manifest
# when individual binaries are drawn from the tests manifest.
":legacy-tests-deps-$cpu",
]
metadata = {
# This prevents build_api_module("legacy-$cpu") from visiting the
# ASan incarnations of all the libraries. The legacy build wants
# only the manifest of ASan shared libraries. It wants the targets
# themselves only from the primary build.
legacy_barrier = []
}
}
}
environment_redirect("legacy-deps-$cpu") {
visibility = [ ":*" ]
testonly = true
environment_label = "$zx/public/gn/toolchain:user"
cpu = cpu
deps = [
"$zx/bootloader",
"$zx/kernel",
"$zx/system/core",
"$zx/system/dev",
"$zx/system/uapp",
"$zx/third_party/uapp",
]
metadata = {
legacy_barrier = []
}
}
environment_redirect("legacy-tests-deps-$cpu") {
visibility = [ ":*" ]
testonly = true
environment_label = "$zx/public/gn/toolchain:user"
cpu = cpu
direct = true
deps = [
"$zx/system/utest",
]
}
environment_redirect("all-ulib-$cpu") {
testonly = true
cpu = cpu
environment_label = "$zx/public/gn/toolchain:user"
shlib = true
exclude_variant_tags = [ "instrumented" ]
deps = [
"$zx/system/ulib",
]
}
environment_redirect("driver-deps-$cpu") {
testonly = true
cpu = cpu
environment_label = "$zx/public/gn/toolchain:user"
exclude_variant_tags = [ "instrumented" ]
deps = [
"$zx/system/core/devmgr:driver_deps",
"$zx/system/core/devmgr:driver_deps.asan",
]
}
environment_redirect("instrumented-ulib-$cpu") {
testonly = true
cpu = cpu
environment_label = "$zx/public/gn/toolchain:user"
deps = [
":instrumented-ulib-redirect",
]
}
}
if (toolchain.environment == "user") {
instrumented_variants = []
foreach(selector, toolchain.variant_selectors) {
if (selector.tags + [ "instrumented" ] - [ "instrumented" ] !=
selector.tags) {
instrumented_variants += [ selector.variant ]
instrumented_variants -= [ selector.variant ]
instrumented_variants += [ selector.variant ]
}
}
group("instrumented-ulib-redirect") {
testonly = true
visibility = [ ":*" ]
deps = []
foreach(variant, instrumented_variants) {
deps += [ ":instrumented-ulib-redirect.$variant" ]
}
}
foreach(variant, instrumented_variants) {
environment_redirect("instrumented-ulib-redirect.$variant") {
testonly = true
visibility = [ ":instrumented-ulib-redirect" ]
variant = variant
deps = [
"$zx/system/ulib",
]
foreach(dep, toolchain.implicit_deps) {
if (dep == "$dep") {
deps += [ dep ]
} else {
deps += dep.add
}
}
}
}
}
build_api_module("legacy_images") {
testonly = true
data_keys = [ "images" ]
deps = [
"tools",
]
foreach(cpu, standard_fuchsia_cpus) {
deps += [ ":legacy-$cpu" ]
}
}
# TODO(BLD-353): This is just for the legacy build and is not really a
# proper build API module. In the unified build, this string will just be
# directly embedded inside test metadata.
build_api_module("zbi_test_success_string") {
contents = zbi_test_success_string
}
# This describes pre-generated FIDL bindings that are required by the build.
#
# TODO(BLD-441): This will go away when fidlgen is built in this build.
# See $zx/public/gn/fidl/llcpp.gni, where the metadata is generated.
#
# Type: list(scope)
#
# name
# Required: The FIDL library name as it appears in FIDL source (with dots).
# Type: string
#
# label
# Required: The label of the fidl_library() target.
# Type: label_no_toolchain
#
# json
# Required: Path to the fidlc --json output.
# Type: path relative to $root_build_dir
#
# target_gen_dir
# Required: The place in the source tree where generated files go.
# Type: path relative to $root_build_dir
#
# args
# Required: Argument list for `fidlgen` if run in $root_build_dir.
# Type: list(string)
#
build_api_module("fidl_gen") {
testonly = true
data_keys = [ "fidl_gen" ]
deps = default_deps
}