This document explains the changes made to create fully static, portable binaries for the SOAR project.
The original build used x86_64-unknown-linux-gnu target which creates binaries that dynamically link against:
glibc(GNU C Library)libgdal(GDAL geospatial library)libpq(PostgreSQL client library)libssl/libcrypto(OpenSSL)- Other system libraries
This causes deployment issues:
- Version mismatches between build and deployment servers
- Missing libraries on destination servers
- Complex dependency management during deployment
Use musl libc instead of glibc, which enables full static linking:
- Target:
x86_64-unknown-linux-musl(andaarch64-unknown-linux-muslfor ARM64) - Build tool:
crosswith Alpine Linux-based Docker images - Result: Single binary with no external dependencies
Added musl target configurations:
[target.x86_64-unknown-linux-musl]
image = "ghcr.io/cross-rs/x86_64-unknown-linux-musl:edge"
pre-build = [
"apk add --no-cache gdal-dev gdal-static postgresql-dev pkgconfig",
]
[target.aarch64-unknown-linux-musl]
image = "ghcr.io/cross-rs/aarch64-unknown-linux-musl:edge"
pre-build = [
"apk add --no-cache gdal-dev gdal-static postgresql-dev pkgconfig",
]Added rustflags for static linking:
[target.x86_64-unknown-linux-musl]
rustflags = [
"--cfg", "tokio_unstable",
"-C", "target-feature=+crt-static",
"-C", "link-arg=-static",
]- Changed
build-releasejob to usex86_64-unknown-linux-musl - Removed GDAL/mold installation steps (handled by cross)
- Added
crossinstallation and caching - Added static linking verification
- ARM64 static musl build moved to separate manually-triggered workflow
- Uses
aarch64-unknown-linux-musltarget - Can be triggered via GitHub Actions UI when ARM64 builds are needed
- Same changes as ci.yml for release builds
- Same changes as ci.yml for ADS-B deployment builds
- Portability: Binary runs on any Linux system (kernel 2.6.32+)
- Simplicity: No need to install dependencies on deployment servers
- Consistency: Same binary works across different distros/versions
- Security: Easier to audit - all dependencies bundled
- Size: Similar size to dynamically linked builds
The workflow includes a verification step:
ldd target/x86_64-unknown-linux-musl/release/soar
# Should output: "not a dynamic executable"- Build binary with musl:
cross build --release --target x86_64-unknown-linux-musl - Verify static linking:
ldd target/x86_64-unknown-linux-musl/release/soar - Test on different Linux distros (Ubuntu, Debian, Alpine, CentOS, etc.)
Pros:
- Complete portability
- No dependency hell
- Simplified deployment
Cons:
- Slightly slower DNS resolution (musl's getaddrinfo)
- Larger build time (static linking all dependencies)
- Cannot use glibc-specific features
- Finish updating release.yml
- Finish updating deploy-adsb.yml
- Test binary on multiple Linux distributions
- Update deployment scripts to remove dependency installation steps
- Document deployment process