Eyra is a package that supports building Rust programs implemented entirely
in Rust.
It uses [Origin] for program and thread startup and shutdown, and [c-gull] for
ABI-compatible libc function implementations. It currently works on
Nightly Rust on Linux on x86-64, x86, aarch64, and riscv64.
[Origin]: https://github.com/sunfishcode/origin#readme
[c-gull]: https://github.com/sunfishcode/c-ward/tree/main/c-gull#readme
## Quick start
Running a Rust program under Eyra needs two steps. First, a Cargo.toml
dependency, which we can add with:
```console
cargo add eyra --rename=std
```
And, a build.rs file to add `-nostartfiles` to the link flags to disable the
host startup code, so that Eyra can provide its own. build.rs:
```rust,no_run
fn main() {
println!("cargo:rustc-link-arg=-nostartfiles");
}
```
With that, `cargo build`, `cargo run`, `cargo test` (with Nightly) and so on
will work normally with any `*-unknown-linux-gnu*` target.
Under the covers, it's using [Origin] to start and stop the program, [c-ward]
to handle libc calls from `std`, and [rustix] to do the printing, so it's
completely implemented in Rust.
## Examples
For an example of the above steps, check out [this hello world example].
Other examples include
- [enabling LTO],
- [using min-sized-rust technique to produce small binaries], and
- [adding Eyra as an optional dependency].
- [building a program completely from source].
[this hello world example]: https://github.com/sunfishcode/eyra/tree/main/example-crates/hello-world#readme
[enabling LTO]: https://github.com/sunfishcode/eyra/tree/main/example-crates/hello-world-lto#readme
[using min-sized-rust technique to produce small binaries]: https://github.com/sunfishcode/eyra/tree/main/example-crates/hello-world-small#readme
[adding Eyra as an optional dependency]: https://github.com/sunfishcode/eyra/tree/main/example-crates/eyra-optional-example#readme
[building a program completely from source]: https://github.com/sunfishcode/eyra/tree/main/example-crates/all-from-source#readme
## Why?
Why use Eyra?
- It fixes Rust's [`set_var` unsoundness issue]. The environment-variable
implementation leaks memory internally (it is optional, but enabled by
default), so `setenv` etc. are thread-safe.
- [Whole-program LTO], including the libc. This sometimes produces smaller
static binaries, and sometimes produces faster code (though on the other
hand, sometimes it doesn't, though on the first hand, there are still
low-hanging fruit, so consider trying it and filing issues).
For even more code-size reductions, see the techniques in
[the hello-world-small example].
- Support for compiling programs with alternate calling conventions, using
[Eyra and `-Zbuild-std`] to [build a program completely from source].
- [Fully static linking] that supports the platform NSS/DNS config. "Is such
a thing even possible?", "Yes it is."
- Or, bring your own reason! Be creative and do your own thing, and tell us
about it!
Why not use Eyra?
- It's not as mature as the major libc implementations.
- It's not as complete as the major libc implementations. It can run most Rust
code, and some popular C libraries, but still lacks a lot of things used by
typical C code.
- It currently depends on Rust Nightly and only runs on Linux, and currently
only on x86-64, x86, aarch64, and riscv64.
- It can't currently run under Miri because Miri doesn't currently recognize
syscalls made from assembly code. That said, Eyra does strive to adhere to
strict provenance and to avoid undefined behavior throughout, so if Miri
were to gain support for such syscalls, Eyra should be well-positioned.
- No support for dynamic linking.
It might seem like "memory safety" might be a reason to use Eyra, and Eyra does
have a lot of code written in safe Rust, so it does benefit some from Rust's
memory safety. However, Eyra also has a lot of `unsafe` code (it's unavoidable
for implementing a libc). Until this code has been more throughly proven, it's
not realistic to consider it more safe than mature C code.
[Whole-program LTO]: https://github.com/sunfishcode/eyra/tree/main/example-crates/hello-world-lto#readme
[`set_var` unsoundness issue]: https://github.com/rust-lang/rust/issues/27970
[Eyra and `-Zbuild-std`]: #compatibility-with--zbuild-std
[Fully static linking]: #fully-static-linking
## Fully static linking
Eyra executables don't depend on any dynamic libraries, however by default they
do still depend on a dynamic linker (eg. "/lib64/ld-linux-x86-64.so.2").
For fully static linking, there are currently two options:
- Build with
`RUSTFLAGS=-C target-feature=+crt-static -C relocation-model=static`. This
disables Position-Independent Executable (PIE) mode, which is
straightforward, however it loses the security benefits of
Address-Space Layout Randomization (ASLR).
- Build with `RUSTFLAGS=-C target-feature=+crt-static` and enable the
`experimental-relocate` feature. This allows PIE mode and ASLR to work,
however it does so by enabling an experimental implementation of
relocations. This code seems to be working in practice so far, however it
involves Rust code patching itself as it runs, which is outside of any Rust
semantics.
## Optional logging
Eyra has a `log` feature to enable Rust `log` tracing of program and thread
startup and shutdown, and an `env_logger` feature to install `env_logger`
as the logger, which can be enabled in Cargo.toml:
```toml
[dependencies]
std = { package = "eyra", version = "