From e916640efe57349a8f2cd8e827438c5794cc14cb Mon Sep 17 00:00:00 2001 From: Alex Samorukov Date: Mon, 5 Oct 2026 17:02:04 +0200 Subject: [PATCH] feat(fff-bun): allow an explicit native library via FFF_C_LIB Some platforms have no @ff-labs/fff-bin-* prebuilt. FreeBSD builds the C library cleanly from source, but nothing publishes it, so an npm install can never resolve it. Add an FFF_C_LIB override, checked before the npm package and the local dev build, so such a build is usable from a normal install (and from a bun --compile binary, where resolution happens at runtime). Also recognise freebsd in getTriple(), allow @ff-labs/fff-bun to install there, and make resolveFromNpmPackage() return null instead of throwing when the platform has no package mapped. --- packages/fff-bun/README.md | 14 ++++++++++++++ packages/fff-bun/package.json | 3 ++- packages/fff-bun/src/download.ts | 24 +++++++++++++++++++++--- packages/fff-bun/src/platform.ts | 2 ++ 4 files changed, 39 insertions(+), 4 deletions(-) diff --git a/packages/fff-bun/README.md b/packages/fff-bun/README.md index 0e7c480e3..5e98725ab 100644 --- a/packages/fff-bun/README.md +++ b/packages/fff-bun/README.md @@ -29,6 +29,20 @@ The correct native binary for your platform is installed automatically via platf If the platform package isn't available, the postinstall script will attempt to download from GitHub releases as a fallback. +### Platforms without a prebuilt package + +On a platform that has no `@ff-labs/fff-bin-*` package, build the C library from +source and point `@ff-labs/fff-bun` at it with `FFF_C_LIB`: + +```bash +cargo build --release -p fff-c +FFF_C_LIB=target/release/libfff_c.so bun ./app.ts +``` + +`FFF_C_LIB` is checked before the platform package and the local dev build, so it +also works for a regular `bun add @ff-labs/fff-bun` install. If the path does not +exist, resolution fails with an explicit error rather than silently falling back. + ### Standalone executables (`bun build --compile`) `@ff-labs/fff-bun` embeds the native library into single-file executables built diff --git a/packages/fff-bun/package.json b/packages/fff-bun/package.json index ec5ff0734..4813048ab 100644 --- a/packages/fff-bun/package.json +++ b/packages/fff-bun/package.json @@ -33,7 +33,8 @@ "darwin", "linux", "win32", - "android" + "android", + "freebsd" ], "cpu": [ "x64", diff --git a/packages/fff-bun/src/download.ts b/packages/fff-bun/src/download.ts index 74918f3d2..a3b70c22f 100644 --- a/packages/fff-bun/src/download.ts +++ b/packages/fff-bun/src/download.ts @@ -2,8 +2,9 @@ * Binary resolution utilities for fff * * Resolves the native library from: - * 1. Platform-specific npm package (e.g. @ff-labs/fff-bin-darwin-arm64) - * 2. Local dev build (target/release or target/debug) + * 1. The FFF_C_LIB environment variable (explicit path to libfff_c.so/.dylib/.dll) + * 2. Platform-specific npm package (e.g. @ff-labs/fff-bin-darwin-arm64) + * 3. Local dev build (target/release or target/debug) */ import { existsSync } from "node:fs"; @@ -54,7 +55,13 @@ export function binaryExists(): boolean { * in the same directory. */ function resolveFromNpmPackage(): string | null { - const packageName = getNpmPackageName(); + let packageName: string; + try { + packageName = getNpmPackageName(); + } catch { + // Unsupported platform, or no platform package mapped for it. + return null; + } try { // Use createRequire to resolve the platform package's location @@ -105,12 +112,23 @@ function isDevWorkspace(): boolean { * Find the native library binary. * * Resolution order: + * - FFF_C_LIB (if set) always wins * - Dev workspace: local dev build first, then npm package * - Production: npm package first, then dev build * * @returns Absolute path to the library, or null if not found */ export function findBinary(): string | null { + // Explicit override for platforms without a prebuilt package (for example a + // libfff_c.so built from source on FreeBSD, or any custom build). + const override = process.env["FFF_C_LIB"]; + if (override) { + if (!existsSync(override)) { + throw new Error(`FFF_C_LIB points to a file that does not exist: ${override}`); + } + return override; + } + if (isDevWorkspace()) { // 1. Local bin/ directory (populated by `make prepare-bun`) const binPath = join(getPackageDir(), "bin", getLibFilename()); diff --git a/packages/fff-bun/src/platform.ts b/packages/fff-bun/src/platform.ts index 11070e206..c659795f0 100644 --- a/packages/fff-bun/src/platform.ts +++ b/packages/fff-bun/src/platform.ts @@ -20,6 +20,8 @@ export function getTriple(): string { osName = detectLinuxLibc(); } else if (platform === "win32") { osName = "pc-windows-msvc"; + } else if (platform === "freebsd") { + osName = "unknown-freebsd"; } else { throw new Error(`Unsupported platform: ${platform}`); }