Build audit
How ljh-sh/wdiff is built, what
each target produces, and how to verify a release.
5-target build matrix
| target | runner | toolchain | linkage |
|---|---|---|---|
x86_64-linux-musl | ubuntu-latest + Alpine 3.20 docker | alpine gcc + musl | fully static |
aarch64-linux-musl | ubuntu-24.04-arm + Alpine 3.20 docker | alpine gcc + musl | fully static |
aarch64-macos | macos-14 | Apple clang | static, system libc/libSystem |
x86_64-macos | macos-14 | Apple clang (-arch x86_64) | static, system libc/libSystem |
x86_64-windows | windows-latest + MSYS2 + mingw64 | x86_64-w64-mingw32-gcc | fully static (no DLLs) |
The matrix is split into two workflows (per the ljh-sh dist regime):
build-and-test.yml— fires on push tomain+ every PR. Runs the matrix + smoke + uploads per-target artifacts.release.yml— fires onv*tags +workflow_dispatch. Runs the same matrix, downloads all artifacts, and creates a GitHub Release with theSHA256SUMSfile.
What scripts/build.sh does
- autoreconf -if --force on
upstream/wdiff/andupstream/diffutils/. The--forceflag is needed because the upstream 1.2.2 tarball ships pre-generatedpo/files thatautopointwould otherwise refuse to overwrite. - Sub-build 1: diffutils — out-of-tree
configurewith--disable-shared --enable-static, thenmake. Producesbuild/diffutils/src/diff. - Sub-build 2: wdiff — out-of-tree
configurewithDIFF_PROGRAM=$abs_path_to_diffbaked in (via thediff_cv_prog_diff_programcache variable), thenmake. Producesbuild/wdiff/src/wdiff.
Both sub-builds are out-of-tree: nothing under
upstream/ is mutated. This lets musl-Alpine
and host-glibc builds share the same source tree without
fighting over Makefile state.
Reproducibility
The build is not bit-for-bit reproducible across machines (yet) because:
- The upstream wdiff / diffutils autotools
configurescripts embed the build host and timestamp into the generatedconfig.h. - The default ar / ranlib ordering depends on the toolchain vendor (alpine gcc 14 vs. macOS Apple clang).
A user who runs bash scripts/build.sh on the
same OS with the same toolchain version will get a
functionally-identical binary but with different bytes.
Bit-for-bit reproducibility is a future v0.2.0 goal,
tracked under the OpenSSF Scorecard "reproducible-builds"
check.
Verifying a release
Each GitHub Release ships:
- 5 per-target archives (
wdiff-<target>.tar.gzor.zip) - 5 per-archive
.sha256files - 1 top-level
SHA256SUMSfile (basename-keyed, nodist/prefix)
To verify the Linux x86_64 musl binary:
curl -L -O https://github.com/ljh-sh/wdiff/releases/latest/download/wdiff-x86_64-linux-musl.tar.gz
curl -L -O https://github.com/ljh-sh/wdiff/releases/latest/download/wdiff-x86_64-linux-musl.tar.gz.sha256
sha256sum -c wdiff-x86_64-linux-musl.tar.gz.sha256
To verify all 5 archives against the top-level
SHA256SUMS:
curl -L -O https://github.com/ljh-sh/wdiff/releases/latest/download/SHA256SUMS
for f in wdiff-*.tar.gz wdiff-*.zip; do sha256sum -c <(grep " $f$" SHA256SUMS); done