Build audit
How ljh-sh/dwdiff 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 + bundled ICU 78.3 | fully static |
aarch64-linux-musl | ubuntu-24.04-arm + Alpine 3.20 docker | alpine gcc + musl + bundled ICU 78.3 | fully static |
aarch64-macos | macos-14 | Apple clang + bundled ICU 78.3 | static, system libc/libSystem |
x86_64-macos | macos-14 | Apple clang (-arch x86_64) + bundled ICU 78.3 | static, system libc/libSystem |
x86_64-windows | windows-latest + MSYS2 + mingw64 | x86_64-w64-mingw32-gcc + bundled ICU 78.3 | fully static (no DLLs) |
The matrix is split into two workflows (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
- Sub-build 1: ICU 78.3 — out-of-tree
runConfigureICU Linuxwith--enable-static --disable-shared --disable-icuio --disable-icusnfp --disable-icuscriptbreaks --disable-extras --disable-samples --disable-tests, thenmake. ~10 min on a 4-core runner. Producesbuild/icu/lib/libicuuc.a+build/icu/lib/libicudata.a. - Sub-build 2: dwdiff — in-source
./configure --without-gettext --prefix=/usr/local+make. Detects ICU viapkg-config; we write a shimbuild/pkgconfig/icu-uc.pcthat points dwdiff'sicu-uclookup at the vendored static ICU. ~3 s. Producesupstream/dwdiff/dwdiff+dwfilter. - Copy + distclean — copy the freshly-built
binaries to
build/dwdiff/(sosmoke.sh+package.shcan find them in a stable location), thenmake distcleanin the source dir to restore the upstream tree.
dwdiff's configure writes
config.pkg in the source dir, so the build is
in-source by necessity. We restore the tree after build
via make distclean + an explicit
cp config.pkg from the tarball at vendor-refresh
time.
Why the binary is so big
A static dwdiff binary with bundled ICU 78.3
is ~30-35 MB. The bulk is the ICU Unicode database
(~15 MB of libicudata.a) + the ICU
normalisation tables. We disable
--disable-icuio --disable-icusnfp
--disable-icuscriptbreaks --disable-extras to
trim ~20% of that. Further reduction is possible with
the ICU_DATA_SIZE_WHEN_STATIC build option,
but requires custom data-build tooling and is deferred
to a v0.2.0 build-script patch.
The size is the price of a fully self-contained CJK + Unicode-segmentation diff tool. Distroless / scratch containers that don't have system ICU get full support.
Verifying a release
Each GitHub Release ships:
- 5 per-target archives (
dwdiff-<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/dwdiff/releases/latest/download/dwdiff-x86_64-linux-musl.tar.gz
curl -L -O https://github.com/ljh-sh/dwdiff/releases/latest/download/dwdiff-x86_64-linux-musl.tar.gz.sha256
sha256sum -c dwdiff-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/dwdiff/releases/latest/download/SHA256SUMS
for f in dwdiff-*.tar.gz dwdiff-*.zip; do sha256sum -c <(grep " $f$" SHA256SUMS); done