minimal_rt_build/lib.rs
1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4#![expect(missing_docs)]
5#![forbid(unsafe_code)]
6
7/// Initializes compiler flags for building a minimal kernel using the
8/// `minimal_rt` crate.
9///
10/// Only does anything if the `MINIMAL_RT_BUILD` environment variable is set.
11///
12/// Also, sets the `minimal_rt` `cfg` so that code can detect that it should
13/// build for running as a minimal kernel.
14pub fn init() -> bool {
15 println!("cargo:rustc-check-cfg=cfg(minimal_rt)");
16
17 // If the user sets this environment variable, build the binary for use as a
18 // boot loader. Otherwise, just build a stub binary for unit tests, clippy,
19 // rust-analyzer, etc.
20 //
21 // We don't use a feature for this because because this would break
22 // `--all-features`. We don't use a profile or something for this because
23 // cargo doesn't want us to know about custom profiles. There's no other
24 // mechanism I know of to communicate this information through cargo.
25 println!("cargo:rerun-if-env-changed=MINIMAL_RT_BUILD");
26 if matches!(
27 std::env::var("MINIMAL_RT_BUILD").as_deref().ok(),
28 None | Some("")
29 ) {
30 return false;
31 }
32
33 let triple = std::env::var("TARGET").unwrap();
34 let unsupported = |supported_triple| {
35 panic!(
36 "build is only supported with the {} target, not {}, clear MINIMAL_RT_BUILD",
37 supported_triple, triple
38 );
39 };
40 // xtask-fmt allow-target-arch sys-crate
41 match std::env::var("CARGO_CFG_TARGET_ARCH").unwrap().as_str() {
42 "x86_64" => {
43 // This is the supported triple for x86-64 because, compared to a
44 // linux target, it disables the red zone (needed to prevent
45 // interrupts from overwriting the stack) and it disables use of SSE
46 // by default (needed to avoid accidentally using SSE intrinstics in
47 // various places).
48 //
49 // No special linker flags are needed.
50 if triple != "x86_64-unknown-none" {
51 unsupported("x86_64-unknown-none");
52 }
53 }
54 "aarch64" => {
55 match triple.as_str() {
56 "aarch64-minimal_rt-none" => {
57 // This is a custom target, defined via
58 // aarch64-minimal_rt-none.json. So, it requires
59 // RUSTC_BOOTSTRAP=1 or an unstable toolchain in order to
60 // use `-Zbuild-std`.
61 //
62 // It is aarch64-unknown-none with support for static PIE
63 // binaries, which we need to support loading the image
64 // anywhere in PA space.
65 }
66 "aarch64-unknown-linux-musl" => {
67 // This target works (it supports static PIE binaries) and
68 // does not require an unstable toolchain, but it is
69 // difficult to build from non-Linux host environments.
70 //
71 // This does require some tweaks to the linker flags.
72 //
73 // Don't include the _start entry point.
74 println!("cargo:rustc-link-arg=-nostartfiles");
75 // Make the executable relocatable.
76 println!("cargo:rustc-link-arg=-static-pie");
77 }
78 _ => {
79 unsupported("aarch64-unknown-linux-musl");
80 }
81 }
82 }
83 arch => panic!("unsupported arch {arch}"),
84 }
85
86 println!("cargo:rustc-cfg=minimal_rt");
87 true
88}