std now builds with latest nightly of cosmo

This commit is contained in:
ahgamut 2022-06-22 22:39:06 +05:30
parent f6ae82160c
commit 2f9973a168
5 changed files with 55 additions and 123 deletions

View file

@ -13,7 +13,10 @@ use `rustc` or equivalent compiler to generate `.o` files, and then write a
shell script that does the linking with the expected flags. I have not tried
this method.
## Build steps
> a previous attempt at a Rust APE was done without using the `std` crate. You
can view that in the [`without-std` branch of this repo][without-std-branch].
## Building a Rust APE with the `std` crate
1. Download the Cosmopolitan Libc [amalgamation][amalg-download] into the `libcosmo` folder:
@ -24,10 +27,13 @@ unzip cosmopolitan.zip
cd ../
```
2. Download the necessary *host* toolchain and source code for Rust:
For reference, I used the nightly version of `cosmopolitan.a` from June 22 2022,
which can be built from source if needed from [this commit][cosmo-nightly].
2. Download the necessary host toolchain and source code for Rust:
```bash
# I was on Debian, so I did this
# I was on Debian 11, so I did this
rustup toolchain install nightly-x86_64-unknown-linux-gnu
rustup component add rust-src --toolchain nightly-x86_64-unknown-linux-gnu
# on Alpine Linux, you may need to do
@ -35,39 +41,71 @@ rustup toolchain install nightly-x86_64-unknown-linux-musl
rustup component add rust-src --toolchain nightly-x86_64-unknown-linux-musl
```
For reference, I used the nightly version of Rust from June 22 2022.
3. run `cargo build` to get the debug executable. This uses a bash script that
removes unnecessary linker arguments. A recent version of `gcc` and `ld.bfd`
is required.
```bash
cargo +nightly build -Zbuild-std=core,libc --target=./x86_64-unknown-linux-cosmo.json
cargo +nightly build -Zbuild-std=panic_abort,std -Zbuild-std-features="" --target=./x86_64-unknown-linux-cosmo.json
```
For reference, I used the below versions of `gcc` and `ld.bfd`
```
gcc (Debian 10.2.1-6) 10.2.1 20210110
Copyright (C) 2020 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
```
```
GNU ld (GNU Binutils for Debian) 2.35.2
Copyright (C) 2020 Free Software Foundation, Inc.
This program is free software; you may redistribute it under the terms of
the GNU General Public License version 3 or (at your option) a later version.
This program has absolutely no warranty.
```
4. run `objcopy` on the debug binary to obtain the APE:
```bash
# objcopy is the same version as ld.bfd above
objcopy -SO binary ./target/x86_64-unknown-linux-cosmo/debug/hello_world.com.dbg ./hello_world.com
# run the APE
./hello_world.com
# see syscalls made by the APE
./hello_world.com --strace
```
## What about the `std` crate?
Now we have an Actually Portable Executable built with Rust! There might some
edge cases that I haven't noticed, so clone/fork the repo and try it out! The
[`without-std` branch][without-std-branch] of this repo might be useful.
1. It needs a few stubs functions so the linker doesn't complain. I wrote them
out in `stubs.c`.
## TODOs
```bash
cd ./libcosmo/
# compiling a simple stub file via cosmopolitan.h
./compile-stubs.bash
```
- [ ] figure out build config to avoid using `libunwind`
2. The build command now changes to
The `std` crate relies on
[`backtrace`](https://github.com/rust-lang/backtrace-rs), which depends on
[`libunwind`](https://github.com/libunwind/libunwind) in the default builds for
unix. To work around this, `cosmopolitan.a` currently has stubs for the
functions that `backtrace` relies on. However, it might be easier to provide a
build flag in `Cargo.toml` to use the `noop` module of `backtrace`.
```bash
cargo +nightly build -Zbuild-std=core,alloc,panic_abort,libc,std -Zbuild-std-features= --target=./x86_64-unknown-linux-cosmo.json
```
A small change needs to be submitted to the source code of `backtrace` (in the
`cfg_if!`
[here](https://github.com/rust-lang/backtrace-rs/blob/4e5a3f72929f152752d5659e95bb15c8f6b41eff/src/backtrace/mod.rs#L128))
to allow choosing `noop` when building as part of the `std` crate. This
conditional compilation flag should be accessible when building the `std` crate
either via `Cargo.toml` or something like `-Z use-std-backtrace-noop` in the
build command.
[without-std-branch]: https://github.com/ahgamut/rust-ape-example/tree/without-std
[rust]: https://rust-lang.org
[cosmo]: https://github.com/jart/cosmopolitan
[cosmo-nightly]: https://github.com/jart/cosmopolitan
[amalg-download]: https://justine.lol/cosmopolitan/download.html
[custom-target]: https://doc.rust-lang.org/rustc/targets/custom.html
[custom-embed]: https://docs.rust-embedded.org/embedonomicon/custom-target.html

View file

@ -1,7 +0,0 @@
#!/usr/bin/env bash
set -eux
gcc -g -Os -static -nostdlib -nostdinc \
-fno-pie -no-pie -mno-red-zone \
-fno-omit-frame-pointer -pg -mnop-mcount \
-o ./stubs.o -c ./stubs.c

View file

@ -1,98 +0,0 @@
#include "cosmopolitan.h"
typedef enum {
_URC_NO_REASON = 0,
_URC_FOREIGN_EXCEPTION_CAUGHT = 1,
_URC_FATAL_PHASE2_ERROR = 2,
_URC_FATAL_PHASE1_ERROR = 3,
_URC_NORMAL_STOP = 4,
_URC_END_OF_STACK = 5,
_URC_HANDLER_FOUND = 6,
_URC_INSTALL_CONTEXT = 7,
_URC_CONTINUE_UNWIND = 8
} _Unwind_Reason_Code;
#define UNW_TDEP_CURSOR_LEN 127
typedef uint64_t unw_word_t;
typedef struct unw_cursor {
unw_word_t opaque[UNW_TDEP_CURSOR_LEN];
} unw_cursor_t;
struct _Unwind_Context {
unw_cursor_t cursor;
int end_of_stack;
};
typedef _Unwind_Reason_Code (*_Unwind_Trace_Fn)(struct _Unwind_Context *,
void *);
uintptr_t _Unwind_GetCFA(struct _Unwind_Context *ctx) {
return 0;
}
uintptr_t _Unwind_GetIP(struct _Unwind_Context *ctx) {
return 0;
}
_Unwind_Reason_Code _Unwind_Backtrace(_Unwind_Trace_Fn fn, void *arg) {
return _URC_NORMAL_STOP;
}
void *_Unwind_FindEnclosingFunction(void *arg) {
return NULL;
}
#define MAX_KEYS 64
typedef unsigned pthread_key_t;
typedef void (*dtor)(void*);
typedef struct {
pthread_key_t kval;
dtor d;
void *value;
} tls_t;
static tls_t my_tls[MAX_KEYS] = {0};
static unsigned thread_avail = 0;
int pthread_key_create(pthread_key_t *k, dtor destructor) {
for(pthread_key_t i=1; i<MAX_KEYS; i++) {
if(my_tls[i].kval == 0) {
*k = i;
my_tls[i].kval = i;
my_tls[i].d = destructor;
return 0;
}
}
return -1;
}
void* pthread_getspecific(pthread_key_t k) {
if(k < MAX_KEYS) {
return my_tls[k].value;
}
return NULL;
}
int pthread_setspecific(pthread_key_t k, const void* value) {
if(k < MAX_KEYS) {
my_tls[k].value = value;
return 0;
}
return -1;
}
int pthread_key_delete(pthread_key_t k) {
if (k < MAX_KEYS) {
my_tls[k].kval = 0;
return 0;
}
return -1;
}
int __xpg_strerror_r(int a, char *b, size_t c) {
return strerror_r(a, b, c);
}

View file

@ -26,5 +26,5 @@ fn my_panic(_info: &core::panic::PanicInfo) -> ! {
#![feature(restricted_std)]
pub fn main() {
println!("hello pls cosmo rust APE");
println!("Hello World! This is an APE built with Rust.");
}

View file

@ -49,7 +49,6 @@
"-fuse-ld=bfd",
"-Wl,-T,./libcosmo/ape.lds",
"./libcosmo/crt.o",
"./libcosmo/stubs.o",
"./libcosmo/ape-no-modify-self.o",
"./libcosmo/cosmopolitan.a"
]