Porting Rust standard library
Difficulty level |
---|
![]() Beginner |
|
Contents |
Guide
This guide shows how to get the standard library to compile for a custom target, though it won't be functional yet.
By the end you should be able to compile a project with
cargo +dev-x86_64-unknown-myos r --target x86_64-unknown-myos
Get sources
git clone https://github.com/rust-lang/rust
Configuration & add target
# config.toml profile = "user" changelog-seen = 2 [build] host = ["x86_64-unknown-linux-gnu"] target = ["x86_64-unknown-linux-gnu", "x86_64-unknown-myos"] [rust] incremental = true
// compiler/rustc_target/src/spec/myos_base.rs use crate::spec::{LinkerFlavor, LldFlavor, TargetOptions}; pub fn opts() -> TargetOptions { TargetOptions { os: "myos".into(), executables: true, linker: Some("ld.lld".into()), linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld), stack_probes: StackProbeType::Inline, ..Default::default() } }
// compiler/rustc_target/src/spec/x86_64_unknown_myos.rs use crate::spec::{Target, PanicStrategy}; pub fn target() -> Target { let mut base = super::myos_base::opts(); base.cpu = "x86-64".into(); base.disable_redzone = true; base.panic_strategy = PanicStrategy::Abort; base.features = "-mmx,-sse,+soft-float".into(); Target { llvm_target: "x86_64-unknown-none".into(), pointer_width: 64, data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128".into(), arch: "x86_64".into(), options: base, } }
--- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -73,6 +73,7 @@ mod linux_uclibc_base; mod msvc_base; mod netbsd_base; +mod myos_base; mod openbsd_base; mod redox_base; mod solaris_base; @@ -1023,6 +1024,8 @@ fn $module() { ("x86_64-unknown-none", x86_64_unknown_none), ("mips64-openwrt-linux-musl", mips64_openwrt_linux_musl), + + ("x86_64-unknown-myos", x86_64_unknown_myos), } /// Warnings encountered when parsing the target `json`.
Adapt library/std
--- a/library/std/build.rs +++ b/library/std/build.rs @@ -29,6 +29,7 @@ fn main() { || target.contains("asmjs") || target.contains("espidf") || target.contains("solid") + || target.contains("myos") { // These platforms don't have any special requirements. } else {
Copy library/std/src/sys/unsupported
to library/std/src/sys/myos
.
--- a/library/std/src/sys_common/mod.rs +++ b/library/std/src/sys_common/mod.rs @@ -39,6 +39,7 @@ cfg_if::cfg_if! { if #[cfg(any(target_os = "l4re", target_os = "hermit", + target_os = "myos", feature = "restricted-std", all(target_family = "wasm", not(target_os = "emscripten")), all(target_vendor = "fortanix", target_env = "sgx")))] {
Add toolchain
rustup toolchain link dev-x86_64-unknown-myos ~/Documents/rust/rust/build/x86_64-unknown-linux-gnu/stage2
Runtime
Integrating a crate
If you use a crate for the runtime (e.g. myos_rt
), you can add it as a dependency to the standard library:
[target.'cfg(target_os = "myos")'.dependencies] myos_rt = { version = "*", features = ["rustc-dep-of-std"] }
The rustc-dep-of-std
feature is necessary since libcore
et al. don't exist yet.
Modify the Cargo.toml
of your runtime library to include the feature and propagate it up, e.g.:
[dependencies] cfg-if = "1.0" core = { version = "1.0.0", optional = true, package = "rustc-std-workspace-core" } compiler_builtins = { version = "0.1", optional = true } [features] rustc-dep-of-std = [ "core", "compiler_builtins", "cfg-if/rustc-dep-of-std" ]
Do keep in mind that the same crate with different feature flags are seen as different crates by the compiler. This means that if you any globals in the runtime crate and have a project that uses both stdlib and your runtime crate there will be two separate sets of those globals. One way to work around this is by giving these globals an explicit name with #[export_name = "__rt_whatever"]
and weakly linking them with #[linkage = "weak"]
.
Troubleshooting
error[E0463]: can't find crate for `compiler_builtins`
Add compiler_builtins
as a dependency for the crates you use in stdlib, e.g.:
[dependencies] core = { version = "1.0.0", optional = true, package = "rustc-std-workspace-core" } compiler_builtins = { version = "*", optional = true } # <-- [features] rustc-dep-of-std = [ "core", "compiler_builtins/rustc-dep-of-std", # <-- ]