blob: 13621b425bfab6d0b5dc81c5557e2a1d9fe5b9b4 [file]
# Copyright 2026 The Fuchsia Authors
#
# Use of this source code is governed by a MIT-style
# license that can be found in the LICENSE file or at
# https://opensource.org/licenses/MIT
import("//build/config/current_target_tuple.gni")
import("//build/rust/config.gni")
import("//build/toolchain/toolchain_environment.gni")
import("//build/zircon/c_utils.gni")
import("//zircon/kernel/kernel_rust_mod.gni")
import("//zircon/kernel/params.gni")
import("//zircon/kernel/phys/kernel_elf_binary.gni")
_kernel_executable_deps = [
"//zircon/kernel/lib/syscalls:syscalls-rs",
"//zircon/kernel/top",
]
_kernel_executable_cpu_deps = {
arm64 = [ "//zircon/kernel/platform/generic-arm" ]
riscv64 = [ "//zircon/kernel/platform/generic-riscv64" ]
x64 = [ "//zircon/kernel/platform/pc" ]
}
# These the implicit subtargets kernel_rust_mod_crate_root() already produces.
# So separate generated_file() targets aren't needed to plumb clippy switches.
_clippy_rsp_inputs = [
{
switch = "--deps="
key = "kernel_rust_externs"
},
{
switch = "--transdeps="
key = "rust_aux_searchdir"
},
]
_static_checks_toolchain =
"//zircon/kernel/switch/set/static-checks:kernel_$current_cpu.static-checks"
# Represents a kernel executable (i.e., a kernel in ELF form) evaluated under
# the current switchset.
#
# Subtargets
#
# * $target_name.clippy
# - The action() target that runs the clippy Rust code linter. This is
# done implicitly via $validations on $target_name but can be done alone.
#
# * $target_name.rsp
# - The link_output_rspfile() containing the output name of the kernel
# executable.
#
# Parameters
#
# * configs
# - Required: Preset via set_defaults() and modifiable as usual.
# - Type: list(label_no_toolchain)
# - Default: via set_defaults()
#
# * deps
# - Optional: Additional sources to link into the kernel.
# - Type: list(label)
# - Default: []
#
# * data_deps
# - Optional: Can be used to bring extra files into the kernel package or
# extra ZBI items into the image.
# - Type: list(label)
# - Default: []
#
# * testonly, visibility
# - Optional: Standard GN meanings.
#
template("kernel_executable") {
assert(toolchain_environment == "kernel",
"kernel_executable() can only be used in the kernel environment")
main_target = target_name
validate_symbols_target = "_kernel_executable.$target_name.validate"
crate_root_target = "_kernel_executable.$target_name.crate_root"
clippy_target = "$target_name.clippy"
rsp_target = "$target_name.rsp"
_kernel_deps =
_kernel_executable_deps + _kernel_executable_cpu_deps[current_cpu]
if (defined(invoker.deps)) {
_kernel_deps += invoker.deps
}
kernel_rust_mod_crate_root(crate_root_target) {
executable_target = main_target
visibility = [ ":*" ]
forward_variables_from(invoker, [ "testonly" ])
deps = _kernel_deps
}
_crate_vars = {
# GN makes an executable() use Rust if its $sources list any Rust files.
crate_type = "bin"
deps = [ ":$crate_root_target" ]
sources = [ "//zircon/kernel/main.rs" ]
crate_root = sources[0]
rustflags = [
"--edition=2024",
# Disambiguate rustc's intermediate object filenames across kernel
# executables that share crate name and source root.
"-Cmetadata=$main_target",
]
# The binary crate is always called "kernel" in every target.
crate_name = "kernel"
forward_variables_from(invoker,
[
"configs",
"testonly",
"visibility",
])
if (defined(visibility)) {
visibility += [ ":*" ]
}
}
action(clippy_target) {
mnemonic = "CLIPPY"
forward_variables_from(_crate_vars, "*")
deps += [ "//zircon/kernel/lib/rust:rust-custom-target" ]
# Prevent distribution_entries from dependency crates evaluated in other
# toolchains (such as static-checks referenced via validations) from leaking
# into production kernel packages during packaging metadata walks.
metadata = {
distribution_entries_barrier = []
}
rustflags += [
"--crate-type=$crate_type",
"--crate-name=$crate_name",
"-Cmetadata=clippy",
]
script = "//build/rust/clippy_wrapper.py"
outputs = [ "$target_gen_dir/$clippy_target" ]
args = [ "--output=" + rebase_path(outputs[0], root_build_dir) ]
depfile = "${outputs[0]}.d"
args += [ "--depfile=" + rebase_path(depfile, root_build_dir) ]
inputs = [ "//prebuilt/third_party/jq/${host_platform}/bin/jq" ]
args += [ "--jq=" + rebase_path(inputs[0], root_build_dir) ]
# Reuse the generated_file() targets kernel_rust_mod_crate_root() emitted.
foreach(rsp, _clippy_rsp_inputs) {
rsp.label = ":$crate_root_target.${rsp.key}.rsp"
_rsp_outputs = [] # Reset from last iteration.
_rsp_outputs = get_target_outputs(rsp.label)
assert(_rsp_outputs == [ _rsp_outputs[0] ])
deps += [ rsp.label ]
inputs += _rsp_outputs
args += [ rsp.switch + rebase_path(_rsp_outputs[0], root_build_dir) ]
}
if (clippy_cause_failure) {
args += [ "--fail" ]
}
if (clippy_ignore_rustc) {
args += [ "--clippy-only" ]
}
args += [
"--",
"env",
"{{rustenv}}",
"${rebased_rustc_prefix}/bin/clippy-driver",
rebase_path(crate_root, root_build_dir),
"{{rustflags}}",
]
}
kernel_elf_binary(main_target) {
forward_variables_from(_crate_vars, "*")
deps += [ "//zircon/kernel/phys:physboot.kernel" ]
install_name = "vmzircon"
validations = [
":$validate_symbols_target",
# Always do the Clippy checks to be sure that this exact configuration is
# fully checked.
":$clippy_target",
]
# Additionally run Clippy in the static-checks switchset (which maximizes
# checks and compiles in ktest unit tests). Only testonly executables can
# depend on the test libraries instantiated in static-checks.
if (defined(invoker.testonly) && invoker.testonly &&
current_toolchain != _static_checks_toolchain) {
validations += [ ":$clippy_target($_static_checks_toolchain)" ]
}
}
rspfile = "$target_gen_dir/$main_target.rsp"
link_output_rspfile(rsp_target) {
forward_variables_from(invoker,
[
"testonly",
"visibility",
])
if (defined(visibility)) {
visibility += [ ":$validate_symbols_target" ]
}
deps = [ ":$main_target.binary" ]
outputs = [ rspfile ]
}
toolchain_utils_action(validate_symbols_target) {
forward_variables_from(invoker, [ "testonly" ])
visibility = [ ":*" ]
outputs = [ "$target_gen_dir/$target_name.stamp" ]
script = "//zircon/kernel/scripts/validate-kernel-symbols.py"
utils = [ "nm" ]
deps = [
":$main_target.binary",
":$rsp_target",
]
sources = [ rspfile ]
depfile = "$target_gen_dir/$target_name.d"
args = rebase_path(sources + outputs + [ depfile ], root_build_dir)
}
}
set_defaults("kernel_executable") {
configs = default_executable_configs +
[ "//zircon/kernel/switch:kernel_executable.config" ]
}