From 4c730f0865ffb8eeb234a41f94a33621cf1c67e9 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Mon, 9 Oct 2023 08:31:04 -0700 Subject: [PATCH] Add an example showing Eyra's small code size Add an example showing the use of [min-sized-rust] techiques to reduce code size. As of this writing, using the same optimizations without Eyra, using `x86_64-unknown-linux-musl`, produces a hello world binary in 50776 bytes, while using them with Eyra uses just 37912 bytes. [min-sized-rust]: https://github.com/johnthagen/min-sized-rust --- README.md | 8 +++++ example-crates/hello-world-small/.gitignore | 2 ++ example-crates/hello-world-small/Cargo.toml | 19 ++++++++++++ example-crates/hello-world-small/README.md | 31 ++++++++++++++++++++ example-crates/hello-world-small/build.rs | 4 +++ example-crates/hello-world-small/src/main.rs | 5 ++++ tests/example_crates.rs | 21 ++++++++++++- 7 files changed, 89 insertions(+), 1 deletion(-) create mode 100644 example-crates/hello-world-small/.gitignore create mode 100644 example-crates/hello-world-small/Cargo.toml create mode 100644 example-crates/hello-world-small/README.md create mode 100644 example-crates/hello-world-small/build.rs create mode 100644 example-crates/hello-world-small/src/main.rs diff --git a/README.md b/README.md index e8c3a7f..f97d884 100644 --- a/README.md +++ b/README.md @@ -101,6 +101,14 @@ extern crate eyra; to ensure that the Eyra libraries are linked in. +## Reducing code size + +Eyra can be used with the techniques in [min-sized-rust] to produce very +small statically-linked binaries. Check out [the hello-world-small example]. + +[min-sized-rust]: https://github.com/johnthagen/min-sized-rust +[the hello-world-small example]: https://github.com/sunfishcode/eyra/tree/main/example-crates/hello-world-small/ + ## Background Eyra is similar to [Mustang] and uses the same underlying code, but instead diff --git a/example-crates/hello-world-small/.gitignore b/example-crates/hello-world-small/.gitignore new file mode 100644 index 0000000..96ef6c0 --- /dev/null +++ b/example-crates/hello-world-small/.gitignore @@ -0,0 +1,2 @@ +/target +Cargo.lock diff --git a/example-crates/hello-world-small/Cargo.toml b/example-crates/hello-world-small/Cargo.toml new file mode 100644 index 0000000..f30f2ca --- /dev/null +++ b/example-crates/hello-world-small/Cargo.toml @@ -0,0 +1,19 @@ +[package] +name = "hello-world-small" +version = "0.0.0" +edition = "2021" +publish = false + +[dependencies] +eyra = { path = "../.." } + +[profile.release] +# Enable options from min-sized-rust: +strip = true # Automatically strip symbols from the binary. +opt-level = "z" # Optimize for size. +lto = true +codegen-units = 1 +panic = "abort" + +# This is just an example crate, and not part of the c-ward workspace. +[workspace] diff --git a/example-crates/hello-world-small/README.md b/example-crates/hello-world-small/README.md new file mode 100644 index 0000000..255bdc8 --- /dev/null +++ b/example-crates/hello-world-small/README.md @@ -0,0 +1,31 @@ +This crate demonstrates the use of Eyra with a smaller binary size! + +This is the same as the [hello-world] example, but enables some options +described in [min-sized-rust] to reduce the size of the final binary. + +It uses the [workaround to support -Zbuild-std], and can be built with +a command like this: + +```console +$ RUSTFLAGS="-Zlocation-detail=none -C relocation-model=static -Ctarget-feature=+crt-static" cargo +nightly run -Z build-std=std,panic_abort -Z build-std-features=panic_immediate_abort --target x86_64-unknown-linux-gnu --release +``` + +This applies all the techniques described on the [min-sized-rust] page +before [Remove `core::fmt` with `#![no_main]` and Careful Usage of `libstd`]. + +As of this writing, using all these same optimizations without Eyra, using +`x86_64-unknown-linux-musl` (which produces smaller statically-linked binaries +than `x86_64-unknown-linux-gnu`), compiles to 50776 bytes, while this Eyra +example currently compiles to 37912 bytes. + +If you're interested in going further down the `#![no_main]`/`#![no_std]` +path, consider [using Origin directly] which can get down to 408 bytes. Or, +consider using [Origin Studio] if you want to go there but still have +`println!`. + +[hello-world]: https://github.com/sunfishcode/eyra/tree/main/example-crates/hello-world/ +[min-sized-rust]: https://github.com/johnthagen/min-sized-rust +[workaround to support -Zbuild-std]: https://github.com/sunfishcode/eyra/blob/main/README.md#compatibility-with--zbuild-std +[Remove `core::fmt` with `#![no_main]` and Careful Usage of `libstd`]: https://github.com/johnthagen/min-sized-rust#remove-corefmt-with-no_main-and-careful-usage-of-libstd +[using Origin directly]: https://github.com/sunfishcode/origin/tree/main/example-crates/tiny +[Origin Studio]: https://github.com/sunfishcode/origin-studio diff --git a/example-crates/hello-world-small/build.rs b/example-crates/hello-world-small/build.rs new file mode 100644 index 0000000..ccccd22 --- /dev/null +++ b/example-crates/hello-world-small/build.rs @@ -0,0 +1,4 @@ +fn main() { + // Pass -nostartfiles to the linker. + println!("cargo:rustc-link-arg=-nostartfiles"); +} diff --git a/example-crates/hello-world-small/src/main.rs b/example-crates/hello-world-small/src/main.rs new file mode 100644 index 0000000..b38c578 --- /dev/null +++ b/example-crates/hello-world-small/src/main.rs @@ -0,0 +1,5 @@ +extern crate eyra; + +fn main() { + println!("Hello, world!"); +} diff --git a/tests/example_crates.rs b/tests/example_crates.rs index c14e2d5..ecc8cb0 100644 --- a/tests/example_crates.rs +++ b/tests/example_crates.rs @@ -62,7 +62,7 @@ fn example_crate_hello_world() { #[test] fn example_crate_hello_world_lto() { test_crate( - "hello-world", + "hello-world-lto", &["--release"], &[], "Hello, world!\n", @@ -71,6 +71,25 @@ fn example_crate_hello_world_lto() { ); } +#[test] +fn example_crate_hello_world_small() { + test_crate( + "hello-world-small", + &[ + "--release", + "-Zbuild-std=std,panic_abort", + "-Zbuild-std-features=panic_immediate_abort", + ], + &[( + "RUSTFLAGS", + "-Zlocation-detail=none -Crelocation-model=static -Ctarget-feature=+crt-static", + )], + "Hello, world!\n", + "", + None, + ); +} + #[test] fn example_crate_extern_crate_hello_world() { test_crate(