Repo-specific notes for native builds, precompiled libvips, CI, and releases.
Compilation Modes
Vix supports three VIX_COMPILATION_MODE values:
PRECOMPILED_NIF_AND_LIBVIPSis the default. It downloads a precompiled Vix NIF from the Vix GitHub release when one is available. Do not use this as the only check for native C changes, because it can reuse the released NIF instead of compiling local C sources.PRECOMPILED_LIBVIPScompiles the local NIF and links it against the sharp-libvips tarball. Use this for changes to native code, precompiled libvips, link flags, or packaged runtime files.PLATFORM_PROVIDED_LIBVIPSusespkg-config vipsand links against the host libvips. SetVIX_LIBVIPS_PREFIXto test a specific local libvips install.
Useful commands:
rm -rf _build/*/lib/vix cache/ priv/*
ELIXIR_MAKE_CACHE_DIR="$(pwd)/cache" \
VIX_COMPILATION_MODE=PRECOMPILED_LIBVIPS \
mix test
VIX_COMPILATION_MODE=PLATFORM_PROVIDED_LIBVIPS mix test
VIX_LIBVIPS_PREFIX=/path/to/libvips/prefix \
VIX_COMPILATION_MODE=PLATFORM_PROVIDED_LIBVIPS \
mix test
make debug
make V=1 all
Generated paths such as _build/, deps/, priv/, cache/, .libvips/,
toolchains/, and checksum.exs should not be committed.
Precompiled libvips
Vix downloads precompiled libvips from
akash-akya/sharp-libvips.
Current configuration:
- sharp-libvips release tag:
v8.18.3-rc1 - upstream libvips version:
8.18.3 - Vix config:
@release_taginbuild_scripts/precompiler.exs - asset pattern:
sharp-libvips-<platform>.tar.gz
Current target mapping:
| Vix target | sharp-libvips asset |
|---|---|
x86_64-linux-gnu | sharp-libvips-linux-x64.tar.gz |
x86_64-linux-musl | sharp-libvips-linuxmusl-x64.tar.gz |
aarch64-linux-gnu | sharp-libvips-linux-arm64v8.tar.gz |
aarch64-linux-musl | sharp-libvips-linuxmusl-arm64v8.tar.gz |
arm-linux-gnueabihf | sharp-libvips-linux-armv6.tar.gz |
armv7l-linux-gnueabihf | sharp-libvips-linux-armv6.tar.gz |
x86_64-apple-darwin | sharp-libvips-darwin-x64.tar.gz |
aarch64-apple-darwin | sharp-libvips-darwin-arm64v8.tar.gz |
For precompiled POSIX builds, Vix links directly to libvips-cpp:
precompiled_libvips/lib/libvips-cpp.so.*
precompiled_libvips/lib/libvips-cpp.*.dylibThis is expected. The sharp-libvips package exports the libvips C ABI from
libvips-cpp, so the precompiled POSIX package does not need a separate
libvips.so or libvips.dylib.
The files copied into precompiled Vix NIF archives are controlled by
make_precompiler_priv_paths in mix.exs.
Local libvips Builds
Use scripts/build_libvips.sh when testing Vix against an upstream libvips ref
without publishing a sharp-libvips release. The script builds a normal C
libvips install for PLATFORM_PROVIDED_LIBVIPS.
./scripts/build_libvips.sh --ref vX.Y.Z
VIX_LIBVIPS_PREFIX="$(pwd)/.libvips/vX.Y.Z" \
VIX_COMPILATION_MODE=PLATFORM_PROVIDED_LIBVIPS \
mix test
If --ref is omitted, the script resolves the latest upstream libvips release.
Use --overwrite to replace an existing local prefix.
Toolchains
precompile.yaml uses musl cross-compilers for musl NIF targets. The scripts
mirror the required musl.cc archives on Vix GitHub releases:
./scripts/download_toolchains.sh
./scripts/mirror_toolchains.sh
The current mirrored version is 11.2.1; update TOOLCHAIN_VERSION in both
scripts if the mirror changes.
CI
.github/workflows/ci.yaml runs on pushes and pull requests to master and
dev. It covers:
- Linux
PLATFORM_PROVIDED_LIBVIPSagainst the latest upstream libvips release. - Linux
PRECOMPILED_LIBVIPS. - Linux default precompiled NIF mode with
mix elixir_make.checksum --only-local. - ARM precompiled smoke test through Docker/QEMU.
- macOS default precompiled and
PRECOMPILED_LIBVIPSthrough Nix. - compile with warnings as errors, unused dependency checks, formatter, Credo, and Dialyzer.
.github/workflows/precompile.yaml runs for v* tags and uploads
cache/*.tar.gz NIF artifacts to the matching GitHub release.
Release Process
Standard Vix Release
Bump
@versioninmix.exs, commit, and pushmaster.git add mix.exs git commit -m "Bump version to X.Y.Z" git push origin masterCreate and push the release tag.
git tag -a vX.Y.Z -m "Release vX.Y.Z" git push origin vX.Y.ZWait for
.github/workflows/precompile.yamlto upload all NIF tarballs to the GitHub release.Generate checksums.
unset VIX_COMPILATION_MODE rm -rf cache/ priv/* _build/*/lib/vix ELIXIR_MAKE_CACHE_DIR="$(pwd)/cache" \ MIX_ENV=prod \ mix elixir_make.checksum --all cat checksum.exschecksum.exsis generated, ignored by Git, and should not be committed. The checksum task rewrites it, so deleting an old copy first is optional. Keep it in the working tree formix hex.publish.Test the release artifacts, then publish.
unset VIX_COMPILATION_MODE rm -rf cache/ priv/* _build/*/lib/vix ELIXIR_MAKE_CACHE_DIR="$(pwd)/cache" mix test mix hex.publishBefore accepting the publish prompt, confirm the file list includes
checksum.exsandDEVELOPMENT.md.Optional cleanup:
rm -rf cache/ priv/* checksum.exs _build/*/lib/vix doc/ vix-*.tarThis is only housekeeping.
checksum.exscan remain locally after publish.
Failed Tag Build
If the tag workflow fails before Hex publish, fix master, push the fix, move
the tag, and force-push the tag:
git push origin master
git tag -fa vX.Y.Z -m "Release vX.Y.Z"
git push --force origin vX.Y.Z
The release workflow uses overwrite_files: true, so rerunning the same tag can
replace partial GitHub release artifacts. After a Hex package is public, do not
move the tag; publish a new patch or release-candidate version instead.
Libvips Update
Use this when Vix should consume a new sharp-libvips release.
Rebase the sharp-libvips fork.
cd ~/repos/clang/sharp-libvips-2 git fetch upstream git checkout main git rebase upstream/mainPreserve only the fork behavior Vix needs: direct GitHub release asset upload,
.integrityfiles, fork-local notices, and any deliberate freshness gate change. Do not reintroduce old C-only packaging changes; Vix expects precompiled POSIX packages to providelibvips-cpp.Push and tag the sharp-libvips release candidate.
git push --force-with-lease origin main git tag -a v<libvips-version>-rc<N> -m "libvips <libvips-version> rc<N>" git push origin v<libvips-version>-rc<N>Verify the release assets.
curl -fsSL \ https://api.github.com/repos/akash-akya/sharp-libvips/releases/tags/v8.18.3-rc1 \ | jq -r '.assets[].name' \ | sortVix needs the mapped tarballs above and their
.integrityfiles.Update Vix.
- Change
@release_taginbuild_scripts/precompiler.exs. - If the package layout changed, update
c_src/Makefile,make_precompiler_priv_pathsinmix.exs, and the target mapping inbuild_scripts/precompiler.exs.
- Change
Test locally.
rm -rf _build/*/lib/vix cache/ priv/* ELIXIR_MAKE_CACHE_DIR="$(pwd)/cache" \ VIX_COMPILATION_MODE=PRECOMPILED_LIBVIPS \ mix test VIX_COMPILATION_MODE=PLATFORM_PROVIDED_LIBVIPS mix testFollow the standard Vix release process.
Troubleshooting
Precompiled libvips Download Fails
Check the configured tag and asset URL:
grep '@release_tag' build_scripts/precompiler.exs
curl -I \
https://github.com/akash-akya/sharp-libvips/releases/download/v8.18.3-rc1/sharp-libvips-linux-x64.tar.gz
If Erlang reports a crypto or SSL error before downloading, fix the local
Erlang/OpenSSL installation. For example, an OTP build linked to
libcrypto.so.1.1 will fail where that shared library is missing.
NIF Link Fails
make deep_clean
make debug
make V=1 all
find priv/precompiled_libvips/lib -maxdepth 1 -name 'libvips-cpp*' -print
pkg-config --modversion vips
pkg-config --cflags --libs vips
Checksum Verification Fails
Regenerate checksums against the intended GitHub release artifacts:
rm -rf cache/ priv/* _build/*/lib/vix
ELIXIR_MAKE_CACHE_DIR="$(pwd)/cache" \
MIX_ENV=prod \
mix elixir_make.checksum --all