diff --git a/.github/workflows/_build.yml b/.github/workflows/_build.yml index 82d2f6241..42f9480cd 100644 --- a/.github/workflows/_build.yml +++ b/.github/workflows/_build.yml @@ -334,3 +334,83 @@ jobs: with: name: binaries-linux-${{ matrix.arch }}-portable path: "*.tar.gz" + + build-freebsd: + name: build-unix (freebsd-${{ matrix.release }}, freebsd, ${{ matrix.arch }}, clang, clang++) + strategy: + fail-fast: false + matrix: + release: ['15.1', '14.4'] + arch: ['x86_64'] + # arch: ['x86_64', 'aarch64'] + # aarch64 disabled for now: lightningcss (a native Rust dependency of + # the Vite/CSS build pipeline) publishes no prebuilt binary for + # freebsd-arm64, so `npm run build` fails with "Cannot find module + # '../lightningcss.freebsd-arm64.node'" — a real gap in that + # package's platform coverage, not something fixable on our side + # without vendoring a Rust build of it. Re-enable once lightningcss + # ships that target, or once the frontend build is moved to run + # natively on a Linux host instead of inside the FreeBSD VM. + include: + - arch: x86_64 + artifact_arch: amd64 + sync: rsync + # - arch: aarch64 + # artifact_arch: arm64-aarch64 + # sync: scp + # Must use ubuntu-latest (x86_64 host). Running QEMU guest emulation on arm runners (ubuntu-*-arm) + # causes severe performance degradation leading to 3+ hour timeouts. + runs-on: ubuntu-latest + timeout-minutes: 240 + steps: + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + + - name: Build FreeBSD ${{ matrix.release }} (${{ matrix.arch }}) binaries inside VM + # https://github.com/vmactions/freebsd-vm + uses: vmactions/freebsd-vm@83b151f58c6047089f4c80eb5ba2039d158ce093 # v1 + with: + release: ${{ matrix.release }} + arch: ${{ matrix.arch }} + # Sync options: rsync, sshfs, nfs, scp + sync: ${{ matrix.sync }} + usesh: true + mem: 6144 + cpu: 4 + prepare: | + pkg update -f + pkg install -y gmake sqlite3 pkgconf node22 npm-node22 bash + which python3 >/dev/null 2>&1 || ln -sf $(which python3.15 python3.14 python3.13 python3.12 python3.11 python3.10 2>/dev/null | head -n 1) /usr/local/bin/python3 + run: | + # Build standard binary (canonical scripts/build.sh pattern) + if [ -n "${{ inputs.version }}" ]; then + scripts/build.sh --version "${{ inputs.version }}" CC=clang CXX=clang++ + else + scripts/build.sh CC=clang CXX=clang++ + fi + scripts/package-release.sh freebsd ${{ matrix.arch }}-${{ matrix.release }} + + # Build UI binary + if [ -n "${{ inputs.version }}" ]; then + scripts/build.sh --version "${{ inputs.version }}" --with-ui CC=clang CXX=clang++ + else + scripts/build.sh --with-ui CC=clang CXX=clang++ + fi + scripts/package-release.sh freebsd ${{ matrix.arch }}-${{ matrix.release }} --variant ui + + - name: Attest standard binary provenance + if: ${{ inputs.attest }} + uses: actions/attest-build-provenance@0f67c3f4856b2e3261c31976d6725780e5e4c373 # v4.1.1 + with: + subject-path: codebase-memory-mcp-freebsd-${{ matrix.artifact_arch }}-${{ matrix.release }}.tar.gz + + - name: Attest UI binary provenance + if: ${{ inputs.attest }} + uses: actions/attest-build-provenance@0f67c3f4856b2e3261c31976d6725780e5e4c373 # v4.1.1 + with: + subject-path: codebase-memory-mcp-ui-freebsd-${{ matrix.artifact_arch }}-${{ matrix.release }}.tar.gz + + - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + with: + name: binaries-freebsd-${{ matrix.artifact_arch }}-${{ matrix.release }} + path: "*.tar.gz" + diff --git a/scripts/build.sh b/scripts/build.sh index 575477a94..7fd7426b5 100755 --- a/scripts/build.sh +++ b/scripts/build.sh @@ -149,10 +149,10 @@ cbm_remove_build_dir "$ROOT" "$BUILD_DIR" # Step 2: Build (Makefile applies $ARCHFLAGS for the target arch on macOS) if $WITH_UI; then - make -j"$NPROC" -f Makefile.cbm cbm-with-ui \ + $MAKE -j"$NPROC" -f Makefile.cbm cbm-with-ui \ CFLAGS_EXTRA="$CFLAGS_EXTRA" "${EXTRA_MAKE_ARGS[@]+"${EXTRA_MAKE_ARGS[@]}"}" else - make -j"$NPROC" -f Makefile.cbm cbm \ + $MAKE -j"$NPROC" -f Makefile.cbm cbm \ CFLAGS_EXTRA="$CFLAGS_EXTRA" "${EXTRA_MAKE_ARGS[@]+"${EXTRA_MAKE_ARGS[@]}"}" fi diff --git a/scripts/env.sh b/scripts/env.sh index e23affe4c..0d0e7b6f6 100755 --- a/scripts/env.sh +++ b/scripts/env.sh @@ -7,7 +7,7 @@ # ARCH — target architecture (arm64 / x86_64) # ARCHFLAGS — "-arch " on macOS (target slice for clang/ld), empty elsewhere # NPROC — number of CPU cores -# OS — darwin / linux / windows +# OS — darwin / linux / windows / freebsd set -euo pipefail @@ -16,10 +16,21 @@ OS="$(uname -s | tr '[:upper:]' '[:lower:]')" case "$OS" in darwin) OS="darwin" ;; linux) OS="linux" ;; + freebsd*) OS="freebsd" ;; mingw*|msys*|cygwin*) OS="windows" ;; *) OS="unknown" ;; esac +# ── Set platform-appropriate make ────────────────────────────── +# FreeBSD ships BSD make as the default 'make'; GNU Makefile syntax in +# Makefile.cbm requires gmake. All other platforms use 'make'. +if [[ "$OS" == "freebsd" ]]; then + MAKE=gmake +else + MAKE=make +fi +export MAKE + # ── Detect / override architecture ───────────────────────────── # Default: native HARDWARE architecture (not Rosetta-translated). # On macOS under Rosetta, uname -m returns x86_64 even on Apple Silicon. diff --git a/scripts/package-release.sh b/scripts/package-release.sh index 72b090704..868fbfc54 100755 --- a/scripts/package-release.sh +++ b/scripts/package-release.sh @@ -23,7 +23,7 @@ Usage: scripts/package-release.sh [--variant standard|ui] The canonical release-archive step: identical in the release build and the local artifact-flow smoke lane. - goos linux | darwin | windows + goos linux | darwin | windows | freebsd goarch arch label used verbatim in the archive name (amd64, arm64, arm64-portable, ...) --variant standard (default) | ui — selects the archive NAME prefix; the @@ -77,8 +77,8 @@ for arg in "$@"; do done [ -n "$GOOS" ] && [ -n "$GOARCH" ] || { usage >&2; exit 2; } case "$GOOS" in -linux | darwin | windows) ;; -*) echo "package-release: goos must be linux, darwin or windows." >&2; exit 2 ;; +linux | darwin | windows | freebsd) ;; +*) echo "package-release: goos must be linux, darwin, windows or freebsd." >&2; exit 2 ;; esac case "$VARIANT" in standard) SUFFIX="" ;;