blob: be3335fe2ce8d269211c3a9ae679d86288a87907 [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/toolchain/toolchain_environment.gni")
import("//build/zircon/c_utils.gni")
import("//zircon/kernel/params.gni")
import("//zircon/kernel/phys/kernel_elf_binary.gni")
_kernel_executable_deps = [
"//zircon/kernel/phys:physboot.kernel",
"//zircon/kernel/top",
]
_kernel_executable_cpu_deps = {
arm64 = [ "//zircon/kernel/platform/generic-arm" ]
riscv64 = [ "//zircon/kernel/platform/generic-riscv64" ]
x64 = [ "//zircon/kernel/platform/pc" ]
}
# Represents a kernel executable (i.e., a kernel in ELF form) evaluated under
# the current switchset.
#
# Subtargets
#
# * $target_name.rsp
# The link_output_rspfile() containing the output name of the kernel
# executable.
#
# Parameters
#
# * 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"
rsp_target = "$target_name.rsp"
_kernel_deps =
_kernel_executable_deps + _kernel_executable_cpu_deps[current_cpu]
if (defined(invoker.deps)) {
_kernel_deps += invoker.deps
}
if (enable_rust_in_zircon) {
# kernel_rust_crate() leaves metadata breadcrumbs to be collected here.
extern_crate_decls_file = "$target_out_dir/$target_name.extern-crates.rs"
extern_crate_flags_file = "$target_out_dir/$target_name.extern-crates.rsp"
generated_file("$target_name.extern-crates.rs") {
visibility = [ ":*" ]
forward_variables_from(invoker, [ "testonly" ])
outputs = [ extern_crate_decls_file ]
output_conversion = "list lines"
# Every kind of Rust target has a link_output_barrier, so this won't look
# past any rustc_library() to see another kernel_rust_crate() it depends
# on, which should be correct: Linking the executable only needs to know
# about C++ -> Rust deps; any Rust -> Rust deps were handled earlier.
walk_keys = [ "link_output_barrier" ]
data_keys = [ "kernel_rust_crate_decls" ]
deps = _kernel_deps
}
generated_file("$target_name.extern-crates.rsp") {
visibility = [ ":*" ]
forward_variables_from(invoker, [ "testonly" ])
outputs = [ extern_crate_flags_file ]
output_conversion = "list lines"
walk_keys = [ "link_output_barrier" ]
data_keys = [ "kernel_rust_crate_flags" ]
deps = _kernel_deps
}
_kernel_deps += [
":$target_name.extern-crates.rs",
":$target_name.extern-crates.rsp",
]
}
kernel_elf_binary(main_target) {
forward_variables_from(invoker,
[
"testonly",
"visibility",
])
if (defined(visibility)) {
visibility += [ ":*" ]
}
install_name = "vmzircon"
configs += [ "//zircon/kernel/switch:kernel_executable.config" ]
deps = _kernel_deps
validations = [ ":$validate_symbols_target" ]
if (enable_rust_in_zircon) {
# GN will consider an executable() target to be C++ regardless of what
# mix of Rust and C++ link inputs are in the deps graph, unless it
# directly lists Rust source files. So inject a single Rust source file
# here just to force this to be a Rust executable() that can have other
# Rust link inputs other than static_library() (via rustc_staticlib()).
crate_type = "bin"
crate_root = "//zircon/kernel/bin/src/main.rs"
sources = [ crate_root ]
# The binary crate is always called "kernel_main" in every target. This
# crate is not expected to define any normal Rust symbols (only the entry
# point function C symbol). It is never referenced in Rust sources.
crate_name = "kernel_main"
# This provides `extern crate name;` for each kernel_rust_crate().
inputs = [ extern_crate_decls_file ]
rustenv = [ "ZIRCON_EXTERN_CRATE_DECLS=" +
rebase_path(extern_crate_decls_file, root_build_dir) ]
# The code includes that file via the rustenv_path::envpath! proc macro.
deps += [ "//zircon/kernel/bin/rustenv_path" ]
# This provides the corresponding `--extern name=.../libname.rlib`.
# These are only needed because GN doesn't propagate the indirect deps to
# {{externs}} in tool("rust_bin"). It does produce necessary order-only
# deps that ensure the rlib is up to date, and rustc's depfile support
# provides the Ninja file dependency.
inputs += [ extern_crate_flags_file ]
rustflags = [ "@" + rebase_path(extern_crate_flags_file, root_build_dir) ]
}
}
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)
}
}