Porting Rust standard library

From OSDev Wiki
Jump to: navigation, search
Difficulty level
Difficulty 1.png
Beginner

This page is under construction! This page or section is a work in progress and may thus be incomplete. Its content may be changed in the near future.

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", # <--
]
Personal tools
Namespaces
Variants
Actions
Navigation
About
Toolbox