From 37748260ff7838cd835209ad73cff4c29b1e43ec Mon Sep 17 00:00:00 2001 From: Brandon Thomas Date: Mon, 5 Oct 2026 09:22:16 -0400 Subject: [PATCH] FreeBSD: release tarball and platform docs The release workflow gains a FreeBSD x86_64 job: packaging/freebsd/package.sh builds in the same pinned FreeBSD VM and writes a /usr/local-style tar.gz (app, CLI, desktop entry, MIME type, AppStream metadata, icons, licences). README and CLAUDE.md list FreeBSD now that its CI job builds PrintCraft and passes all 688 tests on FreeBSD 14.3. Co-Authored-By: Claude Opus 5.5 --- .github/workflows/release.yml | 40 +++++++++++++++++++++++- CLAUDE.md | 2 +- README.md | 6 ++-- packaging/freebsd/package.sh | 58 +++++++++++++++++++++++++++++++++++ 4 files changed, 101 insertions(+), 5 deletions(-) create mode 100755 packaging/freebsd/package.sh diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 3f17eb957..d26fba090 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -201,6 +201,44 @@ jobs: path: dist/release/* if-no-files-found: error + freebsd: + name: FreeBSD x86_64 + needs: version + # GitHub has no FreeBSD runners: build in a FreeBSD VM (see .github/workflows/freebsd.yml). + runs-on: ubuntu-latest + environment: release + timeout-minutes: 180 + env: + PRINTCRAFT_VERSION: ${{ needs.version.outputs.version }} + PRINTCRAFT_BUILD_DATE: ${{ needs.version.outputs.date }} + VERSION_OVERRIDE: ${{ inputs.version }} + steps: + - uses: actions/checkout@v4 + - name: Build and package in a FreeBSD VM (tar.gz) + # vmactions/freebsd-vm v1.5.9, pinned by commit (it runs our build). + uses: vmactions/freebsd-vm@c46abacb49f09938ca4e1702d15d836285d694cc + with: + release: "14.3" + usesh: true + mem: 12288 + envs: "PRINTCRAFT_VERSION PRINTCRAFT_BUILD_DATE VERSION_OVERRIDE" + prepare: | + pkg install -y bash curl git cmake pkgconf llvm19 perl5 \ + libxkbcommon wayland libX11 libXrandr libXi libXcursor mesa-libs gtk3 + curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --profile minimal --default-toolchain stable + run: | + set -e + . "$HOME/.cargo/env" + git config --global --add safe.directory "$PWD" + export LIBCLANG_PATH=/usr/local/llvm19/lib CARGO_BUILD_JOBS=4 + if [ -n "$VERSION_OVERRIDE" ]; then cargo xtask version set "$PRINTCRAFT_VERSION"; fi + packaging/freebsd/package.sh + - uses: actions/upload-artifact@v4 + with: + name: release-freebsd-x86_64 + path: dist/release/* + if-no-files-found: error + web: name: Web (wasm) needs: version @@ -236,7 +274,7 @@ jobs: release: name: Draft GitHub Release - needs: [version, macos, windows, linux, web] + needs: [version, macos, windows, linux, freebsd, web] runs-on: ubuntu-latest environment: release permissions: diff --git a/CLAUDE.md b/CLAUDE.md index 49b1c705a..46fb2650d 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1,6 +1,6 @@ # PrintCraft — instructions for agents -PrintCraft is a clean-room, open-source, Rust-native PDF application targeting Adobe Acrobat Pro parity. It runs natively on macOS, Windows and Linux, and on the web via WASM. It is the sibling of `../photocraft` (a Photoshop-class editor) and follows the same conventions. +PrintCraft is a clean-room, open-source, Rust-native PDF application targeting Adobe Acrobat Pro parity. It runs natively on macOS, Windows, Linux and FreeBSD, and on the web via WASM. It is the sibling of `../photocraft` (a Photoshop-class editor) and follows the same conventions. ## Start every session here 1. Read `plan/STATUS.md`: the current milestone, the next unchecked task and any blockers. `ROADMAP.md` holds the milestone estimates and progress; update its table and log at the end of every session. diff --git a/README.md b/README.md index e21dbfdf7..86d9ef598 100644 --- a/README.md +++ b/README.md @@ -13,13 +13,13 @@

The PDF workbench; an open-source, clean-room reimplementation of Adobe Acrobat, rebuilt in pure Rust.
Read, organize, combine, split and secure PDFs in a fast, native app, written in Rust from the ground up.
- macOS · Windows · Linux · the web + macOS · Windows · Linux · FreeBSD · the web

License: MIT OR Apache-2.0 Written in Rust - Platforms: macOS, Windows, Linux, web + Platforms: macOS, Windows, Linux, FreeBSD, web No account, no telemetry

@@ -256,7 +256,7 @@ Press ⌘K to search every tool and command, or browse the **All tool ## Runs everywhere, stays yours -- **Native on macOS, Windows and Linux**, and **in the browser** through WebAssembly, from the same Rust codebase. +- **Native on macOS, Windows, Linux and FreeBSD**, and **in the browser** through WebAssembly, from the same Rust codebase. - **Private by design.** Documents never leave your machine. There's no account, no telemetry and no cloud processing. - **Engine first.** Parsing, rendering and editing live in reusable library crates. The interface is one swappable layer on top. - **Scriptable.** The `printcraft-cli` tool (see [Built for agents, too](#built-for-agents-too)) covers inspecting, rendering, extracting text, editing, combining, extracting pages and splitting. Robustness sweeps run on the same engine as the app. diff --git a/packaging/freebsd/package.sh b/packaging/freebsd/package.sh new file mode 100755 index 000000000..3d24d4220 --- /dev/null +++ b/packaging/freebsd/package.sh @@ -0,0 +1,58 @@ +#!/usr/bin/env bash +# Build PrintCraft for FreeBSD and package it: +# $DIST/printcraft--freebsd-.tar.gz a /usr/local-style tree (bin/, share/) +# +# Extract it into /usr/local (or anywhere, and run bin/printcraft from there). The desktop entry, +# MIME type, AppStream metadata and icons are the freedesktop ones Linux uses. +# +# Usage: packaging/freebsd/package.sh [--skip-build] +# Needs: bash, a Rust toolchain, and the GUI libraries in .github/workflows/freebsd.yml. +set -euo pipefail +# shellcheck source=../env.sh +. "$(dirname "${BASH_SOURCE[0]}")/../env.sh" +LINUX="$ROOT/packaging/linux" +APP_ID=ai.storyteller.printcraft + +SKIP_BUILD=0 +while [ $# -gt 0 ]; do + case "$1" in + --skip-build) SKIP_BUILD=1; shift ;; + -h | --help) sed -n '2,9p' "$0"; exit 0 ;; + *) echo "unknown argument: $1" >&2; exit 2 ;; + esac +done + +ARCH="$(uname -m)" +case "$ARCH" in + amd64 | x86_64) ARCH=x86_64 ;; + arm64 | aarch64) ARCH=aarch64 ;; + *) echo "unsupported architecture $ARCH" >&2; exit 2 ;; +esac +BASENAME="printcraft-$VERSION-freebsd-$ARCH" + +echo "==> PrintCraft $VERSION for FreeBSD $ARCH" + +if [ "$SKIP_BUILD" = 0 ]; then + (cd "$ROOT" && cargo build --release --locked -p printcraft -p printcraft-cli) +fi +BIN="$CARGO_TARGET_DIR/release" +WORK="$CARGO_TARGET_DIR/freebsd-package" +STAGE="$WORK/$BASENAME" +rm -rf "$WORK" + +# FreeBSD's install(1) has no -D: create the directories first. +mkdir -p "$STAGE/bin" "$STAGE/share/applications" "$STAGE/share/mime/packages" "$STAGE/share/metainfo" \ + "$STAGE/share/icons" "$STAGE/share/doc/printcraft" +install -m 755 "$BIN/printcraft" "$BIN/printcraft-cli" "$STAGE/bin/" +strip "$STAGE/bin/printcraft" "$STAGE/bin/printcraft-cli" 2>/dev/null || true +install -m 644 "$LINUX/$APP_ID.desktop" "$STAGE/share/applications/$APP_ID.desktop" +install -m 644 "$LINUX/$APP_ID.mime.xml" "$STAGE/share/mime/packages/$APP_ID.xml" +sed -e "s/@VERSION@/$VERSION/g" -e "s/@DATE@/$PRINTCRAFT_BUILD_DATE/g" \ + "$LINUX/$APP_ID.metainfo.xml.in" >"$STAGE/share/metainfo/$APP_ID.metainfo.xml" +cp -R "$ROOT/assets/app-icon/hicolor" "$STAGE/share/icons/" +copy_docs "$STAGE/share/doc/printcraft" + +"$STAGE/bin/printcraft" --version +mkdir -p "$DIST" +tar -C "$WORK" -czf "$DIST/$BASENAME.tar.gz" "$BASENAME" +echo "wrote $DIST/$BASENAME.tar.gz"