Commit 7b225fbf authored by Eric Kidd's avatar Eric Kidd
Browse files

Define a custom target and compile our own libcore

Up until now, we've been using the standard `x86_64-unknown-linux-gnu`
target to build our operating system.  This builds normal Linux Rust
binaries which assume that they're running in userspace.

According the http://wiki.osdev.org/Beginner_Mistakes, we _really_ out
to be using a cross-compiler instead:

> Avoid Ignorance
>
> Beginners often ask "What is the easiest way to do X?" rather than
> "What is the best, proper, correct way to do X?". This is dangerous as
> the newcomer doesn't invest time into understanding the superior way
> to implement something, but instead pick a conceptually simpler method
> copied from a tutorial. Indeed, the simpler route is often too simple
> and end up causing more problems in the long run, because the beginner
> is ignorant of the superior alternative and doesn't know when it is
> better to switch. What's so bad about taking the hard route instead?
>
> Common examples include being too lazy to use a Cross-Compiler,
> developing in Real Mode instead of Protected Mode or Long Mode,
> relying on BIOS calls rather than writing real hardware drivers, using
> flat binaries instead of ELF, and so on.

The Rust equivalent using a cross-compiler is to define a custom target
file (`x86_64-unknown-none-gnu.json`, where `none` means "bare metal")
and configure Rust correctly.  Then we need to build a custom libcore.

We do this using a patch from
https://github.com/thepowersgang/rust-barebones-kernel, which we
download and apply to a copy of the Rust source.  From there, it's
possible to get cargo running against `x86_64-unknown-none-gnu.json`,
which is awesome.
parent ee0344f8
/build
/target/
/rust/
# Copied from http://blog.phil-opp.com/rust-os/multiboot-kernel.html
arch ?= x86_64
target ?= $(arch)-unknown-linux-gnu
target ?= $(arch)-unknown-none-gnu
rust_os := target/$(target)/debug/libtoyos.a
kernel := build/kernel-$(arch).bin
......@@ -14,7 +14,13 @@ assembly_source_files := $(wildcard src/arch/$(arch)/*.asm)
assembly_object_files := $(patsubst src/arch/$(arch)/%.asm, \
build/arch/$(arch)/%.o, $(assembly_source_files))
.PHONY: all fmt clean run debug iso cargo
libcore_nofp_patch := build/libcore_nofp.patch
libcore_nofp_url := \
https://raw.githubusercontent.com/thepowersgang/rust-barebones-kernel/master/libcore_nofp.patch
installed_target_libs := \
~/.multirust/toolchains/nightly/lib/rustlib/$(target)/lib
.PHONY: all fmt clean run debug iso cargo core patch
all: $(kernel)
......@@ -22,7 +28,7 @@ fmt:
rustfmt --write-mode overwrite src/lib.rs
clean:
rm -rf build
rm -rf build target
run: $(iso)
@echo QEMU $(iso)
......@@ -48,7 +54,25 @@ $(kernel): cargo $(assembly_object_files) $(linker_script)
cargo:
@echo CARGO
@cargo rustc --target $(target) -- -Z no-landing-pads -C no-redzone
@cargo rustc --target $(target) -- -Z no-landing-pads
patch: $(libcore_nofp_patch)
@echo Patching libcore to remove floating point.
@(cd rust/src/libcore && patch -p1 < ../../../$(libcore_nofp_patch))
$(libcore_nofp_patch):
@echo CURL $(libcore_nofp_patch)
@mkdir -p $(shell dirname $(libcore_nofp_patch))
@curl -o $(libcore_nofp_patch) $(libcore_nofp_url)
core:
@echo RUSTC libcore
@mkdir -p $(installed_target_libs)
@rustc --verbose --target $(target) \
-Z no-landing-pads \
--cfg disable_float \
--out-dir $(installed_target_libs) \
rust/src/libcore/lib.rs
build/arch/$(arch)/%.o: src/arch/$(arch)/%.asm $(assembly_header_files)
@echo NASM $<
......
......@@ -5,3 +5,47 @@ This is based on Philipp Oppermann's
to see what Rust feels like on bare metal.
[blog]: http://blog.phil-opp.com/
[rust-barebones-kernel]: https://github.com/thepowersgang/rust-barebones-kernel
## Building `libcore`
This is largely based on the approach taken by [rust-barebones-kernel][],
but with added support for cargo. The `Makefile` assumes that you're using
a nighly build of run installed by `multirust`, and configured as an
override for the current directory:
```sh
multirust override nightly
```
First, you'll need to get your current version of `rustc`
```
$ rustc --version
rustc 1.6.0-nightly (2e07996a9 2015-10-29)
```
Remember the hexadecimal number in the parentheses, and check out a
matching source tree:
```sh
git clone https://github.com/rust-lang/rust
(cd rust && git checkout 2e07996a9)
```
Now you can try to patch `libcore` and install it where `rustc` and `cargo`
will find it:
```
make patch
make core
```
You may need to manually fix the `libcore` build to hide any new `f32` or
`f63` features behind `#[cfg(not(disable_float))]`.
## Building the kernel
```sh
make run
```
{
"llvm-target": "x86_64-unknown-none-gnu",
"target-endian": "little",
"target-pointer-width": "64",
"os": "none",
"arch": "x86_64",
"data-layout": "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128",
"pre-link-args": [ "-m64" ],
"cpu": "x86-64",
"features": "-mmx,-sse,-sse2,-sse3,-ssse3",
"disable-redzone": true,
"eliminate-frame-pointer": false,
"linker-is-gnu": true,
"no-compiler-rt": true,
"archive-format": "gnu"
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment