One executable. Five x86-64 builds. The best one selected automatically.
Quick start · Supported projects · How it works · Function cheat sheet · File format
spec-elf packages multiple x86-64 builds of a project into a single Linux ELF or Windows PE executable.
At runtime, it detects the host CPU and launches the best compatible payload. Linux specializes the packed file
permanently on first run; Windows uses a temporary executable because a running .exe cannot replace itself.
| Platforms | Linux and Windows x86-64 | Languages | C, C++, Rust, Zig |
|---|---|---|---|
| Variants | native, baseline, v2, v3, v4 | Compression | Zstandard, per payload |
cargo build --release
The launcher is written to target/release/spec-elf on Linux and
target/release/spec-elf.exe on Windows.
Pass the project directory explicitly. Use . for the current directory.
cd /path/to/project
/path/to/spec-elf/target/release/spec-elf .Or package it from elsewhere:
/path/to/spec-elf/target/release/spec-elf /path/to/projectOn Windows PowerShell:
Set-Location C:\path\to\project
& "C:\path\to\spec-elf\target\release\spec-elf.exe" .
The resulting packed executable is named spec-elf on Linux or spec-elf.exe on Windows and is
placed in the project directory. Intermediate binaries are written to that project's build/ directory.
Host builds only: run spec-elf on Linux to package Linux executables and on Windows to
package Windows executables. Cross-compiling a package for another operating system is not currently supported.
Every supported project is built for these targets:
| Variant | When it is selected |
|---|---|
native | The CPU identity matches the machine that built the package. |
x86-64-v4 | The host supports the complete v4 feature set. |
x86-64-v3 | The host supports the complete v3 feature set. |
x86-64-v2 | The host supports the complete v2 feature set. |
x86-64 | Baseline fallback for any x86-64 host. |
The launcher uses native only for a matching CPU. Otherwise, it selects the highest
compatible standardized x86-64 level.
spec-elf detects the project language by recursively counting source-file extensions.
It ignores target/, build/, and .git/ directories.
| Language | Detected by | Build behavior |
|---|---|---|
| C | .c |
Uses CMake when CMakeLists.txt exists; otherwise uses gcc -O3. |
| C++ | .cpp, .cc, .cxx, .hpp, .hxx |
Uses CMake when CMakeLists.txt exists; otherwise uses g++ -O3. |
| Rust | .rs |
Finds the nearest Cargo.toml, builds in release mode, and sets RUSTFLAGS per target. |
| Zig | .zig |
Builds the first Zig source with zig build-exe -O ReleaseFast. |
- Rust and Cargo to build
spec-elf. gccor CMake with a GCC-compatible C compiler for C projects.g++or CMake with a GCC-compatible C++ compiler for C++ projects.- Cargo for Rust projects.
- Zig for Zig projects.
- Build five CPU-specific versions of the project.
- Compress each payload independently with Zstandard.
- Append the compressed frames and a manifest to the launcher.
- Detect the current CPU's x86-64 feature level at runtime.
- Extract the best matching payload to a temporary sibling file.
- On Linux, atomically replace the launcher and execute the selected payload.
- On Windows, run the temporary
.exe, forward its exit code, and remove it afterward.
Linux permanently replaces the packed file after specialization. Windows keeps the packed launcher because the operating system locks running executables. Both platforms require write access to the launcher's directory. Runtime arguments are forwarded to the selected program. See the packed-format documentation for the binary layout.
Current limitations
- Only x86-64 Linux and Windows are supported.
- The packaging CLI accepts exactly one project-directory argument; packed programs may receive arbitrary runtime arguments.
- The packaged output is named after the launcher binary, normally
spec-elforspec-elf.exe. - Packages are built for the host operating system; cross-OS packaging is not supported.
- Direct C and C++ builds cannot supply custom libraries, linker flags, or complex include paths; use CMake for those projects.
- C and C++ CPU variants currently require GCC-compatible
-marchflags; MSVC is not supported. - CMake packaging expects exactly one executable in its configured runtime output directory.
- Rust supports the default binary or one explicit
[[bin]]; multiple explicit binaries require a future selection option. - Zig currently builds the first
.zigsource found. - Each decompressed payload is limited to 1 GiB.
- On Windows, remove an existing packed output before rebuilding it; Windows does not allow the final rename to replace an existing file.
| Task | Command |
|---|---|
| Run tests | cargo test |
| Show CLI help | cargo run -- --help |
| Package a project | cargo run -- /path/to/project |
| Fuzz the archive parser | cargo fuzz run archive from fuzz/ |
Experimental software.
Useful for testing CPU-specialized builds; not yet a general-purpose application packager.