{"id":13648527,"url":"https://github.com/sunfishcode/eyra","last_synced_at":"2025-05-14T09:09:01.664Z","repository":{"id":212178158,"uuid":"695302368","full_name":"sunfishcode/eyra","owner":"sunfishcode","description":"Rust programs written entirely in Rust","archived":false,"fork":false,"pushed_at":"2025-03-07T01:16:25.000Z","size":164,"stargazers_count":822,"open_issues_count":5,"forks_count":12,"subscribers_count":15,"default_branch":"main","last_synced_at":"2025-04-03T21:36:48.362Z","etag":null,"topics":["linux","rust"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/sunfishcode.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE-APACHE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-09-22T20:09:24.000Z","updated_at":"2025-03-30T22:45:02.000Z","dependencies_parsed_at":"2023-12-12T23:29:46.689Z","dependency_job_id":"b55f1a68-341c-49f2-bfce-4c0b6f71f6e1","html_url":"https://github.com/sunfishcode/eyra","commit_stats":{"total_commits":75,"total_committers":3,"mean_commits":25.0,"dds":0.06666666666666665,"last_synced_commit":"89f70c2b1af862964f24d29210c0be1579677d5c"},"previous_names":["sunfishcode/eyra"],"tags_count":19,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sunfishcode%2Feyra","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sunfishcode%2Feyra/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sunfishcode%2Feyra/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sunfishcode%2Feyra/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/sunfishcode","download_url":"https://codeload.github.com/sunfishcode/eyra/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248335001,"owners_count":21086488,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["linux","rust"],"created_at":"2024-08-02T01:04:19.564Z","updated_at":"2025-04-11T03:27:35.401Z","avatar_url":"https://github.com/sunfishcode.png","language":"Rust","readme":"\u003cdiv align=\"center\"\u003e\n  \u003ch1\u003eEyra\u003c/h1\u003e\n\n  \u003cp\u003e\n    \u003cstrong\u003eRust programs written entirely in Rust\u003c/strong\u003e\n  \u003c/p\u003e\n\n  \u003cp\u003e\n    \u003ca href=\"https://github.com/sunfishcode/eyra/actions?query=workflow%3ACI\"\u003e\u003cimg src=\"https://github.com/sunfishcode/eyra/workflows/CI/badge.svg\" alt=\"Github Actions CI Status\" /\u003e\u003c/a\u003e\n    \u003ca href=\"https://bytecodealliance.zulipchat.com/#narrow/stream/206238-general\"\u003e\u003cimg src=\"https://img.shields.io/badge/zulip-join_chat-brightgreen.svg\" alt=\"zulip chat\" /\u003e\u003c/a\u003e\n    \u003ca href=\"https://crates.io/crates/eyra\"\u003e\u003cimg src=\"https://img.shields.io/crates/v/eyra.svg\" alt=\"crates.io page\" /\u003e\u003c/a\u003e\n    \u003ca href=\"https://docs.rs/eyra\"\u003e\u003cimg src=\"https://docs.rs/eyra/badge.svg\" alt=\"docs.rs docs\" /\u003e\u003c/a\u003e\n  \u003c/p\u003e\n\u003c/div\u003e\n\nEyra is a package that supports building Rust programs implemented entirely\nin Rust.\n\nIt uses [Origin] for program and thread startup and shutdown, and [c-gull] for\nABI-compatible libc function implementations. It currently works on\nNightly Rust on Linux on x86-64, x86, aarch64, and riscv64.\n\n[Origin]: https://github.com/sunfishcode/origin#readme\n[c-gull]: https://github.com/sunfishcode/c-ward/tree/main/c-gull#readme\n\n## Quick start\n\nRunning a Rust program under Eyra needs two steps. First, a Cargo.toml\ndependency, which we can add with:\n\n```console\ncargo add eyra --rename=std\n```\n\nAnd, a build.rs file to add `-nostartfiles` to the link flags to disable the\nhost startup code, so that Eyra can provide its own. build.rs:\n\n```rust,no_run\nfn main() {\n    println!(\"cargo:rustc-link-arg=-nostartfiles\");\n}\n```\n\nWith that, `cargo build`, `cargo run`, `cargo test` (with Nightly) and so on\nwill work normally with any `*-unknown-linux-gnu*` target.\n\nUnder the covers, it's using [Origin] to start and stop the program, [c-ward]\nto handle libc calls from `std`, and [rustix] to do the printing, so it's\ncompletely implemented in Rust.\n\n## Examples\n\nFor an example of the above steps, check out [this hello world example].\n\nOther examples include\n - [enabling LTO],\n - [using min-sized-rust technique to produce small binaries], and\n - [adding Eyra as an optional dependency].\n - [building a program completely from source].\n\n[this hello world example]: https://github.com/sunfishcode/eyra/tree/main/example-crates/hello-world#readme\n[enabling LTO]: https://github.com/sunfishcode/eyra/tree/main/example-crates/hello-world-lto#readme\n[using min-sized-rust technique to produce small binaries]: https://github.com/sunfishcode/eyra/tree/main/example-crates/hello-world-small#readme\n[adding Eyra as an optional dependency]: https://github.com/sunfishcode/eyra/tree/main/example-crates/eyra-optional-example#readme\n[building a program completely from source]: https://github.com/sunfishcode/eyra/tree/main/example-crates/all-from-source#readme\n\n## Why?\n\nWhy use Eyra?\n\n - It fixes Rust's [`set_var` unsoundness issue]. The environment-variable\n   implementation leaks memory internally (it is optional, but enabled by\n   default), so `setenv` etc. are thread-safe.\n\n - [Whole-program LTO], including the libc. This sometimes produces smaller\n   static binaries, and sometimes produces faster code (though on the other\n   hand, sometimes it doesn't, though on the first hand, there are still\n   low-hanging fruit, so consider trying it and filing issues).\n\n   For even more code-size reductions, see the techniques in\n   [the hello-world-small example].\n\n - Support for compiling programs with alternate calling conventions, using\n   [Eyra and `-Zbuild-std`] to [build a program completely from source].\n\n - [Fully static linking] that supports the platform NSS/DNS config. \"Is such\n   a thing even possible?\", \"Yes it is.\"\n\n - Or, bring your own reason! Be creative and do your own thing, and tell us\n   about it!\n\nWhy not use Eyra?\n\n - It's not as mature as the major libc implementations.\n\n - It's not as complete as the major libc implementations. It can run most Rust\n   code, and some popular C libraries, but still lacks a lot of things used by\n   typical C code.\n\n - It currently depends on Rust Nightly and only runs on Linux, and currently\n   only on x86-64, x86, aarch64, and riscv64.\n\n - It can't currently run under Miri because Miri doesn't currently recognize\n   syscalls made from assembly code. That said, Eyra does strive to adhere to\n   strict provenance and to avoid undefined behavior throughout, so if Miri\n   were to gain support for such syscalls, Eyra should be well-positioned.\n\n - No support for dynamic linking.\n\nIt might seem like \"memory safety\" might be a reason to use Eyra, and Eyra does\nhave a lot of code written in safe Rust, so it does benefit some from Rust's\nmemory safety. However, Eyra also has a lot of `unsafe` code (it's unavoidable\nfor implementing a libc). Until this code has been more throughly proven, it's\nnot realistic to consider it more safe than mature C code.\n\n[Whole-program LTO]: https://github.com/sunfishcode/eyra/tree/main/example-crates/hello-world-lto#readme\n[`set_var` unsoundness issue]: https://github.com/rust-lang/rust/issues/27970\n[Eyra and `-Zbuild-std`]: #compatibility-with--zbuild-std\n[Fully static linking]: #fully-static-linking\n\n## Fully static linking\n\nEyra executables don't depend on any dynamic libraries, however by default they\ndo still depend on a dynamic linker (eg. \"/lib64/ld-linux-x86-64.so.2\").\n\nFor fully static linking, there are currently two options:\n\n - Build with\n   `RUSTFLAGS=-C target-feature=+crt-static -C relocation-model=static`. This\n   disables Position-Independent Executable (PIE) mode, which is\n   straightforward, however it loses the security benefits of\n   Address-Space Layout Randomization (ASLR).\n\n - Build with `RUSTFLAGS=-C target-feature=+crt-static` and enable the\n   `experimental-relocate` feature. This allows PIE mode and ASLR to work,\n   however it does so by enabling an experimental implementation of\n   relocations. This code seems to be working in practice so far, however it\n   involves Rust code patching itself as it runs, which is outside of any Rust\n   semantics.\n\n## Optional logging\n\nEyra has a `log` feature to enable Rust `log` tracing of program and thread\nstartup and shutdown, and an `env_logger` feature to install `env_logger`\nas the logger, which can be enabled in Cargo.toml:\n\n```toml\n[dependencies]\nstd = { package = \"eyra\", version = \"\u003ccurrent-version\u003e\", features = [\"log\", \"env_logger\"] }\n```\n\nWith this, and setting the `RUST_LOG` environment variable to \"trace\", the\nhello world program output like this:\n\n```console\n[TRACE origin::program] Program started\n[TRACE origin::thread] Main Thread[51383] initialized\n[TRACE origin::program] Calling `.init_array`-registered function `0x55e86306bb80(1, 0x7ffd0f76aad8, 0x7ffd0f76aae8)`\n[TRACE origin::program] Calling `origin_main(1, 0x7ffd0f76aad8, 0x7ffd0f76aae8)`\nHello, world!\n[TRACE origin::program] `origin_main` returned `0`\n[TRACE origin::thread] Thread[51383] calling `at_thread_exit`-registered function\n[TRACE origin::thread] Thread[51383] calling `at_thread_exit`-registered function\n[TRACE origin::program] Program exiting with status `0`\n```\n\n## Compatibility with `-Zbuild-std`\n\nEyra works with `-Zbuild-std`, however the `--rename=std` trick used above\ndoesn't work, so it's necessary to instead use this `cargo add` invocation:\n\n```console\ncargo add eyra\n```\n\nand to also add this line to the program's `main.rs` file:\n\n```rust,no_run\nextern crate eyra;\n```\n\nto ensure that the Eyra libraries are linked in.\n\n## Reducing code size\n\nEyra can be used with the techniques in [min-sized-rust] to produce very\nsmall statically-linked binaries. Check out [the hello-world-small example].\n\n[min-sized-rust]: https://github.com/johnthagen/min-sized-rust\n[the hello-world-small example]: https://github.com/sunfishcode/eyra/tree/main/example-crates/hello-world-small/#readme\n\n## Relationship to Mustang\n\nEyra is similar to [Mustang] and uses the same underlying code, but instead\nof using a custom target and -Z build-std, Eyra just needs users to add\n`-nostartfiles` to their link line, such as via build.rs in the example.\n\nLike Mustang, Eyra currently runs on Nightly Rust on Linux on x86-64, x86,\naarch64, and riscv64. It aims to support all Linux versions\n[supported by Rust], though at this time it's only tested on relatively recent\nversions. It's complete enough to run:\n - [ripgrep](https://github.com/sunfishcode/ripgrep/tree/eyra)\n - [coreutils](https://github.com/sunfishcode/coreutils/tree/eyra),\n   including the \"unix\" feature set\n - [async-std](https://github.com/sunfishcode/tide/tree/eyra)\n - [tokio](https://github.com/sunfishcode/tokio/tree/eyra)\n - [bat](https://github.com/sunfishcode/bat/tree/eyra), including git\n   support with libgit2\n - [cargo-watch](https://github.com/sunfishcode/cargo-watch/tree/eyra)\n - [nushell](https://github.com/sunfishcode/nushell/tree/eyra), with a\n   few workarounds\n\n## Compiling C programs\n\nEyra can also be compiled into a libc.a that can be used to compile C\nprograms; see the [eyra-c] repository.\n\n[eyra-c]: https://github.com/sunfishcode/eyra-c\n\n## Design philosophy\n\nEyra and the libraries it uses have some design goals.\n\n### Normal Rust, all the way down\n\nSometimes in libc implementation code, there's a temptation to say \"it's ok\nif some things are technically Undefined Behavior, because this is Low Level\nCode and We Know What We're Doing\".\n\nOrigin, c-scape, c-gull, rustix, and the others strive to resist this\ntemptation, and follow the Rust rules, including strict provenance, I/O safety,\nand all the rest, all the way down to the syscalls.\n\nIt's just normal Rust code, as far down as we can go in userspace, and when we\neventually do have to switch to inline asm, we do as little of it as we can.\n\nCurrently there is only one known place where this goal is not achieved. In a\n\"static PIE\" executable (eg. built with\n`RUSTFLAGS=\"-C target-feature=+crt-static\"`), the dynamic linker isn't used,\nso the executable has to handle all its relocations itself. However, that\nmeans storing to memory locations that wouldn't otherwise be considered\nmutable. Origin's code for doing this is currently disabled by default, and\ncan be enabled with the \"experimental-relocate\" cargo feature.\n\n### C compatibility as a layer on top of Rust, not vice versa\n\nEyra is built on a collection of Rust crates with idiomatic Rust APIs, and two\ncrates, c-scape and c-gull, which are relatively thin layers on top that\nimplement the libc-compatible C ABI.\n\nIt's sometimes more work to write the code as separate layers like this, but\nit has the advantage of clearly separating out the `unsafe` associated with\nthings like C pointers and strings in libc APIs from the essential `unsafe`\nneeded to implement things like system calls, thread primitives, and other\nfeatures. And it means that Rust programs that don't want to go through the C\ncompatibility layer can use the underlying crates directly.\n\n[Mustang]: https://github.com/sunfishcode/mustang#readme\n[Origin]: https://github.com/sunfishcode/origin#readme\n[c-ward]: https://github.com/sunfishcode/c-ward#readme\n[rustix]: https://github.com/bytecodealliance/rustix#readme\n[supported by Rust]: https://doc.rust-lang.org/nightly/rustc/platform-support.html\n[build a program completely from source]: https://github.com/sunfishcode/eyra/tree/main/example-crates/all-from-source#readme\n","funding_links":[],"categories":["Rust"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsunfishcode%2Feyra","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsunfishcode%2Feyra","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsunfishcode%2Feyra/lists"}