Skip to content

Commit

Permalink
add nostd test crate
Browse files Browse the repository at this point in the history
  • Loading branch information
jordanisaacs committed Feb 6, 2023
1 parent 61c9cc1 commit 675f53b
Show file tree
Hide file tree
Showing 4 changed files with 85 additions and 0 deletions.
14 changes: 14 additions & 0 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -192,3 +192,17 @@ jobs:
cargo +nightly-2022-11-17 run --target=${{ matrix.host_target }}
env:
RUST_BACKTRACE: 1

- name: test mustang-nostd as program
working-directory: test-crates/mustang-nostd
run: |
cargo +nightly-2022-11-17 run -Zbuild-std=core,alloc --target=../../mustang/target-specs/${{ matrix.mustang_target }}.json
env:
RUST_BACKTRACE: 1

- name: test mustang-nostd as tests
working-directory: test-crates/mustang-nostd
run: |
cargo +nightly-2022-11-17 test -Zbuild-std=core,alloc,test,std --target=../../mustang/target-specs/${{ matrix.mustang_target }}.json
env:
RUST_BACKTRACE: 1
12 changes: 12 additions & 0 deletions test-crates/mustang-nostd/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
[package]
name = "mustang-nostd"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
# The mustang crate provides the `can_run_this!()` macro.
mustang = { path = "../../mustang", default-features = false, features = ["threads", "default-alloc"] }

[workspace]
21 changes: 21 additions & 0 deletions test-crates/mustang-nostd/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
This crate demonstrates the use of mustang with no_std. Specifying `-Zbuild-std=core,alloc` lets you skip compiling std as it will not be used:

```
cargo run --target=x86_64-mustang-linux-gnu -Zbuild-std=core,alloc
```

This line:

```toml
mustang = { path = "../../mustang", default-features = false, features = ["threads", "default-alloc"] }
```

tells cargo to not enable the "std" feature which results in no dependencies on std. c-gull will re-export the no-std version of c-scape. c-scape is still necessary because `dlmalloc` and `unwinding` rely on some libc functionality. `dlmalloc` uses libc for syscalls and needs a pthread implementation for `GlobalAlloc`. `unwinding` uses the libc `dl_iterate_phdr` function, see [comment](https://github.com/sunfishcode/mustang/blob/bf6b53a4c5edd1dec71fa65f468b2c76ff96eb62/mustang/Cargo.toml#L19).

You can use either `#[start]` or replacing the C shim as in the example. See the unstable book for more [details](https://doc.rust-lang.org/unstable-book/language-features/lang-items.html#writing-an-executable-without-stdlib). It may or may not be undefined behavior to call `panic!()` from the function as no catch_unwind has been set, see the start feature [tracking issue](https://github.com/rust-lang/rust/issues/29633) and [following issue](https://github.com/rust-lang/rust/issues/107381).

To use tests, make sure to also compile test and std:

```
cargo test --target=x86_64-mustang-linux-gnu -Zbuild-std=core,alloc,std,test
```
38 changes: 38 additions & 0 deletions test-crates/mustang-nostd/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
#![feature(lang_items)]
#![no_std]
// When testing we do not want to use our main function
#![cfg_attr(not(test), no_main)]

mustang::can_run_this!();

use core::ffi::c_int;

#[cfg(not(test))]
#[panic_handler]
fn panic(_panic: &core::panic::PanicInfo<'_>) -> ! {
loop {}
}

#[cfg(not(test))]
#[lang = "eh_personality"]
extern "C" fn eh_personality() {}

// Small hack for rust-analyzer.
//
// If we do `#[cfg(not(test))]` then rust-analyzer will say the code is inactive and we
// lose the ability to use rust-analyzer.
// By disabling `no_mangle` during test, we do not get the two main functions defined error.
// This function ends up just behaving like any other (unused) function in the binary during
// test compilation.
//
// Using `#[start]` would not require us to use this hack but then we lose `_envp`
// function parameter.
#[cfg_attr(not(test), no_mangle)]
extern "C" fn main(_argc: c_int, _argv: *mut *mut u8, _envp: *mut *mut u8) -> c_int {
0
}

#[test]
fn test_tests() {
assert_eq!(1, 1)
}

0 comments on commit 675f53b

Please sign in to comment.