| # 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) |
| } |
| } |