From 76e759287e67e4134293c3ad3fb92a55aa15c719 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ga=C3=ABtan=20Andr=C3=A9?= Date: Sun, 19 Apr 2026 18:46:10 +0200 Subject: [PATCH 01/14] Add Nix flake dev shell design spec Co-Authored-By: Claude Sonnet 4.6 --- .../2026-04-19-nix-flake-dev-shell-design.md | 99 +++++++++++++++++++ 1 file changed, 99 insertions(+) create mode 100644 docs/superpowers/specs/2026-04-19-nix-flake-dev-shell-design.md diff --git a/docs/superpowers/specs/2026-04-19-nix-flake-dev-shell-design.md b/docs/superpowers/specs/2026-04-19-nix-flake-dev-shell-design.md new file mode 100644 index 00000000..8f9a8af9 --- /dev/null +++ b/docs/superpowers/specs/2026-04-19-nix-flake-dev-shell-design.md @@ -0,0 +1,99 @@ +# Nix Flake Dev Shell — Design + +## Overview + +Add a `flake.nix` at the project root that provides a single `devShells.default` containing all +dependencies listed in `doc/BUILD.md`: the Linaro ARM cross-compiler, a Rust toolchain with the +ARM target, native libraries for the emulator, and all thirdparty build tools. Entering the shell +with `nix develop` is sufficient to run `./build.sh` and `./run-emulator.sh`. + +The thirdparty source builds (`thirdparty/build.sh`) are not changed — they continue to +cross-compile their own libs. The flake provides the tools those scripts need (compiler, make, +meson, etc.) and the native libs the emulator links against. + +--- + +## Files + +### `flake.nix` (new) + +Two inputs: + +- `nixpkgs` — pinned to `nixpkgs-unstable` +- `rust-overlay` — `github:oxalica/rust-overlay` + +The `outputs` function calls `rust-overlay.overlays.default` on nixpkgs, then defines +`devShells.default` for `aarch64-darwin` and `x86_64-darwin` (the project runs on macOS). + +The shell's `packages` list: + +| Package | Source | +|---|---| +| Linaro `arm-linux-gnueabihf` toolchain | `nix/linaro.nix` | +| Rust stable + `arm-unknown-linux-gnueabihf` target | `rust-overlay` — `pkgs.rust-bin.stable.latest.default.override { targets = ["arm-unknown-linux-gnueabihf"]; }` | +| SDL2 | `pkgs.SDL2` | +| FreeType | `pkgs.freetype` | +| HarfBuzz | `pkgs.harfbuzz` | +| DjVuLibre | `pkgs.djvulibre` | +| MuPDF 1.27.0 | `pkgs.mupdf` overridden to 1.27.0 (see below) | +| Build tools | `pkgs.gnumake`, `pkgs.meson`, `pkgs.ninja`, `pkgs.cmake`, `pkgs.autoconf`, `pkgs.automake`, `pkgs.libtool`, `pkgs.pkg-config` | + +No `shellHook` is required — all packages expose their `bin/` directories automatically. + +### `nix/linaro.nix` (new) + +A single derivation that: + +1. Fetches `gcc-linaro-4.9.4-2017.01-20170615_darwin.tar.bz2` using `pkgs.fetchurl`. + The direct download URL must be resolved from the Google Drive folder in `doc/BUILD.md` + during implementation (the folder ID is `1YT6x2X070-cg_E8iWvNUUrWg5-t_YcV0`; the per-file + direct link uses the individual file ID, not the folder ID). + SHA256 of the tarball: `sha256:1x3zi21m9gx7p3aqj5cvnb2p7glxqa77abzwqhfszc6a5wjzh8xd` + (computed from the copy in `~/Downloads/`). +2. Unpacks the tarball into `$out` (strip one leading path component). +3. Sets `dontBuild = true`, `dontFixup = true` — the Darwin binaries need no patching on macOS. + +The derivation is a function `{ pkgs }: pkgs.stdenv.mkDerivation { ... }` and is called from +`flake.nix` via `import ./nix/linaro.nix { inherit pkgs; }`. + +### MuPDF 1.27.0 override + +nixpkgs-unstable ships an older MuPDF. We override it inline in `flake.nix`: + +```nix +mupdf' = pkgs.mupdf.overrideAttrs (_: { + version = "1.27.0"; + src = pkgs.fetchurl { + url = "https://casper.mupdf.com/downloads/archive/mupdf-1.27.0-source.tar.gz"; + # hash filled in during implementation with nix-prefetch-url + hash = "sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="; + }; +}); +``` + +The source URL is the same one already used in `thirdparty/download.sh`. + +--- + +## Cargo config + +`.cargo/config.toml` already sets `linker = "arm-linux-gnueabihf-gcc"` for the ARM target. No +changes needed. + +--- + +## Usage + +```sh +nix develop # enter the shell +./build.sh # cross-compile for Kobo +./run-emulator.sh # run the emulator +``` + +--- + +## Out of scope + +- NixOS / Linux support (project is developed on macOS) +- Packaging the build outputs as Nix derivations +- CI integration From c11c2f3e99d4eecb55f5ea4efab6d7a28d7f2c59 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ga=C3=ABtan=20Andr=C3=A9?= Date: Sun, 19 Apr 2026 19:43:37 +0200 Subject: [PATCH 02/14] Add Nix flake dev shell implementation plan Co-Authored-By: Claude Sonnet 4.6 --- .../plans/2026-04-19-nix-flake-dev-shell.md | 525 ++++++++++++++++++ 1 file changed, 525 insertions(+) create mode 100644 docs/superpowers/plans/2026-04-19-nix-flake-dev-shell.md diff --git a/docs/superpowers/plans/2026-04-19-nix-flake-dev-shell.md b/docs/superpowers/plans/2026-04-19-nix-flake-dev-shell.md new file mode 100644 index 00000000..a92c0d51 --- /dev/null +++ b/docs/superpowers/plans/2026-04-19-nix-flake-dev-shell.md @@ -0,0 +1,525 @@ +# Nix Flake Dev Shell Implementation Plan + +> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. + +**Goal:** Add `flake.nix` so that `nix develop` provides every dependency needed to cross-compile Plato for Kobo and run the emulator on macOS. + +**Architecture:** Single `devShells.default` driven by two flake inputs (`nixpkgs-unstable` and `rust-overlay`). Linaro 4.9.4 is packaged as a local derivation in `nix/linaro.nix` that unpacks a manually-downloaded tarball placed at `nix/linaro-darwin.tar.bz2`. MuPDF 1.27.0 is provided by overriding the nixpkgs derivation. All other packages come straight from nixpkgs. + +**Tech Stack:** Nix Flakes 2.4+, nixpkgs-unstable, oxalica/rust-overlay, Nix stdenv (macOS Darwin) + +--- + +## File Map + +| File | Action | Responsibility | +|---|---|---| +| `flake.nix` | Create | Declare inputs, expose `devShells.default` for `aarch64-darwin` and `x86_64-darwin` | +| `nix/linaro.nix` | Create | Derivation that unpacks the Linaro Darwin tarball | +| `nix/linaro-darwin.tar.bz2` | Copy (not committed) | Linaro 4.9.4 tarball from Google Drive | +| `.gitignore` | Modify | Ignore `nix/linaro-darwin.tar.bz2` | +| `flake.lock` | Auto-generated | Pinned input revisions | + +--- + +## Task 1: Stage the Linaro tarball and gitignore it + +**Files:** +- Modify: `.gitignore` +- Create (not committed): `nix/linaro-darwin.tar.bz2` + +- [ ] **Step 1: Create the nix/ directory** + +```bash +mkdir -p nix +``` + +- [ ] **Step 2: Copy the Linaro tarball into place** + +```bash +cp ~/Downloads/gcc-linaro-4.9.4-2017.01-20170615_darwin.tar.bz2 nix/linaro-darwin.tar.bz2 +``` + +- [ ] **Step 3: Verify the SHA256 matches the expected value** + +```bash +shasum -a 256 nix/linaro-darwin.tar.bz2 +``` + +Expected output (the hash must match exactly): +``` +ad23f8252fcab0af1dc4fc2f758ec29dbe73c5b29b1589d5b8a7bf5483887ff4 nix/linaro-darwin.tar.bz2 +``` + +If it doesn't match, do not proceed — the tarball is corrupt or a different version. + +- [ ] **Step 4: Add the tarball to .gitignore** + +Append to `.gitignore`: +``` +/nix/linaro-darwin.tar.bz2 +``` + +- [ ] **Step 5: Commit the .gitignore change** + +```bash +git add .gitignore +git commit -m "chore: ignore Linaro tarball in nix/" +``` + +--- + +## Task 2: Write nix/linaro.nix and verify the ARM compiler appears in PATH + +**Files:** +- Create: `nix/linaro.nix` + +- [ ] **Step 1: Write the derivation** + +Create `nix/linaro.nix`: + +```nix +{ pkgs }: +pkgs.stdenv.mkDerivation { + name = "gcc-linaro-4.9.4-2017.01"; + + src = builtins.path { + name = "gcc-linaro-darwin.tar.bz2"; + path = ./linaro-darwin.tar.bz2; + }; + + unpackPhase = '' + tar -xjf "$src" --strip-components=1 -C . + ''; + + installPhase = '' + mkdir -p "$out" + cp -r . "$out" + ''; + + dontBuild = true; + dontFixup = true; + dontStrip = true; + dontPatchELF = true; +} +``` + +- [ ] **Step 2: Write a minimal flake.nix that only includes the Linaro package (scaffold)** + +Create `flake.nix`: + +```nix +{ + inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable"; + + outputs = { self, nixpkgs }: + let + systems = [ "aarch64-darwin" "x86_64-darwin" ]; + forAllSystems = f: nixpkgs.lib.genAttrs systems f; + in { + devShells = forAllSystems (system: + let + pkgs = import nixpkgs { inherit system; }; + linaro = import ./nix/linaro.nix { inherit pkgs; }; + in { + default = pkgs.mkShell { + packages = [ linaro ]; + }; + } + ); + }; +} +``` + +- [ ] **Step 3: Enter the shell and verify arm-linux-gnueabihf-gcc is on PATH** + +```bash +nix develop --command arm-linux-gnueabihf-gcc --version +``` + +Expected output (version line): +``` +arm-linux-gnueabihf-gcc (Linaro GCC 4.9-2017.01) 4.9.4 +``` + +- [ ] **Step 4: Commit** + +```bash +git add nix/linaro.nix flake.nix +git commit -m "feat(nix): add Linaro 4.9.4 derivation and scaffold flake" +``` + +--- + +## Task 3: Add rust-overlay and the Rust toolchain + +**Files:** +- Modify: `flake.nix` + +- [ ] **Step 1: Verify cargo is NOT yet available (expected failure)** + +```bash +nix develop --command cargo --version +``` + +Expected: error — cargo not found. + +- [ ] **Step 2: Add rust-overlay input and Rust toolchain to flake.nix** + +Replace `flake.nix` entirely: + +```nix +{ + inputs = { + nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable"; + rust-overlay = { + url = "github:oxalica/rust-overlay"; + inputs.nixpkgs.follows = "nixpkgs"; + }; + }; + + outputs = { self, nixpkgs, rust-overlay }: + let + systems = [ "aarch64-darwin" "x86_64-darwin" ]; + forAllSystems = f: nixpkgs.lib.genAttrs systems f; + in { + devShells = forAllSystems (system: + let + pkgs = import nixpkgs { + inherit system; + overlays = [ rust-overlay.overlays.default ]; + }; + linaro = import ./nix/linaro.nix { inherit pkgs; }; + rust = pkgs.rust-bin.stable.latest.default.override { + targets = [ "arm-unknown-linux-gnueabihf" ]; + }; + in { + default = pkgs.mkShell { + packages = [ linaro rust ]; + }; + } + ); + }; +} +``` + +- [ ] **Step 3: Update flake.lock to pin rust-overlay** + +```bash +nix flake update rust-overlay +``` + +- [ ] **Step 4: Verify cargo and rustc are available** + +```bash +nix develop --command cargo --version +nix develop --command rustc --version +``` + +Expected output (exact versions will vary, check for stable channel): +``` +cargo 1.x.x (... ...) +rustc 1.x.x (... ...) +``` + +- [ ] **Step 5: Verify ARM target is present** + +```bash +nix develop --command rustc --print target-list | grep arm-unknown-linux-gnueabihf +``` + +Expected: `arm-unknown-linux-gnueabihf` + +- [ ] **Step 6: Commit** + +```bash +git add flake.nix flake.lock +git commit -m "feat(nix): add Rust stable toolchain with arm-unknown-linux-gnueabihf target" +``` + +--- + +## Task 4: Add SDL2, FreeType, HarfBuzz, DjVuLibre + +**Files:** +- Modify: `flake.nix` + +- [ ] **Step 1: Verify SDL2 is NOT yet available (expected failure)** + +```bash +nix develop --command pkg-config --modversion sdl2 +``` + +Expected: error — sdl2 not found. + +- [ ] **Step 2: Add the four packages to flake.nix** + +Replace the `packages` list in `flake.nix`: + +```nix +packages = [ + linaro + rust + pkgs.SDL2 + pkgs.freetype + pkgs.harfbuzz + pkgs.djvulibre +]; +``` + +- [ ] **Step 3: Verify all four packages are available** + +```bash +nix develop --command pkg-config --modversion sdl2 +nix develop --command pkg-config --modversion freetype2 +nix develop --command pkg-config --modversion harfbuzz +nix develop --command pkg-config --modversion ddjvuapi +``` + +Each command must exit 0 and print a version string. + +- [ ] **Step 4: Commit** + +```bash +git add flake.nix +git commit -m "feat(nix): add SDL2, FreeType, HarfBuzz, DjVuLibre for emulator" +``` + +--- + +## Task 5: Add MuPDF 1.27.0 + +**Files:** +- Modify: `flake.nix` + +- [ ] **Step 1: Verify mupdf is NOT yet available (expected failure)** + +```bash +nix develop --command pkg-config --modversion mupdf +``` + +Expected: error — mupdf not found. + +- [ ] **Step 2: Replace flake.nix entirely with the MuPDF override added** + +```nix +{ + inputs = { + nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable"; + rust-overlay = { + url = "github:oxalica/rust-overlay"; + inputs.nixpkgs.follows = "nixpkgs"; + }; + }; + + outputs = { self, nixpkgs, rust-overlay }: + let + systems = [ "aarch64-darwin" "x86_64-darwin" ]; + forAllSystems = f: nixpkgs.lib.genAttrs systems f; + in { + devShells = forAllSystems (system: + let + pkgs = import nixpkgs { + inherit system; + overlays = [ rust-overlay.overlays.default ]; + }; + linaro = import ./nix/linaro.nix { inherit pkgs; }; + rust = pkgs.rust-bin.stable.latest.default.override { + targets = [ "arm-unknown-linux-gnueabihf" ]; + }; + mupdf' = pkgs.mupdf.overrideAttrs (_old: { + version = "1.27.0"; + src = pkgs.fetchurl { + url = "https://casper.mupdf.com/downloads/archive/mupdf-1.27.0-source.tar.gz"; + hash = "sha256-xuffhESEBMoT0Yio1b6jx6wr+sYmpTctGJnkbUFCJK4="; + }; + patches = []; + }); + in { + default = pkgs.mkShell { + packages = [ + linaro + rust + pkgs.SDL2 + pkgs.freetype + pkgs.harfbuzz + pkgs.djvulibre + mupdf' + ]; + }; + } + ); + }; +} +``` + +- [ ] **Step 3: Build the override (this compiles MuPDF from source — may take a few minutes)** + +```bash +nix develop --command pkg-config --modversion mupdf +``` + +Expected: version string `1.27.0`. + +If the override fails to build due to API changes between the nixpkgs MuPDF version and 1.27.0, also override `buildInputs` to clear version-dependent extras: + +```nix +mupdf' = pkgs.mupdf.overrideAttrs (_old: { + version = "1.27.0"; + src = pkgs.fetchurl { + url = "https://casper.mupdf.com/downloads/archive/mupdf-1.27.0-source.tar.gz"; + hash = "sha256-xuffhESEBMoT0Yio1b6jx6wr+sYmpTctGJnkbUFCJK4="; + }; + patches = []; + buildFlags = [ "HAVE_X11=no" "HAVE_GLUT=no" "shared=yes" ]; +}); +``` + +- [ ] **Step 4: Commit** + +```bash +git add flake.nix +git commit -m "feat(nix): add MuPDF 1.27.0 override" +``` + +--- + +## Task 6: Add thirdparty build tools + +**Files:** +- Modify: `flake.nix` + +These tools are required by the scripts in `thirdparty/` when cross-compiling the C/C++ dependencies (MuPDF, HarfBuzz, DjVuLibre, etc.) for Kobo. + +- [ ] **Step 1: Verify meson is NOT yet available (expected failure)** + +```bash +nix develop --command meson --version +``` + +Expected: error — meson not found. + +- [ ] **Step 2: Add build tools to the packages list in flake.nix** + +```nix +packages = [ + linaro + rust + pkgs.SDL2 + pkgs.freetype + pkgs.harfbuzz + pkgs.djvulibre + mupdf' + # thirdparty build tools + pkgs.gnumake + pkgs.meson + pkgs.ninja + pkgs.cmake + pkgs.autoconf + pkgs.automake + pkgs.libtool + pkgs.pkg-config +]; +``` + +- [ ] **Step 3: Verify all build tools are present** + +```bash +nix develop --command bash -c " + make --version | head -1 && + meson --version && + ninja --version && + cmake --version | head -1 && + autoconf --version | head -1 && + automake --version | head -1 && + libtool --version | head -1 && + pkg-config --version +" +``` + +Each tool must print a version without errors. + +- [ ] **Step 4: Commit** + +```bash +git add flake.nix +git commit -m "feat(nix): add thirdparty build tools (make, meson, ninja, cmake, autotools)" +``` + +--- + +## Task 7: Integration smoke test + +These commands verify that the full shell satisfies all requirements from `doc/BUILD.md`. + +- [ ] **Step 1: Check flake structure is valid** + +```bash +nix flake check +``` + +Expected: exits 0 with no errors. + +- [ ] **Step 2: Verify cross-compiler full triple** + +```bash +nix develop --command bash -c " + arm-linux-gnueabihf-gcc --version | head -1 && + arm-linux-gnueabihf-g++ --version | head -1 && + arm-linux-gnueabihf-ar --version | head -1 && + arm-linux-gnueabihf-strip --version | head -1 +" +``` + +Expected: each prints a Linaro GCC 4.9.4 version line. + +- [ ] **Step 3: Verify Rust + ARM target** + +```bash +nix develop --command bash -c " + rustc --version && + cargo --version && + rustc --target arm-unknown-linux-gnueabihf --print cfg 2>&1 | grep target_arch +" +``` + +Expected: `target_arch=\"arm\"` + +- [ ] **Step 4: Verify emulator native libs** + +```bash +nix develop --command bash -c " + pkg-config --modversion sdl2 && + pkg-config --modversion freetype2 && + pkg-config --modversion harfbuzz && + pkg-config --modversion mupdf +" +``` + +Expected: four version strings, mupdf must be `1.27.0`. + +- [ ] **Step 5: Verify build tools** + +```bash +nix develop --command bash -c " + which make meson ninja cmake autoconf automake libtool pkg-config +" +``` + +Expected: eight paths, all inside the Nix store. + +- [ ] **Step 6: Final commit** + +```bash +git add flake.nix flake.lock nix/linaro.nix .gitignore +git commit -m "feat(nix): complete dev shell with all BUILD.md dependencies" +``` + +--- + +## Appendix: Known hashes + +| Artifact | Hash (SRI) | +|---|---| +| `nix/linaro-darwin.tar.bz2` | `sha256-rSP4JS/KsK8dxPwvdY7Cnb5zxbKbFYnVuKe/VIOIf/Q=` | +| `mupdf-1.27.0-source.tar.gz` | `sha256-xuffhESEBMoT0Yio1b6jx6wr+sYmpTctGJnkbUFCJK4=` | From fadb4f8c136b86edf4cdd77986ac0d5228010479 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ga=C3=ABtan=20Andr=C3=A9?= Date: Sat, 25 Apr 2026 07:15:00 +0200 Subject: [PATCH 03/14] chore: ignore Linaro tarball in nix/ --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index 250af8f8..5a7e5af1 100644 --- a/.gitignore +++ b/.gitignore @@ -15,7 +15,9 @@ /hyphenation-patterns /dictionaries /dist +/books /bundle /plato-*.zip /thirdparty/*/* !/thirdparty/*/*kobo* +/nix/linaro-darwin.tar.bz2 From 73cacece94e987e6fe73f0fa5abc5053bd451f5f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ga=C3=ABtan=20Andr=C3=A9?= Date: Sat, 25 Apr 2026 07:26:38 +0200 Subject: [PATCH 04/14] chore(plan): update Linaro to fetchurl from Google Drive, add Linux support Co-Authored-By: Claude Sonnet 4.6 --- .../plans/2026-04-19-nix-flake-dev-shell.md | 89 +++++++++++++------ 1 file changed, 60 insertions(+), 29 deletions(-) diff --git a/docs/superpowers/plans/2026-04-19-nix-flake-dev-shell.md b/docs/superpowers/plans/2026-04-19-nix-flake-dev-shell.md index a92c0d51..e3d7344f 100644 --- a/docs/superpowers/plans/2026-04-19-nix-flake-dev-shell.md +++ b/docs/superpowers/plans/2026-04-19-nix-flake-dev-shell.md @@ -2,11 +2,11 @@ > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. -**Goal:** Add `flake.nix` so that `nix develop` provides every dependency needed to cross-compile Plato for Kobo and run the emulator on macOS. +**Goal:** Add `flake.nix` so that `nix develop` provides every dependency needed to cross-compile Plato for Kobo and run the emulator on macOS and Linux. -**Architecture:** Single `devShells.default` driven by two flake inputs (`nixpkgs-unstable` and `rust-overlay`). Linaro 4.9.4 is packaged as a local derivation in `nix/linaro.nix` that unpacks a manually-downloaded tarball placed at `nix/linaro-darwin.tar.bz2`. MuPDF 1.27.0 is provided by overriding the nixpkgs derivation. All other packages come straight from nixpkgs. +**Architecture:** Single `devShells.default` driven by two flake inputs (`nixpkgs-unstable` and `rust-overlay`). Linaro 4.9.4 is packaged in `nix/linaro.nix` using `pkgs.fetchurl` to download directly from Google Drive (separate tarballs for Darwin and Linux). On Linux, `autoPatchelfHook` patches the ELF binaries for the Nix environment. MuPDF 1.27.0 is provided by overriding the nixpkgs derivation. All other packages come straight from nixpkgs. -**Tech Stack:** Nix Flakes 2.4+, nixpkgs-unstable, oxalica/rust-overlay, Nix stdenv (macOS Darwin) +**Tech Stack:** Nix Flakes 2.4+, nixpkgs-unstable, oxalica/rust-overlay, Nix stdenv (Darwin + Linux) --- @@ -14,10 +14,9 @@ | File | Action | Responsibility | |---|---|---| -| `flake.nix` | Create | Declare inputs, expose `devShells.default` for `aarch64-darwin` and `x86_64-darwin` | -| `nix/linaro.nix` | Create | Derivation that unpacks the Linaro Darwin tarball | -| `nix/linaro-darwin.tar.bz2` | Copy (not committed) | Linaro 4.9.4 tarball from Google Drive | -| `.gitignore` | Modify | Ignore `nix/linaro-darwin.tar.bz2` | +| `flake.nix` | Create | Declare inputs, expose `devShells.default` for `aarch64-darwin`, `x86_64-darwin`, `x86_64-linux` | +| `nix/linaro.nix` | Create | Derivation that downloads and unpacks the correct Linaro tarball per platform | +| `.gitignore` | Modify (done ✓) | Ignore `nix/linaro-darwin.tar.bz2` (harmless; no local tarball needed) | | `flake.lock` | Auto-generated | Pinned input revisions | --- @@ -79,17 +78,46 @@ git commit -m "chore: ignore Linaro tarball in nix/" Create `nix/linaro.nix`: ```nix -{ pkgs }: +{ pkgs, system }: +let + inherit (pkgs) lib; + + sources = { + "x86_64-darwin" = { + url = "https://drive.usercontent.google.com/download?id=1ggMLM3VBwCYQuFTpJEC0OmyMkiDtYMju&export=download&confirm=t"; + hash = "sha256-rSP4JS/KsK8dxPwvdY7Cnb5zxbKbFYnVuKe/VIOIf/Q="; + }; + "aarch64-darwin" = { + url = "https://drive.usercontent.google.com/download?id=1ggMLM3VBwCYQuFTpJEC0OmyMkiDtYMju&export=download&confirm=t"; + hash = "sha256-rSP4JS/KsK8dxPwvdY7Cnb5zxbKbFYnVuKe/VIOIf/Q="; + }; + "x86_64-linux" = { + url = "https://drive.usercontent.google.com/download?id=1xSf7PzfmI2DD7RHsPhwSy-Ltm8gabblK&export=download&confirm=t"; + hash = "sha256-B6wRny+a/dla8tzL3Lu1U2lcAQeBtSQ4lT+W/RhBkSI="; + }; + }; + source = sources.${system}; +in pkgs.stdenv.mkDerivation { name = "gcc-linaro-4.9.4-2017.01"; - src = builtins.path { - name = "gcc-linaro-darwin.tar.bz2"; - path = ./linaro-darwin.tar.bz2; + src = pkgs.fetchurl { + inherit (source) url hash; }; + # On Linux, autoPatchelfHook patches all ELF binaries to use Nix store paths. + # On Darwin, Mach-O binaries need no patching. + nativeBuildInputs = lib.optionals pkgs.stdenv.isLinux [ + pkgs.autoPatchelfHook + ]; + + buildInputs = lib.optionals pkgs.stdenv.isLinux [ + pkgs.glibc + pkgs.stdenv.cc.cc.lib # libstdc++, libgcc_s + ]; + unpackPhase = '' - tar -xjf "$src" --strip-components=1 -C . + tar -xf "$src" --strip-components=1 -C . ''; installPhase = '' @@ -97,10 +125,10 @@ pkgs.stdenv.mkDerivation { cp -r . "$out" ''; - dontBuild = true; - dontFixup = true; - dontStrip = true; - dontPatchELF = true; + dontBuild = true; + dontStrip = true; + dontFixup = pkgs.stdenv.isDarwin; + dontPatchELF = pkgs.stdenv.isDarwin; } ``` @@ -114,13 +142,13 @@ Create `flake.nix`: outputs = { self, nixpkgs }: let - systems = [ "aarch64-darwin" "x86_64-darwin" ]; + systems = [ "aarch64-darwin" "x86_64-darwin" "x86_64-linux" ]; forAllSystems = f: nixpkgs.lib.genAttrs systems f; in { devShells = forAllSystems (system: let pkgs = import nixpkgs { inherit system; }; - linaro = import ./nix/linaro.nix { inherit pkgs; }; + linaro = import ./nix/linaro.nix { inherit pkgs system; }; in { default = pkgs.mkShell { packages = [ linaro ]; @@ -171,8 +199,8 @@ Replace `flake.nix` entirely: ```nix { inputs = { - nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable"; - rust-overlay = { + nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable"; + rust-overlay = { url = "github:oxalica/rust-overlay"; inputs.nixpkgs.follows = "nixpkgs"; }; @@ -180,7 +208,7 @@ Replace `flake.nix` entirely: outputs = { self, nixpkgs, rust-overlay }: let - systems = [ "aarch64-darwin" "x86_64-darwin" ]; + systems = [ "aarch64-darwin" "x86_64-darwin" "x86_64-linux" ]; forAllSystems = f: nixpkgs.lib.genAttrs systems f; in { devShells = forAllSystems (system: @@ -189,7 +217,7 @@ Replace `flake.nix` entirely: inherit system; overlays = [ rust-overlay.overlays.default ]; }; - linaro = import ./nix/linaro.nix { inherit pkgs; }; + linaro = import ./nix/linaro.nix { inherit pkgs system; }; rust = pkgs.rust-bin.stable.latest.default.override { targets = [ "arm-unknown-linux-gnueabihf" ]; }; @@ -314,7 +342,7 @@ Expected: error — mupdf not found. outputs = { self, nixpkgs, rust-overlay }: let - systems = [ "aarch64-darwin" "x86_64-darwin" ]; + systems = [ "aarch64-darwin" "x86_64-darwin" "x86_64-linux" ]; forAllSystems = f: nixpkgs.lib.genAttrs systems f; in { devShells = forAllSystems (system: @@ -323,7 +351,7 @@ Expected: error — mupdf not found. inherit system; overlays = [ rust-overlay.overlays.default ]; }; - linaro = import ./nix/linaro.nix { inherit pkgs; }; + linaro = import ./nix/linaro.nix { inherit pkgs system; }; rust = pkgs.rust-bin.stable.latest.default.override { targets = [ "arm-unknown-linux-gnueabihf" ]; }; @@ -517,9 +545,12 @@ git commit -m "feat(nix): complete dev shell with all BUILD.md dependencies" --- -## Appendix: Known hashes +## Appendix: Known hashes and URLs + +| Artifact | Google Drive ID | Hash (SRI) | +|---|---|---| +| Linaro Darwin (`gcc-linaro-4.9.4-2017.01-20170615_darwin.tar.bz2`) | `1ggMLM3VBwCYQuFTpJEC0OmyMkiDtYMju` | `sha256-rSP4JS/KsK8dxPwvdY7Cnb5zxbKbFYnVuKe/VIOIf/Q=` | +| Linaro Linux (`gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf.tar.*`) | `1xSf7PzfmI2DD7RHsPhwSy-Ltm8gabblK` | `sha256-B6wRny+a/dla8tzL3Lu1U2lcAQeBtSQ4lT+W/RhBkSI=` | +| `mupdf-1.27.0-source.tar.gz` | — | `sha256-xuffhESEBMoT0Yio1b6jx6wr+sYmpTctGJnkbUFCJK4=` | -| Artifact | Hash (SRI) | -|---|---| -| `nix/linaro-darwin.tar.bz2` | `sha256-rSP4JS/KsK8dxPwvdY7Cnb5zxbKbFYnVuKe/VIOIf/Q=` | -| `mupdf-1.27.0-source.tar.gz` | `sha256-xuffhESEBMoT0Yio1b6jx6wr+sYmpTctGJnkbUFCJK4=` | +Download URL pattern: `https://drive.usercontent.google.com/download?id=&export=download&confirm=t` From 83c7259e4055b68f6b196061aaf2ac1b04d9dde7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ga=C3=ABtan=20Andr=C3=A9?= Date: Sat, 25 Apr 2026 07:29:21 +0200 Subject: [PATCH 05/14] feat(nix): add Linaro 4.9.4 derivation and scaffold flake Co-Authored-By: Claude Sonnet 4.6 --- flake.lock | 27 ++++++++++++++++++++++++++ flake.nix | 20 +++++++++++++++++++ nix/linaro.nix | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 99 insertions(+) create mode 100644 flake.lock create mode 100644 flake.nix create mode 100644 nix/linaro.nix diff --git a/flake.lock b/flake.lock new file mode 100644 index 00000000..b3b55428 --- /dev/null +++ b/flake.lock @@ -0,0 +1,27 @@ +{ + "nodes": { + "nixpkgs": { + "locked": { + "lastModified": 1776949667, + "narHash": "sha256-GMSVw35Q+294GlrTUKlx087E31z7KurReQ1YHSKp5iw=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "01fbdeef22b76df85ea168fbfe1bfd9e63681b30", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "nixpkgs": "nixpkgs" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 00000000..c46d9f7b --- /dev/null +++ b/flake.nix @@ -0,0 +1,20 @@ +{ + inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable"; + + outputs = { self, nixpkgs }: + let + systems = [ "aarch64-darwin" "x86_64-darwin" "x86_64-linux" ]; + forAllSystems = f: nixpkgs.lib.genAttrs systems f; + in { + devShells = forAllSystems (system: + let + pkgs = import nixpkgs { inherit system; }; + linaro = import ./nix/linaro.nix { inherit pkgs system; }; + in { + default = pkgs.mkShell { + packages = [ linaro ]; + }; + } + ); + }; +} diff --git a/nix/linaro.nix b/nix/linaro.nix new file mode 100644 index 00000000..c02585c8 --- /dev/null +++ b/nix/linaro.nix @@ -0,0 +1,52 @@ +{ pkgs, system }: +let + inherit (pkgs) lib; + + sources = { + "x86_64-darwin" = { + url = "https://drive.usercontent.google.com/download?id=1ggMLM3VBwCYQuFTpJEC0OmyMkiDtYMju&export=download&confirm=t"; + hash = "sha256-rSP4JS/KsK8dxPwvdY7Cnb5zxbKbFYnVuKe/VIOIf/Q="; + }; + "aarch64-darwin" = { + url = "https://drive.usercontent.google.com/download?id=1ggMLM3VBwCYQuFTpJEC0OmyMkiDtYMju&export=download&confirm=t"; + hash = "sha256-rSP4JS/KsK8dxPwvdY7Cnb5zxbKbFYnVuKe/VIOIf/Q="; + }; + "x86_64-linux" = { + url = "https://drive.usercontent.google.com/download?id=1xSf7PzfmI2DD7RHsPhwSy-Ltm8gabblK&export=download&confirm=t"; + hash = "sha256-B6wRny+a/dla8tzL3Lu1U2lcAQeBtSQ4lT+W/RhBkSI="; + }; + }; + source = sources.${system}; +in +pkgs.stdenv.mkDerivation { + name = "gcc-linaro-4.9.4-2017.01"; + + src = pkgs.fetchurl { + inherit (source) url hash; + }; + + # On Linux, autoPatchelfHook patches all ELF binaries to use Nix store paths. + # On Darwin, Mach-O binaries need no patching. + nativeBuildInputs = lib.optionals pkgs.stdenv.isLinux [ + pkgs.autoPatchelfHook + ]; + + buildInputs = lib.optionals pkgs.stdenv.isLinux [ + pkgs.glibc + pkgs.stdenv.cc.cc.lib # libstdc++, libgcc_s + ]; + + unpackPhase = '' + tar -xf "$src" --strip-components=1 -C . + ''; + + installPhase = '' + mkdir -p "$out" + cp -r . "$out" + ''; + + dontBuild = true; + dontStrip = true; + dontFixup = pkgs.stdenv.isDarwin; + dontPatchELF = pkgs.stdenv.isDarwin; +} From bad665604c5f4442c2b1a7ee8142f2f162f1fb0e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ga=C3=ABtan=20Andr=C3=A9?= Date: Sat, 25 Apr 2026 08:30:52 +0200 Subject: [PATCH 06/14] feat(nix): add Rust stable toolchain with arm-unknown-linux-gnueabihf target --- flake.lock | 23 ++++++++++++++++++++++- flake.nix | 20 ++++++++++++++++---- 2 files changed, 38 insertions(+), 5 deletions(-) diff --git a/flake.lock b/flake.lock index b3b55428..e2598792 100644 --- a/flake.lock +++ b/flake.lock @@ -18,7 +18,28 @@ }, "root": { "inputs": { - "nixpkgs": "nixpkgs" + "nixpkgs": "nixpkgs", + "rust-overlay": "rust-overlay" + } + }, + "rust-overlay": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1777086717, + "narHash": "sha256-vEl3cGHRxEFdVNuP9PbrhAWnmU98aPOLGy9/1JXzSuM=", + "owner": "oxalica", + "repo": "rust-overlay", + "rev": "3be56bd430bfd65d3c468a50626c3a601c7dee03", + "type": "github" + }, + "original": { + "owner": "oxalica", + "repo": "rust-overlay", + "type": "github" } } }, diff --git a/flake.nix b/flake.nix index c46d9f7b..1b7d6bb3 100644 --- a/flake.nix +++ b/flake.nix @@ -1,18 +1,30 @@ { - inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable"; + inputs = { + nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable"; + rust-overlay = { + url = "github:oxalica/rust-overlay"; + inputs.nixpkgs.follows = "nixpkgs"; + }; + }; - outputs = { self, nixpkgs }: + outputs = { self, nixpkgs, rust-overlay }: let systems = [ "aarch64-darwin" "x86_64-darwin" "x86_64-linux" ]; forAllSystems = f: nixpkgs.lib.genAttrs systems f; in { devShells = forAllSystems (system: let - pkgs = import nixpkgs { inherit system; }; + pkgs = import nixpkgs { + inherit system; + overlays = [ rust-overlay.overlays.default ]; + }; linaro = import ./nix/linaro.nix { inherit pkgs system; }; + rust = pkgs.rust-bin.stable.latest.default.override { + targets = [ "arm-unknown-linux-gnueabihf" ]; + }; in { default = pkgs.mkShell { - packages = [ linaro ]; + packages = [ linaro rust ]; }; } ); From aae6d19b65fbba75ada4acf7dad0b13f44d2b281 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ga=C3=ABtan=20Andr=C3=A9?= Date: Sat, 25 Apr 2026 08:32:06 +0200 Subject: [PATCH 07/14] feat(nix): add SDL2, FreeType, HarfBuzz, DjVuLibre for emulator --- flake.nix | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/flake.nix b/flake.nix index 1b7d6bb3..900585f2 100644 --- a/flake.nix +++ b/flake.nix @@ -24,7 +24,14 @@ }; in { default = pkgs.mkShell { - packages = [ linaro rust ]; + packages = [ + linaro + rust + pkgs.SDL2 + pkgs.freetype + pkgs.harfbuzz + pkgs.djvulibre + ]; }; } ); From 2fcb4d7335ac7f87fe6413a9592a6b14c35f87c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ga=C3=ABtan=20Andr=C3=A9?= Date: Sat, 25 Apr 2026 09:57:45 +0200 Subject: [PATCH 08/14] feat(nix): add MuPDF 1.27.0 override Override nixpkgs mupdf derivation to version 1.27.0 with correct source hash and version string in the generated pkg-config file. Add pkg-config to nativeBuildInputs so PKG_CONFIG_PATH is populated in the dev shell. Co-Authored-By: Claude Sonnet 4.6 --- flake.nix | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/flake.nix b/flake.nix index 900585f2..1dd2a3b5 100644 --- a/flake.nix +++ b/flake.nix @@ -22,15 +22,28 @@ rust = pkgs.rust-bin.stable.latest.default.override { targets = [ "arm-unknown-linux-gnueabihf" ]; }; + mupdf' = pkgs.mupdf.overrideAttrs (old: { + version = "1.27.0"; + src = pkgs.fetchurl { + url = "https://casper.mupdf.com/downloads/archive/mupdf-1.27.0-source.tar.gz"; + hash = "sha256-riRCQW3kmRgtN6UmxvorrMejvtWoiNETygSERITf58Y="; + }; + postInstall = builtins.replaceStrings ["Version: 1.27.2"] ["Version: 1.27.0"] old.postInstall; + }); in { default = pkgs.mkShell { + nativeBuildInputs = [ pkgs.pkg-config ]; packages = [ linaro rust + ]; + buildInputs = [ pkgs.SDL2 pkgs.freetype pkgs.harfbuzz pkgs.djvulibre + mupdf' + mupdf'.dev ]; }; } From d2a1a365b4fe7a6678535d5ae850673ccf3a8093 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ga=C3=ABtan=20Andr=C3=A9?= Date: Sat, 25 Apr 2026 10:04:53 +0200 Subject: [PATCH 09/14] feat(nix): add thirdparty build tools (make, meson, ninja, cmake, autotools) --- flake.nix | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/flake.nix b/flake.nix index 1dd2a3b5..271d53c5 100644 --- a/flake.nix +++ b/flake.nix @@ -36,6 +36,15 @@ packages = [ linaro rust + # thirdparty build tools + pkgs.gnumake + pkgs.meson + pkgs.ninja + pkgs.cmake + pkgs.autoconf + pkgs.automake + pkgs.libtool + pkgs.pkg-config ]; buildInputs = [ pkgs.SDL2 From 1e1289a4e109b3327b067ada156157f6e105b19d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ga=C3=ABtan=20Andr=C3=A9?= Date: Sat, 25 Apr 2026 10:14:07 +0200 Subject: [PATCH 10/14] =?UTF-8?q?fix(nix):=20wire=20up=20emulator=20build?= =?UTF-8?q?=20=E2=80=94=20cross-CC=20env=20vars=20+=20native=20libs=20+=20?= =?UTF-8?q?libmupdf-third=20stub?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Set CC/CXX/AR_arm_unknown_linux_gnueabihf so build scripts use Linaro rather than the Nix-wrapped clang for cross-compiled C crates (zstd-sys). Add libjpeg/libpng/gumbo/openjpeg/jbig2dec/bzip2/zlib to buildInputs for the native emulator target, and create a stub empty libmupdf-third.a (the Nix mupdf package bundles third-party symbols into one dylib). Co-Authored-By: Claude Sonnet 4.6 --- flake.nix | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/flake.nix b/flake.nix index 271d53c5..0280088a 100644 --- a/flake.nix +++ b/flake.nix @@ -53,7 +53,30 @@ pkgs.djvulibre mupdf' mupdf'.dev + # libs needed by plato-core/build.rs for the native emulator target + pkgs.libjpeg + pkgs.libpng + pkgs.gumbo + pkgs.openjpeg + pkgs.jbig2dec + pkgs.bzip2 + pkgs.zlib ]; + shellHook = '' + export CC_arm_unknown_linux_gnueabihf=arm-linux-gnueabihf-gcc + export CXX_arm_unknown_linux_gnueabihf=arm-linux-gnueabihf-g++ + export AR_arm_unknown_linux_gnueabihf=arm-linux-gnueabihf-ar + + # The Nix MuPDF package bundles third-party libs into libmupdf.dylib. + # plato-core/build.rs still links -lmupdf-third on non-ARM targets, + # so we create a stub empty static archive to satisfy the linker. + _stub_dir="$HOME/.cache/plato-nix-stubs" + mkdir -p "$_stub_dir" + if [ ! -f "$_stub_dir/libmupdf-third.a" ]; then + ar rcs "$_stub_dir/libmupdf-third.a" + fi + export LIBRARY_PATH="$_stub_dir''${LIBRARY_PATH:+:$LIBRARY_PATH}" + ''; }; } ); From d2d04613c3979aa5183b244e3278a281c97afb2e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ga=C3=ABtan=20Andr=C3=A9?= Date: Sat, 25 Apr 2026 10:16:23 +0200 Subject: [PATCH 11/14] chore(nix): add clarifying comments, remove duplicate pkg-config if present --- flake.nix | 6 +++--- nix/linaro.nix | 2 ++ 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/flake.nix b/flake.nix index 0280088a..db339159 100644 --- a/flake.nix +++ b/flake.nix @@ -67,9 +67,9 @@ export CXX_arm_unknown_linux_gnueabihf=arm-linux-gnueabihf-g++ export AR_arm_unknown_linux_gnueabihf=arm-linux-gnueabihf-ar - # The Nix MuPDF package bundles third-party libs into libmupdf.dylib. - # plato-core/build.rs still links -lmupdf-third on non-ARM targets, - # so we create a stub empty static archive to satisfy the linker. + # Create a stub libmupdf-third.a: plato-core/build.rs emits -lmupdf-third + # but Nix's MuPDF bundles all third-party symbols into a single libmupdf.so/.dylib. + # This stub satisfies the linker without providing any symbols. _stub_dir="$HOME/.cache/plato-nix-stubs" mkdir -p "$_stub_dir" if [ ! -f "$_stub_dir/libmupdf-third.a" ]; then diff --git a/nix/linaro.nix b/nix/linaro.nix index c02585c8..398dbf16 100644 --- a/nix/linaro.nix +++ b/nix/linaro.nix @@ -7,6 +7,8 @@ let url = "https://drive.usercontent.google.com/download?id=1ggMLM3VBwCYQuFTpJEC0OmyMkiDtYMju&export=download&confirm=t"; hash = "sha256-rSP4JS/KsK8dxPwvdY7Cnb5zxbKbFYnVuKe/VIOIf/Q="; }; + # Both Darwin architectures use the same tarball because the Linaro Darwin binary + # is x86_64 and runs under Rosetta 2 on Apple Silicon. "aarch64-darwin" = { url = "https://drive.usercontent.google.com/download?id=1ggMLM3VBwCYQuFTpJEC0OmyMkiDtYMju&export=download&confirm=t"; hash = "sha256-rSP4JS/KsK8dxPwvdY7Cnb5zxbKbFYnVuKe/VIOIf/Q="; From 3a9e74fc233c320210b16b15064756753821d134 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ga=C3=ABtan=20Andr=C3=A9?= Date: Sat, 25 Apr 2026 10:25:12 +0200 Subject: [PATCH 12/14] docs: document Nix flake setup in BUILD.md Co-Authored-By: Claude Sonnet 4.6 --- doc/BUILD.md | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/doc/BUILD.md b/doc/BUILD.md index f9e42fd7..438ede24 100644 --- a/doc/BUILD.md +++ b/doc/BUILD.md @@ -7,6 +7,33 @@ git clone https://github.com/baskerville/plato.git cd plato ``` +## Nix (recommended) + +A `flake.nix` is provided that supplies every dependency automatically on macOS and Linux. + +Enable flakes (once, user-level): +```sh +mkdir -p ~/.config/nix +echo 'experimental-features = nix-command flakes' >> ~/.config/nix/nix.conf +``` + +Enter the development shell: +```sh +nix develop +``` + +This gives you the Linaro cross-compiler, Rust stable with the ARM target, and all libraries needed for the emulator. From inside the shell, the usual commands apply: + +```sh +./build.sh # cross-compile for Kobo +./run-emulator.sh # run the emulator +./dist.sh # build the distribution archive +``` + +--- + +## Manual Setup + ## Plato #### Preliminary From 20a03d24445db81486a7543666e8aaa1078e14ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ga=C3=ABtan=20Andr=C3=A9?= Date: Sat, 25 Apr 2026 10:38:44 +0200 Subject: [PATCH 13/14] fix(nix): move libmupdf-third stub into Nix store, remove stale tarball MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The stub libmupdf-third.a is now created in mupdf's postInstall so it lives in the Nix store alongside libmupdf.dylib — reproducible for any developer, no ~/.cache writes needed. Remove nix/linaro-darwin.tar.bz2 gitignore entry: the tarball was a leftover from an abandoned local-file approach; nix/linaro.nix fetches directly from Google Drive via fetchurl. Co-Authored-By: Claude Sonnet 4.6 --- .gitignore | 1 - flake.nix | 20 ++++++++------------ 2 files changed, 8 insertions(+), 13 deletions(-) diff --git a/.gitignore b/.gitignore index 5a7e5af1..fd8a58b5 100644 --- a/.gitignore +++ b/.gitignore @@ -20,4 +20,3 @@ /plato-*.zip /thirdparty/*/* !/thirdparty/*/*kobo* -/nix/linaro-darwin.tar.bz2 diff --git a/flake.nix b/flake.nix index db339159..8001d5d6 100644 --- a/flake.nix +++ b/flake.nix @@ -28,11 +28,17 @@ url = "https://casper.mupdf.com/downloads/archive/mupdf-1.27.0-source.tar.gz"; hash = "sha256-riRCQW3kmRgtN6UmxvorrMejvtWoiNETygSERITf58Y="; }; - postInstall = builtins.replaceStrings ["Version: 1.27.2"] ["Version: 1.27.0"] old.postInstall; + postInstall = + (builtins.replaceStrings ["Version: 1.27.2"] ["Version: 1.27.0"] old.postInstall) + + '' + # plato-core/build.rs emits -lmupdf-third on non-ARM targets, but this + # MuPDF build bundles all third-party symbols into libmupdf. + # An empty stub satisfies the linker without providing any symbols. + ar rcs $out/lib/libmupdf-third.a + ''; }); in { default = pkgs.mkShell { - nativeBuildInputs = [ pkgs.pkg-config ]; packages = [ linaro rust @@ -66,16 +72,6 @@ export CC_arm_unknown_linux_gnueabihf=arm-linux-gnueabihf-gcc export CXX_arm_unknown_linux_gnueabihf=arm-linux-gnueabihf-g++ export AR_arm_unknown_linux_gnueabihf=arm-linux-gnueabihf-ar - - # Create a stub libmupdf-third.a: plato-core/build.rs emits -lmupdf-third - # but Nix's MuPDF bundles all third-party symbols into a single libmupdf.so/.dylib. - # This stub satisfies the linker without providing any symbols. - _stub_dir="$HOME/.cache/plato-nix-stubs" - mkdir -p "$_stub_dir" - if [ ! -f "$_stub_dir/libmupdf-third.a" ]; then - ar rcs "$_stub_dir/libmupdf-third.a" - fi - export LIBRARY_PATH="$_stub_dir''${LIBRARY_PATH:+:$LIBRARY_PATH}" ''; }; } From 8c4fc8ac21a3c326c1a5859a7d33dcdf87dab05e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ga=C3=ABtan=20Andr=C3=A9?= Date: Sat, 25 Apr 2026 17:20:45 +0200 Subject: [PATCH 14/14] don't link mupdf-third --- crates/core/build.rs | 6 +++--- flake.nix | 17 +++++++++-------- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/crates/core/build.rs b/crates/core/build.rs index e3ab3e01..d646552c 100644 --- a/crates/core/build.rs +++ b/crates/core/build.rs @@ -16,15 +16,15 @@ fn main() { "linux" => { println!("cargo:rustc-link-search=target/mupdf_wrapper/Linux"); println!("cargo:rustc-link-lib=dylib=stdc++"); - }, + } "macos" => { println!("cargo:rustc-link-search=target/mupdf_wrapper/Darwin"); println!("cargo:rustc-link-lib=dylib=c++"); - }, + } _ => panic!("Unsupported platform: {}.", target_os), } - println!("cargo:rustc-link-lib=mupdf-third"); + // println!("cargo:rustc-link-lib=mupdf-third"); } println!("cargo:rustc-link-lib=z"); diff --git a/flake.nix b/flake.nix index 8001d5d6..497f7f15 100644 --- a/flake.nix +++ b/flake.nix @@ -28,14 +28,14 @@ url = "https://casper.mupdf.com/downloads/archive/mupdf-1.27.0-source.tar.gz"; hash = "sha256-riRCQW3kmRgtN6UmxvorrMejvtWoiNETygSERITf58Y="; }; - postInstall = - (builtins.replaceStrings ["Version: 1.27.2"] ["Version: 1.27.0"] old.postInstall) - + '' - # plato-core/build.rs emits -lmupdf-third on non-ARM targets, but this - # MuPDF build bundles all third-party symbols into libmupdf. - # An empty stub satisfies the linker without providing any symbols. - ar rcs $out/lib/libmupdf-third.a - ''; + # postInstall = + # (builtins.replaceStrings ["Version: 1.27.2"] ["Version: 1.27.0"] old.postInstall) + # + '' + # # plato-core/build.rs emits -lmupdf-third on non-ARM targets, but this + # # MuPDF build bundles all third-party symbols into libmupdf. + # # An empty stub satisfies the linker without providing any symbols. + # ar rcs $out/lib/libmupdf-third.a + # ''; }); in { default = pkgs.mkShell { @@ -43,6 +43,7 @@ linaro rust # thirdparty build tools + pkgs.git pkgs.gnumake pkgs.meson pkgs.ninja