Skip to content

Build release artifacts free of the Nix build environment - #205

Merged
lambdalisue merged 4 commits into
mainfrom
fix/nix-free-release-artifacts
Jul 29, 2026
Merged

Build release artifacts free of the Nix build environment#205
lambdalisue merged 4 commits into
mainfrom
fix/nix-free-release-artifacts

Conversation

@lambdalisue

Copy link
Copy Markdown
Member

Summary

  • Build the release matrix (macOS, Linux x64/arm64, Windows) with each platform's native toolchain instead of the Nix devShell; check, test and nix-check keep running through Nix, and flake.nix is untouched.
  • Add just verify-bundle, backed by scripts/verify-macos-bundle.sh and scripts/verify-linux-bundle.sh, and run it in CI on the artifact about to be published: no /nix/store in any load command, ELF interpreter, RUNPATH or embedded string; declared Depends that actually resolve; and the executable really starts.
  • Declare the .deb's direct shared-library dependencies in Dioxus.toml, so apt install ./arto_*.deb pulls in the GTK/WebKit stack instead of leaving the user with a bare dynamic-linker error.
  • Document Linux installation and the supported distribution floor in the README.

Why

Every published Unix artifact was unusable off the build machine, because just build ran inside nix develop.

On macOS the libc crate's #[link(name = "iconv")] resolved through the devShell's -L /nix/store/…-libiconv/lib, so the app recorded an absolute store path as the install name and dyld killed it at launch (#204). With the Apple toolchain the same link resolves to /usr/lib/libiconv.2.dylib, which every Mac has — verified locally.

Linux was worse: the shipped arto_0.31.2_amd64.deb records /nix/store/…-glibc-2.42-67/lib/ld-linux-x86-64.so.2 as its ELF interpreter, so the binary cannot even be exec'd without that store, and the package declared no Depends at all.

Post-processing the binaries would have patched over the symptom; building natively removes the cause, and the verification gate makes a regression fail the build instead of the download.

Test Plan

Verified locally (macOS):

  • Apple toolchain resolves -liconv to /usr/lib/libiconv.2.dylib
  • macOS verifier rejects a devShell-built .app and accepts one whose only libiconv reference is the system copy (launch and codesign --verify --deep --strict both pass)
  • Linux verifier rejects the published arto_0.31.2_amd64.deb, reporting both the /nix/store interpreter and the missing Depends
  • Depends parsing handles a | b alternatives and rejects a typo'd package name
  • just fmt check test

Needs a real CI run (cannot be exercised from macOS):

  • Native Linux build succeeds and its .deb passes verification
  • Native macOS build succeeds and its .app passes verification
  • Declared Debian package names resolve against the Ubuntu 24.04 index

A re-release is required to get fixed binaries to users; the published 0.31.2 artifacts stay broken.

Closes #204

The generated package carried no Depends field at all, so installing it
pulled in none of the GTK/WebKit stack the binary links against and the
app died with a bare dynamic-linker error. Declare every direct DT_NEEDED
library rather than leaning on WebKitGTK to drag the rest in, so a distro
splitting or renaming one of them cannot silently break the package.
Both published Unix artifacts were unusable off the build machine and
nothing caught it: the macOS app resolved libiconv through an absolute
/nix/store path, and the .deb recorded a /nix/store ELF interpreter that
cannot even be exec'd elsewhere. Inspect the artifact that is about to be
published - load commands, ELF interpreter, RUNPATH, declared dependencies
- and launch it, so the next leak fails the build instead of the download.

Deliberately kept out of `build`: bundles built inside the Nix devShell
legitimately reference the store and must stay usable locally.
Copilot AI review requested due to automatic review settings July 29, 2026 13:37

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR changes the release build pipeline to produce macOS/Linux/Windows artifacts using each platform’s native toolchain (instead of building inside the Nix devShell) and adds CI gates to prevent publishing bundles that embed /nix/store paths or fail to launch. It also improves Linux installability by declaring Debian shared-library dependencies and documents Linux installation requirements.

Changes:

  • Add macOS/Linux bundle verification scripts and a just verify-bundle gate, run in CI before uploading release artifacts.
  • Build release artifacts with a native toolchain (while keeping check/test under Nix) and install required native dependencies/tools in the workflow/action.
  • Declare .deb runtime dependencies via desktop/Dioxus.toml and document Linux installation + distro floor in README.md.

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
scripts/verify-macos-bundle.sh Verifies .app Mach-O load commands contain no /nix/store references and that the executable starts.
scripts/verify-linux-bundle.sh Verifies .deb ELF metadata/strings contain no /nix/store, checks Depends, and smoke-runs the binary.
README.md Adds Linux install instructions and supported distro floor; adds releases link.
justfile Adds platform-scoped verify-bundle entrypoint.
desktop/justfile Implements platform-specific verify-bundle recipes for .app and .deb artifacts.
desktop/Dioxus.toml Declares direct shared-library dependencies for the Debian package.
.github/workflows/build.yml Switches release builds to native toolchain, installs dioxus-cli, and runs just verify-bundle on Unix legs.
.github/actions/setup-toolchain/action.yml Adds toolchain flavoring (nix vs native) and installs required native deps/tools for release builds.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread .github/actions/setup-toolchain/action.yml
Release bundles were built inside the Nix devShell, which bakes absolute
/nix/store paths into the binary: the libiconv install name on macOS, the
ELF interpreter and RUNPATH on Linux. No machine without that store can
resolve them, so every published macOS and Linux build failed at launch.
The native toolchain links against the libraries the user's machine
actually has.

Checks, tests and `nix build` keep running through Nix - only the
artifacts that ship must be free of it.

Closes #204
The Installation section covered only Homebrew and Nix, leaving the
published .deb undocumented - including the glibc floor that follows from
building it on Ubuntu 24.04.
@lambdalisue
lambdalisue force-pushed the fix/nix-free-release-artifacts branch from 60751d0 to a2f4fdd Compare July 29, 2026 14:12
@lambdalisue
lambdalisue merged commit bd5b7a7 into main Jul 29, 2026
15 checks passed
@lambdalisue
lambdalisue deleted the fix/nix-free-release-artifacts branch July 29, 2026 14:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[macOS] v0.31.2 aarch64 build crashes on launch due to missing libiconv

2 participants