blob: 3821164f94728934dcd70f7e66618a456e6d7ebc [file] [log] [blame]
# Copyright 2023 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/config/compiler.gni")
import("//build/python/python_action.gni")
import("//build/sdk/config.gni")
import("//build/toolchain/goma.gni")
import("//build/toolchain/rbe.gni")
import("//sdk/config.gni")
# Create a GN directory, and build an `sdk_collection` target for a particular
# target_cpu and api_level by calling `gn gen` and then `ninja` in that
# directory.
template("_subbuild") {
assert(defined(invoker.sdk_collection))
assert(defined(invoker.target_cpu))
assert(defined(invoker.api_level))
assert(defined(invoker.extra_deps))
_build_dir = root_build_dir + "/build-${target_name}"
_build_dir_stamp = _build_dir + ".stamp"
_sdk_collection_dir = get_label_info(invoker.sdk_collection, "dir")
_sdk_collection_name = get_label_info(invoker.sdk_collection, "name")
_sdk_collection = "${_sdk_collection_dir}:${_sdk_collection_name}"
_collection_dir = _build_dir + "/sdk/exported/${_sdk_collection_name}"
_collection_dir_manifest = "${_collection_dir}/meta/manifest.json"
action(target_name) {
script = "//build/sdk/subbuild.py"
outputs = [
_build_dir_stamp,
_collection_dir_manifest,
]
# //sdk:idk_build_tools contains the host tools that must be used in the
# subbuilds. Make sure those (and any extra deps) are built first.
deps = [ "//sdk:idk_build_tools" ] + invoker.extra_deps
args = [
"--stamp-file",
rebase_path(_build_dir_stamp, root_build_dir),
"--sdk-id",
sdk_id,
"--output-build-dir",
rebase_path(_build_dir, root_build_dir),
"--sdk-collection-label",
_sdk_collection,
"--target-cpu",
invoker.target_cpu,
"--api-level",
invoker.api_level,
"--fuchsia-dir",
rebase_path("//", root_build_dir),
"--prebuilt-host-tools-dir",
rebase_path("$root_build_dir/sdk/idk_build_tools", _build_dir),
"--compress-debuginfo",
compress_debuginfo,
]
if (sdk_sub_build_parallelism != "") {
args += [
"--parallelism",
"${sdk_sub_build_parallelism}",
]
}
if (sdk_sub_build_max_load_average != "") {
args += [
"--max-load-average",
"${sdk_sub_build_max_load_average}",
]
}
if (sdk_sub_build_verbose) {
args += [ "--verbose" ]
}
if (cxx_rbe_enable) {
args += [ "--cxx-rbe-enable" ]
}
if (rust_rbe_enable) {
args += [ "--rust-rbe-enable" ]
}
if (use_goma) {
args += [ "--use-goma" ]
if (goma_dir != prebuilt_goma_dir) {
args += [ "--goma-dir=${goma_dir}" ]
}
}
pool = "//sdk:subbuild_pool"
# This script cannot be hermetic.
hermetic_deps = false
forward_variables_from(invoker,
[
"testonly",
"visibility",
])
}
}
# Generate a IDK directory, which combines outputs from different arch-specific
# sub-builds into a single one. The generated directory will include prebuilts
# for all the given `target_cpus`. On a host Linux machine, the generated
# archive will have host tools for both Linux/x64 and Linux/arm64.
#
# The generated directory will go into
# $root_build_dir/sdk/exported/{output_name}
#
# Arguments:
# target_cpus: (required)
# List of target cpu names. This must include the default target_cpu
# value for the current build configuration.
#
# api_levels: (required)
# List of API levels, as integers, to build prebuilts for, in addition to
# the current (HEAD) one.
#
# sdk_collection_label: (required)
# A single label for an sdk_collection() GN target that will be built
# multiple times and merged into the final directory.
#
# output_name: (optional)
# Name of the directory. Default is target_name
#
# testonly, visibility
# Usual GN meaning.
#
template("idk") {
assert(defined(invoker.target_cpus),
"target_cpus must be defined for $target_name")
assert(defined(invoker.api_levels),
"api_levels must be defined for $target_name")
assert(defined(invoker.sdk_collection_label),
"sdk_collection_label must be defined for $target_name")
# Default output name.
_output_name = target_name
if (defined(invoker.output_name)) {
_output_name = invoker.output_name
}
_non_current_cpus = invoker.target_cpus + [ current_cpu ] - [ current_cpu ]
assert(
invoker.target_cpus != _non_current_cpus,
"The target_cpus argument must include the current target_cpu ($target_cpu): ${invoker.target_cpus}")
# Do the current CPU first. This may not be necessary, but it's what the old
# script did and I want a null-diff.
_target_cpus = [ current_cpu ] + _non_current_cpus
_exported_dir = root_build_dir + "/sdk/exported/${_output_name}"
_exported_dir_manifest = "${_exported_dir}/meta/manifest.json"
_exported_dir_stamp = _exported_dir + ".stamp"
_sdk_collection_name = get_label_info(invoker.sdk_collection_label, "name")
_relative_collection_build_manifest = "sdk/manifest/${_sdk_collection_name}"
# Targets that must be built before producing the final IDK.
_subbuild_targets = []
# Build directories for each subbuilds that contribute to the IDK, including
# the main build. Note that the contents of the IDK are sensitive to the order
# of this list.
_subbuild_dirs = []
# First, do subbuilds for the default API level.
foreach(target_cpu, _target_cpus) {
if (target_cpu == current_cpu) {
# Don't do a subbuild for the current CPU - just depend on the
# `sdk_collection` in the current build.
_subbuild_targets += [ invoker.sdk_collection_label ]
_subbuild_dirs += [ root_build_dir ]
} else {
_subbuild_name = "${target_name}.subbuild-${target_cpu}"
_subbuild(_subbuild_name) {
sdk_collection = invoker.sdk_collection_label
target_cpu = target_cpu
api_level = "PLATFORM"
# Each subbuild depends on the `sdk_collection` in the main build, so
# that when a change happens that would cause the `sdk_collection` to be
# rebuilt, that also triggers the subbuilds to be rerun.
extra_deps = [ invoker.sdk_collection_label ]
forward_variables_from(invoker,
[
"testonly",
"visibility",
])
}
_subbuild_targets += [ ":$_subbuild_name" ]
_subbuild_dirs += [ "${root_build_dir}/build-${_subbuild_name}" ]
}
}
# Now do them for individual API levels.
foreach(api_level, invoker.api_levels) {
foreach(target_cpu, _target_cpus) {
_subbuild_name = "${target_name}.subbuild-api${api_level}-${target_cpu}"
_subbuild(_subbuild_name) {
sdk_collection = invoker.sdk_collection_label
target_cpu = target_cpu
api_level = "$api_level"
# Each subbuild depends on the `sdk_collection` in the main build, so
# that when a change happens that would cause the `sdk_collection` to be
# rebuilt, that also triggers the subbuilds to be rerun.
extra_deps = [ invoker.sdk_collection_label ]
forward_variables_from(invoker,
[
"testonly",
"visibility",
])
}
_subbuild_targets += [ ":$_subbuild_name" ]
_subbuild_dirs += [ "${root_build_dir}/build-${_subbuild_name}" ]
}
}
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"
# Combine all the individual sdk_collection subbuilds and put the result in
# the exported directory.
python_action(target_name) {
binary_label = "//build/sdk/generate_idk"
deps = _subbuild_targets
outputs = [
_exported_dir_manifest,
_exported_dir_stamp,
]
# The exported dir is fully under our control and gets deleted by every
# invocation of this build rule.
hermetic_action_ignored_prefixes = [ _exported_dir ]
depfile = "${target_gen_dir}/${target_name}.d"
args = []
foreach(dir, _subbuild_dirs) {
args += [
"--subbuild-directory",
rebase_path(dir, root_build_dir),
]
}
args += [
"--relative-manifest",
_relative_collection_build_manifest,
"--output-directory",
rebase_path(_exported_dir, root_build_dir),
"--stamp-file",
rebase_path(_exported_dir_stamp, root_build_dir),
"--depfile",
rebase_path(depfile, root_build_dir),
"--host-arch",
host_triple,
"--release-version",
sdk_id,
]
foreach(cpu, invoker.target_cpus) {
args += [
"--target-arch",
cpu,
]
}
forward_variables_from(invoker,
[
"testonly",
"visibility",
])
}
}