Porting Rust standard library: Difference between revisions

Format article source and remove use of deprecated <source> tag
[unchecked revision][unchecked revision]
(Add instructions on making the PAL functional)
(Format article source and remove use of deprecated <source> tag)
Line 1:
{{Ratingrating|1}}
{{template:In_Progress}}
 
Line 7:
 
By the end you should be able to compile a project with
<sourcesyntaxhighlight lang="bash">
cargo +dev-x86_64-unknown-myos r --target x86_64-unknown-myos
</syntaxhighlight>
</source>
 
===Get sources===
 
<sourcesyntaxhighlight lang="bash">
git clone https://github.com/rust-lang/rust
</syntaxhighlight>
</source>
 
===Configuration===
 
<sourcesyntaxhighlight lang="ini">
# config.toml
profile = "compiler"
Line 30:
[rust]
incremental = true
</syntaxhighlight>
</source>
 
===Adding the target===
Line 37:
In addition, the rust compiler must be given a path to a valid crt0 object file. Rustc does not supply a <code>_start</code> symbol of its own, and the defalt linker doesn't provide one either, so we must provide our own. (TODO: Figure out self-contained linking of the crt0).
 
<sourcesyntaxhighlight lang="rust">
// compiler/rustc_target/src/spec/base/myos.rs
use crate::spec::crt_objects;
Line 54:
}
}
</syntaxhighlight>
</source>
 
 
<sourcesyntaxhighlight lang="rust">
// compiler/rustc_target/src/spec/targets/x86_64_unknown_myos.rs
use crate::spec::{base, PanicStrategy, Target, TargetMetadata};
Line 82 ⟶ 83:
}
}
</source><syntaxhighlight lang="diff">
 
 
<syntaxhighlight lang="diff">
--- a/compiler/rustc_target/src/spec/base/mod.rs
+++ b/compiler/rustc_target/src/spec/base/mod.rs
Line 93 ⟶ 97:
pub(crate) mod nto_qnx;
pub(crate) mod openbsd;
</syntaxhighlight><source lang="diff">
 
 
<syntaxhighlight lang="diff">
--- a/compiler/rustc_target/src/spec/mod.rs
+++ b/compiler/rustc_target/src/spec/mod.rs
Line 103 ⟶ 110:
+
}
</source><syntaxhighlight lang="diff">
 
 
<syntaxhighlight lang="diff">
--- a/compiler/rustc_target/src/spec/crt_objects.rs
+++ b/compiler/rustc_target/src/spec/crt_objects.rs
Line 163 ⟶ 173:
 
===Adapt library/std===
In addition to rustc, std must also be modified to support the target. By default, std will error on build if the OS isn't explicitly supported, so we must add our OS to the list of supported OSes. In addition, we must provide a PAL (Platform Abstraction Layer) to tell std how to interact with our OS.<source lang="diff">
<syntaxhighlight lang="diff">
--- a/library/std/build.rs
+++ b/library/std/build.rs
Line 174 ⟶ 185:
// See src/bootstrap/src/core/build_steps/synthetic_targets.rs
|| env::var("RUSTC_BOOTSTRAP_SYNTHETIC_TARGET").is_ok()
</syntaxhighlight>
</source>
 
Copy <code>library/std/src/sys/pal/unsupported</code> to <code>library/std/src/sys/pal/myos</code>.
 
<sourcesyntaxhighlight lang="diff">
--- a/library/std/src/sys/pal/mod.rs
+++ b/library/std/src/sys/pal/mod.rs
Line 191 ⟶ 202:
mod unsupported;
pub use self::unsupported::*;
</syntaxhighlight>
</source>
 
===Add toolchain===
 
<sourcesyntaxhighlight lang="bash">
rustup toolchain link dev-x86_64-unknown-myos ~/Documents/rust/rust/build/x86_64-unknown-linux-gnu/stage2
</syntaxhighlight>
</source>
 
==Making the standard library functional==
Line 243 ⟶ 254:
====Global statics (easiest, single-threaded only) ====
{{Warning | This WILL not work on multi-threaded systems.}}
If your OS is single-threaded or you don't want to implement full TLS before adding multithreading to your PAL, Rust can implement TLS via global statics. <syntaxhighlight lang="diff">
<syntaxhighlight lang="diff">
--- a/library/std/src/sys/thread_local/mod.rs
+++ b/library/std/src/sys/thread_local/mod.rs
Line 261 ⟶ 273:
 
====Native ELF TLS (fastest)====
This option is the fastest way of doing TLS, but requires more complex suport from the OS. To implement it, see the linked wiki article on TLS. Enabling it in rustc is done by adding a target option for your OS.<syntaxhighlight lang="diff">
<syntaxhighlight lang="diff">
--- a/compiler/rustc_target/src/spec/base/myos.rs
+++ b/compiler/rustc_target/src/spec/base/myos.rs
Line 279 ⟶ 292:
Adding print support is fairly simple given the architecture of the PAL, and merly requires filling out the Write implementations of stdout/err in <code>stdio.rs</code>. In addition, the panic_output function shoudl be set to the desired output stream for panic messages, usually stderr.
 
Example code is provided below. The given code assumes syscalls are done with interrupt 0x80 with the number in rax and the first parameter in rcx, and syscall 0 takes a byte to write to some text output device. You will probably need to change the syscall number and parameters for your OS, but this should be a basic starting point.<syntaxhighlight lang="diff">
<syntaxhighlight lang="diff">
--- a/library/std/src/sys/pal/myos/stdio.rs
+++ b/library/std/src/sys/pal/myos/stdio.rs
Line 320 ⟶ 334:
+ Some(Stderr::new())
}
</syntaxhighlight>
</syntaxhighlight>Now you should be able to compile and run the default Rust hello world program for your target and see it print to screen.
 
==Runtime==
Line 328 ⟶ 343:
If you use a crate for the runtime (e.g. <code>myos_rt</code>), you can add it as a dependency to the standard library:
 
<sourcesyntaxhighlight lang="initoml">
[target.'cfg(target_os = "myos")'.dependencies]
myos_rt = { version = "*", features = ["rustc-dep-of-std"] }
</syntaxhighlight>
</source>
 
The <code>rustc-dep-of-std</code> feature is necessary since <code>libcore</code> et al. don't exist yet.
Line 337 ⟶ 352:
Modify the <code>Cargo.toml</code> of your runtime library to include the feature and propagate it up, e.g.:
 
<sourcesyntaxhighlight lang="initoml">
[dependencies]
cfg-if = "1.0"
Line 349 ⟶ 364:
"cfg-if/rustc-dep-of-std"
]
</syntaxhighlight>
</source>
 
Do keep in mind that the same crate with different feature flags are seen as [https://github.com/rust-lang/cargo/issues/2363 <strong>different crates</strong> 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 <code>#[export_name = "__rt_whatever"]</code> and weakly linking them with <code>#[linkage = "weak"]</code>.
Line 359 ⟶ 374:
Add <code>compiler_builtins</code> as a dependency for the crates you use in stdlib, e.g.:
 
<sourcesyntaxhighlight lang="ini">
[dependencies]
core = { version = "1.0.0", optional = true, package = "rustc-std-workspace-core" }
Line 369 ⟶ 384:
"compiler_builtins/rustc-dep-of-std", # <--
]
</syntaxhighlight>
</source>
 
[[Category:Rust]]
Anonymous user