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"