Skip to content

[JSCOnly] Add FreeBSD cross-compile target#197

Merged
Jarred-Sumner merged 6 commits into
mainfrom
claude/freebsd-support
Apr 24, 2026
Merged

[JSCOnly] Add FreeBSD cross-compile target#197
Jarred-Sumner merged 6 commits into
mainfrom
claude/freebsd-support

Conversation

@Jarred-Sumner

Copy link
Copy Markdown
Collaborator

WebKit already has full FreeBSD source support (OS(FREEBSD) in PlatformOS.h, MachineContext.h ucontext access, the CMAKE_SYSTEM_NAME MATCHES "FreeBSD" branch in PlatformJSCOnly.cmake). This PR adds the build infrastructure to publish bun-webkit-freebsd-{amd64,arm64}{,-debug} prebuilts, following the same pattern as #196 (Android).

Changes

  • Dockerfile.freebsd — Ubuntu 24.04 host + apt.llvm.org clang-21, FreeBSD 14.3 base.txz sysroot, two-stage ICU cross-build (host tools → --with-cross-build), then CMAKE_SYSTEM_NAME=FreeBSD JSCOnly build. Unlike Android, no compiler-rt resource-dir symlinking is needed: FreeBSD ships builtins as /usr/lib/libgcc.a and clang's freebsd driver finds it via --sysroot.
  • freebsd-release.sh — docker buildx wrapper (mirrors android-release.sh). Selects FREEBSD_ARCH={x86_64,aarch64} with arch-appropriate -march defaults.
  • .github/workflows/build-reusable.ymlfreebsd job (4-way {x86_64,aarch64}×{Release,Debug} matrix on linux-x64-gh), release download/rename/upload steps.

Testing

Verified locally that clang --target=x86_64-unknown-freebsd14.3 --sysroot=<base.txz> produces a valid ELF 64-bit LSB executable, x86-64, version 1 (FreeBSD) for both C and C++ (libc++ from sysroot).

Companion Bun PR: oven-sh/bun (jarred/freebsd).

WebKit already has full FreeBSD source support (OS(FREEBSD),
MachineContext.h, PlatformJSCOnly.cmake's FreeBSD branch). This adds
the build infrastructure to produce bun-webkit-freebsd-{amd64,arm64}
prebuilts:

- Dockerfile.freebsd: Ubuntu host + clang-21, base.txz sysroot,
  two-stage ICU cross-build, CMAKE_SYSTEM_NAME=FreeBSD JSCOnly build.
  No compiler-rt symlinking needed — FreeBSD ships builtins as
  /usr/lib/libgcc.a and clang's freebsd driver finds it via --sysroot.
- freebsd-release.sh: docker buildx wrapper (mirrors android-release.sh).
- build-reusable.yml: 4-way {x64,arm64}×{Release,Debug} matrix on
  linux-x64-gh, plus release download/rename/upload steps.
- BPlatform.h: add BOS(FREEBSD) to BENABLE_LIBPAS condition (libpas
  already has PAS_OS_FREEBSD support — _umtx_op futex, MADV_FREE).
- AvailableMemory.cpp/RAMSize.cpp: drop sys/sysinfo.h include for
  FreeBSD (Linux-only header); use sysctlbyname("hw.physmem") in
  computeAvailableMemory's FreeBSD branch.
- pas_monotonic_time.c: add PAS_OS(FREEBSD) branch using
  clock_gettime(CLOCK_MONOTONIC_FAST).
- PlatformJSCOnly.cmake: link execinfo on FreeBSD (backtrace() lives
  in libexecinfo, not libc).
@coderabbitai

coderabbitai Bot commented Apr 24, 2026

Copy link
Copy Markdown

Walkthrough

Adds FreeBSD build support: CI job producing FreeBSD tarballs, Docker cross-compilation pipeline producing FreeBSD WebKit/ICU artifacts, and platform-specific source changes for ARM64 assembly, memory detection, monotonic time, and bmalloc configuration.

Changes

Cohort / File(s) Summary
CI/CD Workflow
.github/workflows/build-reusable.yml
Adds a freebsd matrix job producing four FreeBSD artifacts (amd64/arm64 × Release/Debug); updates release job to depend on freebsd, download/rename artifacts to ./out/bun-webkit-freebsd-*.tar.gz, and publish them to GitHub releases.
Docker build & release script
Dockerfile.freebsd, freebsd-release.sh
Adds a multi-stage Dockerfile.freebsd that cross-compiles ICU and WebKit for FreeBSD (stages: base, build_icu, build_webkit, artifact) and emits aggregated /output; adds freebsd-release.sh to drive docker buildx with arch/version/release-type/LTO flags and export artifacts locally.
JavaScriptCore ARM64 platform support
Source/JavaScriptCore/assembler/ARM64Assembler.h, Source/JavaScriptCore/assembler/ARM64Registers.h, Source/JavaScriptCore/offlineasm/arm64.rb
Implements cacheFlush for FreeBSD using __builtin___clear_cache; extends ARM64 GP register macro to include FreeBSD; routes globaladdr handling for FreeBSD through the ELF GOT relocation path.
Platform memory and linking changes
Source/WTF/wtf/AvailableMemory.cpp, Source/WTF/wtf/RAMSize.cpp, Source/WTF/wtf/PlatformJSCOnly.cmake
For FreeBSD, read physical memory via sysctlbyname("hw.physmem") (fallback to previous guess on failure); restricts sys/sysinfo.h inclusion to Linux; adds execinfo to WTF link libraries for FreeBSD.
Allocator and monotonic time
Source/bmalloc/bmalloc/BPlatform.h, Source/bmalloc/libpas/src/libpas/pas_monotonic_time.c
Enables BENABLE_LIBPAS on FreeBSD for x86_64 and ARM64 CPU paths; adds FreeBSD-specific pas_get_current_monotonic_time_nanoseconds() implemented via clock_gettime(CLOCK_MONOTONIC_FAST, ...).
🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title '[JSCOnly] Add FreeBSD cross-compile target' directly and concisely summarizes the main change: adding FreeBSD cross-compilation support to the JSCOnly build infrastructure.
Description check ✅ Passed The PR description is comprehensive and well-structured, explaining the rationale, listing detailed changes, and mentioning testing. However, it lacks the required Bugzilla bug link and 'Reviewed by' attribution format specified in the WebKit PR template.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Comment @coderabbitai help to get the list of available commands and usage tips.

- offlineasm/arm64.rb: globaladdr uses :got:/:got_lo12: ELF relocs on
  FreeBSD (same as Linux — both are ELF/AAPCS64)
- ARM64Registers.h: FreeBSD shares the Linux GP register macro list
  (x18 is callee-saved, not platform-reserved like Darwin)

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 6

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.github/workflows/build-reusable.yml:
- Around line 459-462: Update the GitHub Actions step that uses
docker/setup-buildx-action@v2 by changing the action version to
docker/setup-buildx-action@v4 and remove the deprecated install: true input;
locate the step with id: buildx (currently referencing
docker/setup-buildx-action@v2) and replace the version tag and delete the
install parameter so the step conforms to v4 usage.
- Around line 808-815: Replace every usage of the GitHub Action
softprops/action-gh-release@v1 with softprops/action-gh-release@v2 across this
workflow file; specifically update the FreeBSD release step that currently lists
files like ./out/bun-webkit-freebsd-*.tar.gz (and all other occurrences of
softprops/action-gh-release@v1) to use `@v2` so the workflow benefits from the
JS/TS cross-platform implementation and consistent behavior.

In `@Dockerfile.freebsd`:
- Around line 29-32: The Dockerfile currently pipes the remote llvm.sh into bash
and extracts FreeBSD base.txz without integrity checks; change the llvm install
step (the RUN line invoking wget -qO- https://apt.llvm.org/llvm.sh | bash -s --
${LLVM_VERSION}) to instead download the script to disk (preserve
${LLVM_VERSION} usage), set executable bit, and run it locally after verifying
its integrity/signature, and for the FreeBSD stage download base.txz and its
published checksum/signature from the FreeBSD signatures URL and verify the
archive with the published SHA512/SHA256 or PGP signature before extraction
(fail the build on mismatch); ensure the Dockerfile aborts on verification
failure and does not use network-piped shell execution or unverified archives.
- Around line 155-157: The CMake find root modes are currently set to BOTH which
allows fallback to host artifacts; change CMAKE_FIND_ROOT_PATH_MODE_PACKAGE,
CMAKE_FIND_ROOT_PATH_MODE_LIBRARY, and CMAKE_FIND_ROOT_PATH_MODE_INCLUDE from
BOTH to ONLY so CMake only searches the FreeBSD sysroot, and also export
PKG_CONFIG_SYSROOT_DIR and PKG_CONFIG_LIBDIR pointing at the FreeBSD sysroot so
pkg-config resolves target libs/headers from the sysroot rather than the host
environment.

In `@Source/bmalloc/libpas/src/libpas/pas_monotonic_time.c`:
- Line 97: Replace the floating-point nanosecond conversion with integer math to
avoid precision loss: compute the result as (uint64_t)ts.tv_sec * 1000000000ULL
+ (uint64_t)ts.tv_nsec using the existing ts, tv_sec and tv_nsec variables (and
ensure the function return type is an integer type like uint64_t if not
already).
- Around line 91-98: The FreeBSD branch uses struct timespec and clock_gettime
in pas_get_current_monotonic_time_nanoseconds but doesn't explicitly include
<time.h>; update the platform include guard that currently adds <time.h> for
Linux/PlayStation to also cover PAS_OS(FREEBSD) so the FreeBSD branch explicitly
includes <time.h> (ensure the change is made alongside the existing
include-guard pattern used for other platforms to keep consistency).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 9c1cea6d-4fec-40ff-b84a-bc7b75b0e835

📥 Commits

Reviewing files that changed from the base of the PR and between a4ddad8 and 621cd4a.

📒 Files selected for processing (11)
  • .github/workflows/build-reusable.yml
  • Dockerfile.freebsd
  • Source/JavaScriptCore/assembler/ARM64Assembler.h
  • Source/JavaScriptCore/assembler/ARM64Registers.h
  • Source/JavaScriptCore/offlineasm/arm64.rb
  • Source/WTF/wtf/AvailableMemory.cpp
  • Source/WTF/wtf/PlatformJSCOnly.cmake
  • Source/WTF/wtf/RAMSize.cpp
  • Source/bmalloc/bmalloc/BPlatform.h
  • Source/bmalloc/libpas/src/libpas/pas_monotonic_time.c
  • freebsd-release.sh

Comment on lines +459 to +462
- uses: docker/setup-buildx-action@v2
id: buildx
with:
install: true

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

# Check if the file exists and read lines around 459-462
if [ -f ".github/workflows/build-reusable.yml" ]; then
  echo "=== Lines 455-465 of build-reusable.yml ==="
  sed -n '455,465p' ".github/workflows/build-reusable.yml" | cat -n
else
  echo "File not found, listing workflow files:"
  find .github/workflows -name "*.yml" -o -name "*.yaml" | head -20
fi

Repository: oven-sh/WebKit

Length of output: 485


🌐 Web query:

docker/setup-buildx-action v2 v3 deprecation supported versions

💡 Result:

The docker/setup-buildx-action GitHub Action has versions v2, v3, and v4. v2 is outdated and should be upgraded (examples show migration from v2 to v3). In v3.12.0 (Dec 2025), the 'install' input was deprecated due to upstream docker/buildx changes. v4.0.0 (Mar 2026, current latest as of Apr 2026) fully removes deprecated inputs/outputs including 'install', 'config', 'config-inline', and some outputs like 'endpoint', 'status', 'flags'. Use v4 with recent GitHub Actions runners (v2.327.1+ for Node 24 runtime). Official README examples use docker/setup-buildx-action@v4. v2 and v3 remain functional but lack latest features and fixes; migrate to v4 for support.

Citations:


Upgrade to docker/setup-buildx-action@v4 and remove the deprecated install parameter.

Line 459 uses docker/setup-buildx-action@v2, which is outdated. The current version is v4 (as of Mar 2026). When upgrading, remove the install: true parameter, which was deprecated in v3.12.0 and removed in v4.0.0.

Proposed fix
-      - uses: docker/setup-buildx-action@v2
+      - uses: docker/setup-buildx-action@v4
         id: buildx
-        with:
-          install: true
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
- uses: docker/setup-buildx-action@v2
id: buildx
with:
install: true
- uses: docker/setup-buildx-action@v4
id: buildx
🧰 Tools
🪛 actionlint (1.7.12)

[error] 459-459: the runner of "docker/setup-buildx-action@v2" action is too old to run on GitHub Actions. update the action's version to fix this issue

(action)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/build-reusable.yml around lines 459 - 462, Update the
GitHub Actions step that uses docker/setup-buildx-action@v2 by changing the
action version to docker/setup-buildx-action@v4 and remove the deprecated
install: true input; locate the step with id: buildx (currently referencing
docker/setup-buildx-action@v2) and replace the version tag and delete the
install parameter so the step conforms to v4 usage.

Comment on lines +808 to +815
- uses: softprops/action-gh-release@v1
with:
tag_name: ${{ inputs.release_tag }}
files: |
./out/bun-webkit-freebsd-amd64.tar.gz
./out/bun-webkit-freebsd-amd64-debug.tar.gz
./out/bun-webkit-freebsd-arm64.tar.gz
./out/bun-webkit-freebsd-arm64-debug.tar.gz

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

# First, let's read the workflow file around the specified lines
wc -l .github/workflows/build-reusable.yml

Repository: oven-sh/WebKit

Length of output: 99


🏁 Script executed:

# Read the context around lines 808-815
sed -n '800,820p' .github/workflows/build-reusable.yml

Repository: oven-sh/WebKit

Length of output: 835


🏁 Script executed:

# Search for all uses of softprops/action-gh-release in the workflow file
rg "softprops/action-gh-release" .github/workflows/build-reusable.yml -n -A 10

Repository: oven-sh/WebKit

Length of output: 3083


🏁 Script executed:

# Search for actionlint config or mentions in the repo
fd actionlint

Repository: oven-sh/WebKit

Length of output: 40


🏁 Script executed:

# Check for any linting configuration files
fd -e yaml -e yml | rg -i "actionlint|action" | head -20

Repository: oven-sh/WebKit

Length of output: 360


🏁 Script executed:

# Look for GitHub Actions documentation or version constraints
rg "action-gh-release" . --type yaml -B 2 -A 10 | head -50

Repository: oven-sh/WebKit

Length of output: 40


🏁 Script executed:

# Check if there's any actionlint configuration in common locations
ls -la .github/ | grep -i action

Repository: oven-sh/WebKit

Length of output: 40


🏁 Script executed:

# Look for any workflow linting or CI configuration
find .github -type f -name "*.yml" -o -name "*.yaml" | xargs grep -l "actionlint" 2>/dev/null

Repository: oven-sh/WebKit

Length of output: 42


🌐 Web query:

softprops/action-gh-release v1 vs v2 differences deprecated

💡 Result:

softprops/action-gh-release v1 and v2 are major versions of this GitHub Action for creating GitHub Releases. v1 was originally implemented as a Docker container, limiting it to Linux runners only, and required a 'docker://' prefix in some usages. v2 (starting around 2024 with v2.0.0) rewrote it as a JavaScript/TypeScript action for cross-platform support (Linux, Windows, macOS), removed the Docker dependency (no more 'docker://' prefix needed), upgraded the Node runtime (e.g., to node16 then node20), fixed deprecations like set-output warnings, added/improved inputs like make_latest, previous_tag, working_directory, discussion_category_name, append_body, and enhanced features like better asset handling, error recovery, generate_release_notes support, and numerous bug fixes (e.g., concurrent uploads, prerelease behavior). v1 is effectively legacy/outdated; upgrade to v2 (latest v2.6.2 as of 2026-04) or v3 (Node 24). No explicit deprecation notice for v1, but Dependabot auto-upgrades from v1 to v2, and docs/examples use v2/v3.

Citations:


Use @v2 for softprops/action-gh-release and update all existing instances in this workflow.

The FreeBSD release step at lines 808-815 (and all other uses of softprops/action-gh-release@v1 in this file) should be upgraded to @v2. Version 1 is a legacy Docker-based implementation; v2 provides cross-platform support via JavaScript/TypeScript, improved Node runtime, and better feature support. Lines 763, 769, 786, 799, 808, 817, and 828 all need this update for consistency and to avoid maintenance issues.

Proposed fix for FreeBSD section
-      - uses: softprops/action-gh-release@v1
+      - uses: softprops/action-gh-release@v2
         with:
           tag_name: ${{ inputs.release_tag }}
           files: |
             ./out/bun-webkit-freebsd-amd64.tar.gz
             ./out/bun-webkit-freebsd-amd64-debug.tar.gz
             ./out/bun-webkit-freebsd-arm64.tar.gz
             ./out/bun-webkit-freebsd-arm64-debug.tar.gz
🧰 Tools
🪛 actionlint (1.7.12)

[error] 808-808: the runner of "softprops/action-gh-release@v1" action is too old to run on GitHub Actions. update the action's version to fix this issue

(action)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/build-reusable.yml around lines 808 - 815, Replace every
usage of the GitHub Action softprops/action-gh-release@v1 with
softprops/action-gh-release@v2 across this workflow file; specifically update
the FreeBSD release step that currently lists files like
./out/bun-webkit-freebsd-*.tar.gz (and all other occurrences of
softprops/action-gh-release@v1) to use `@v2` so the workflow benefits from the
JS/TS cross-platform implementation and consistent behavior.

Comment thread Dockerfile.freebsd
Comment on lines +29 to +32
RUN wget -qO- https://apt.llvm.org/llvm.sh | bash -s -- ${LLVM_VERSION} && \
for t in clang clang++ ld.lld lld llvm-ar llvm-ranlib; do \
ln -sf /usr/bin/${t}-${LLVM_VERSION} /usr/local/bin/${t}; \
done

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🌐 Web query:

What is the recommended apt.llvm.org installation flow that avoids piping llvm.shtobash, and where are the official checksum/signature files for FreeBSD 14.3 RELEASE base.txz published?

💡 Result:

The recommended apt.llvm.org installation flow that avoids piping llvm.sh to bash is: wget https://apt.llvm.org/llvm.sh chmod +x llvm.sh sudo ./llvm.sh [version] To install all packages: sudo ./llvm.sh [version] all (or sudo ./llvm.sh all for latest stable). No official checksum or signature files are published for llvm.sh itself on apt.llvm.org; verification relies on HTTPS/TLS and the repo GPG key at https://apt.llvm.org/llvm-snapshot.gpg.key (fingerprint: 6084 F3CF 814B 57C1 CF12 EFD5 15CF 4D18 AF4F 7421). Source packages in the repos use sigstore/rekor for verification. Official checksum/signature files for FreeBSD 14.3-RELEASE base.txz (and other install sets) are published at https://www.freebsd.org/releases/14.3R/signatures/ as PGP-signed SHA512 and SHA256 checksum files per architecture (e.g., SHA512 for amd64 base.txz, etc.).

Citations:


Verify downloaded toolchain and sysroot using published checksums before using them in release builds.

Lines 29–32 pipe a network-fetched script directly into bash as root. The recommended approach is to download, inspect, and execute locally:

RUN wget https://apt.llvm.org/llvm.sh && chmod +x llvm.sh && ./llvm.sh ${LLVM_VERSION}

Lines 42–50 extract base.txz without integrity verification. FreeBSD publishes PGP-signed SHA512/SHA256 checksums at https://www.freebsd.org/releases/14.3R/signatures/. Validate the downloaded archive against the official checksum before extraction.

This stage produces published prebuilts; unverified inputs introduce supply-chain risk.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Dockerfile.freebsd` around lines 29 - 32, The Dockerfile currently pipes the
remote llvm.sh into bash and extracts FreeBSD base.txz without integrity checks;
change the llvm install step (the RUN line invoking wget -qO-
https://apt.llvm.org/llvm.sh | bash -s -- ${LLVM_VERSION}) to instead download
the script to disk (preserve ${LLVM_VERSION} usage), set executable bit, and run
it locally after verifying its integrity/signature, and for the FreeBSD stage
download base.txz and its published checksum/signature from the FreeBSD
signatures URL and verify the archive with the published SHA512/SHA256 or PGP
signature before extraction (fail the build on mismatch); ensure the Dockerfile
aborts on verification failure and does not use network-piped shell execution or
unverified archives.

Comment thread Dockerfile.freebsd
Comment on lines +155 to +157
-DCMAKE_FIND_ROOT_PATH_MODE_PACKAGE=BOTH \
-DCMAKE_FIND_ROOT_PATH_MODE_LIBRARY=BOTH \
-DCMAKE_FIND_ROOT_PATH_MODE_INCLUDE=BOTH \

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🌐 Web query:

For a CMake cross-compilation that sets CMAKE_SYSROOT, when should CMAKE_FIND_ROOT_PATH_MODE_PACKAGE/LIBRARY/INCLUDEbeONLYinstead ofBOTH, and what host-contamination risks does BOTH introduce?

💡 Result:

Use ONLY mode for CMAKE_FIND_ROOT_PATH_MODE_PACKAGE, CMAKE_FIND_ROOT_PATH_MODE_LIBRARY, and CMAKE_FIND_ROOT_PATH_MODE_INCLUDE when cross-compiling with CMAKE_SYSROOT set, to ensure CMake's find_* commands (find_package, find_library, find_path) search exclusively in the sysroot and CMAKE_FIND_ROOT_PATH directories for target libraries, headers, and packages. Use ONLY in strict cross-compilation scenarios where the sysroot contains all required target dependencies. This is the recommended best practice in toolchain files, as shown in official CMake documentation examples. It forces isolation from the host system, preventing CMake from finding incompatible target artifacts on the host. BOTH mode searches both sysroot paths first, then host system paths. Host-contamination risks include: - Linking against host libraries of wrong architecture, causing linker errors or runtime failures (e.g., x86_64 host lib vs ARM target). - Including host headers with mismatched APIs/versions/ABIs, leading to subtle bugs, compilation failures, or binaries depending on unavailable host-specific symbols on target. - Silent failures where builds succeed but produce broken binaries (e.g., wrong glibc versions, versioned symbols). - Particularly dangerous with package managers like Conan that may override to BOTH, allowing fallback to /usr/lib on host. Set in toolchain file example: set(CMAKE_SYSROOT /path/to/target/sysroot) set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) # host tools set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)

Citations:


Restrict CMake package/library/header discovery to the FreeBSD sysroot.

Using CMAKE_FIND_ROOT_PATH_MODE_{PACKAGE,LIBRARY,INCLUDE}=BOTH allows CMake to fall back to Ubuntu host artifacts during cross-compilation, risking mixed host/target inputs and broken FreeBSD binaries. Change these to ONLY to enforce sysroot-only discovery.

🔧 Suggested change
-    -DCMAKE_FIND_ROOT_PATH_MODE_PACKAGE=BOTH \
-    -DCMAKE_FIND_ROOT_PATH_MODE_LIBRARY=BOTH \
-    -DCMAKE_FIND_ROOT_PATH_MODE_INCLUDE=BOTH \
+    -DCMAKE_FIND_ROOT_PATH_MODE_PACKAGE=ONLY \
+    -DCMAKE_FIND_ROOT_PATH_MODE_LIBRARY=ONLY \
+    -DCMAKE_FIND_ROOT_PATH_MODE_INCLUDE=ONLY \

If dependencies are discovered through pkg-config, also set PKG_CONFIG_SYSROOT_DIR and PKG_CONFIG_LIBDIR to the FreeBSD sysroot.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
-DCMAKE_FIND_ROOT_PATH_MODE_PACKAGE=BOTH \
-DCMAKE_FIND_ROOT_PATH_MODE_LIBRARY=BOTH \
-DCMAKE_FIND_ROOT_PATH_MODE_INCLUDE=BOTH \
-DCMAKE_FIND_ROOT_PATH_MODE_PACKAGE=ONLY \
-DCMAKE_FIND_ROOT_PATH_MODE_LIBRARY=ONLY \
-DCMAKE_FIND_ROOT_PATH_MODE_INCLUDE=ONLY \
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Dockerfile.freebsd` around lines 155 - 157, The CMake find root modes are
currently set to BOTH which allows fallback to host artifacts; change
CMAKE_FIND_ROOT_PATH_MODE_PACKAGE, CMAKE_FIND_ROOT_PATH_MODE_LIBRARY, and
CMAKE_FIND_ROOT_PATH_MODE_INCLUDE from BOTH to ONLY so CMake only searches the
FreeBSD sysroot, and also export PKG_CONFIG_SYSROOT_DIR and PKG_CONFIG_LIBDIR
pointing at the FreeBSD sysroot so pkg-config resolves target libs/headers from
the sysroot rather than the host environment.

Comment on lines +91 to +98
#elif PAS_OS(FREEBSD)

uint64_t pas_get_current_monotonic_time_nanoseconds(void)
{
struct timespec ts;
clock_gettime(CLOCK_MONOTONIC_FAST, &ts);
return ts.tv_sec * 1.0e9 + ts.tv_nsec;
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

find . -path "*libpas/pas_monotonic_time.c" -type f

Repository: oven-sh/WebKit

Length of output: 114


🏁 Script executed:

cat -n ./Source/bmalloc/libpas/src/libpas/pas_monotonic_time.c

Repository: oven-sh/WebKit

Length of output: 4580


🏁 Script executed:

cat -n ./Source/bmalloc/libpas/src/libpas/pas_monotonic_time.h

Repository: oven-sh/WebKit

Length of output: 1883


🏁 Script executed:

head -100 ./Source/bmalloc/libpas/src/libpas/pas_config.h

Repository: oven-sh/WebKit

Length of output: 3386


🏁 Script executed:

head -150 ./Source/bmalloc/libpas/src/libpas/pas_utils.h | grep -A 5 -B 5 "include"

Repository: oven-sh/WebKit

Length of output: 1415


Add explicit <time.h> coverage for the FreeBSD branch.

The FreeBSD implementation at lines 95-96 uses struct timespec and clock_gettime(), both defined in <time.h>. Currently, the <time.h> include guard (lines 39-41) covers only Linux and PlayStation, leaving FreeBSD to rely on transitive includes. Extend the include guard to explicitly include <time.h> for FreeBSD, matching the pattern used for other platforms.

Proposed diff
-#if PAS_OS(LINUX) || PAS_PLATFORM(PLAYSTATION)
+#if PAS_OS(LINUX) || PAS_OS(FREEBSD) || PAS_PLATFORM(PLAYSTATION)
 `#include` <time.h>
 `#endif`
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Source/bmalloc/libpas/src/libpas/pas_monotonic_time.c` around lines 91 - 98,
The FreeBSD branch uses struct timespec and clock_gettime in
pas_get_current_monotonic_time_nanoseconds but doesn't explicitly include
<time.h>; update the platform include guard that currently adds <time.h> for
Linux/PlayStation to also cover PAS_OS(FREEBSD) so the FreeBSD branch explicitly
includes <time.h> (ensure the change is made alongside the existing
include-guard pattern used for other platforms to keep consistency).

Comment thread Source/bmalloc/libpas/src/libpas/pas_monotonic_time.c Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

♻️ Duplicate comments (1)
Source/bmalloc/libpas/src/libpas/pas_monotonic_time.c (1)

39-41: ⚠️ Potential issue | 🟡 Minor

Avoid relying on transitive <time.h> includes for the FreeBSD path.

The new FreeBSD branch (Line 95 and Line 96) uses struct timespec / clock_gettime, but the explicit <time.h> include guard (Line 39) still excludes PAS_OS(FREEBSD). This is fragile and can break with header-order changes.

Proposed fix
-#if PAS_OS(LINUX) || PAS_PLATFORM(PLAYSTATION)
+#if PAS_OS(LINUX) || PAS_OS(FREEBSD) || PAS_PLATFORM(PLAYSTATION)
 `#include` <time.h>
 `#endif`
#!/bin/bash
# Verify explicit header coverage for APIs used by the FreeBSD branch.

set -euo pipefail

FILE="Source/bmalloc/libpas/src/libpas/pas_monotonic_time.c"

echo "== Include guard region =="
sed -n '34,45p' "$FILE"

echo
echo "== FreeBSD monotonic branch =="
sed -n '91,100p' "$FILE"

echo
echo "== Confirm API usage lines =="
rg -n 'timespec|clock_gettime|CLOCK_MONOTONIC_FAST|#include <time.h>' "$FILE"

Also applies to: 91-98

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Source/bmalloc/libpas/src/libpas/pas_monotonic_time.c` around lines 39 - 41,
The FreeBSD branch in pas_monotonic_time.c uses struct timespec, clock_gettime
and CLOCK_MONOTONIC_FAST but the existing conditional include for <time.h> only
covers LINUX and PLAYSTATION; update the include guard to also cover
PAS_OS(FREEBSD) so the header is explicitly included for the FreeBSD path
(locate the include block near the top of pas_monotonic_time.c and the FreeBSD
branch that references clock_gettime/struct timespec), ensuring the FreeBSD
compilation does not rely on transitive includes.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@Source/bmalloc/libpas/src/libpas/pas_monotonic_time.c`:
- Around line 39-41: The FreeBSD branch in pas_monotonic_time.c uses struct
timespec, clock_gettime and CLOCK_MONOTONIC_FAST but the existing conditional
include for <time.h> only covers LINUX and PLAYSTATION; update the include guard
to also cover PAS_OS(FREEBSD) so the header is explicitly included for the
FreeBSD path (locate the include block near the top of pas_monotonic_time.c and
the FreeBSD branch that references clock_gettime/struct timespec), ensuring the
FreeBSD compilation does not rely on transitive includes.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 5c6af556-1a3f-4c24-aaf7-6a73e5b8a4f4

📥 Commits

Reviewing files that changed from the base of the PR and between 621cd4a and 55a5c39.

📒 Files selected for processing (1)
  • Source/bmalloc/libpas/src/libpas/pas_monotonic_time.c

…4-gh)

Release builds were running 50+ min and the runner was dying. Debug
builds (which are -O0) finish in ~10 min like Android, so it's the
combination of -O3 + -g + tmpfs that overflows the runner's RAM. Debug
prebuilts keep -g; Release prebuilts don't need it.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@Dockerfile.freebsd`:
- Around line 1-6: The ARG MARCH_FLAG default "-march=haswell" is
x86_64-specific and will break aarch64 builds; update Dockerfile.freebsd to
either make MARCH_FLAG empty by default (ARG MARCH_FLAG="") or add a build-time
validation that inspects FREEBSD_ARCH and fails with a clear message if
FREEBSD_ARCH="aarch64" while MARCH_FLAG contains an x86-only flag (mirror the
architecture validation logic used elsewhere in the file). Target the ARG names
MARCH_FLAG and FREEBSD_ARCH when implementing the change so callers can override
MARCH_FLAG for x86_64 builds or get a helpful error for mismatched arch/flags.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 703179c5-cd23-4ee8-ba73-01e0a1006d9e

📥 Commits

Reviewing files that changed from the base of the PR and between 55a5c39 and c3475f2.

📒 Files selected for processing (1)
  • Dockerfile.freebsd

Comment thread Dockerfile.freebsd
Comment on lines +1 to +6
ARG MARCH_FLAG="-march=haswell"
ARG WEBKIT_RELEASE_TYPE=Release
ARG LTO_FLAG=""
ARG LLVM_VERSION="21"
ARG FREEBSD_VERSION="14.3"
ARG FREEBSD_ARCH="x86_64"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Default MARCH_FLAG is incompatible with aarch64 builds.

-march=haswell is an x86_64 instruction set flag and will cause clang to error when targeting aarch64-unknown-freebsd*. While freebsd-release.sh overrides this, invoking the Dockerfile directly with FREEBSD_ARCH=aarch64 without also overriding MARCH_FLAG will fail.

Consider adding validation or using an empty default:

🔧 Suggested fix
-ARG MARCH_FLAG="-march=haswell"
+ARG MARCH_FLAG=""

Alternatively, add a build-time check similar to line 50's architecture validation.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
ARG MARCH_FLAG="-march=haswell"
ARG WEBKIT_RELEASE_TYPE=Release
ARG LTO_FLAG=""
ARG LLVM_VERSION="21"
ARG FREEBSD_VERSION="14.3"
ARG FREEBSD_ARCH="x86_64"
ARG MARCH_FLAG=""
ARG WEBKIT_RELEASE_TYPE=Release
ARG LTO_FLAG=""
ARG LLVM_VERSION="21"
ARG FREEBSD_VERSION="14.3"
ARG FREEBSD_ARCH="x86_64"
🧰 Tools
🪛 Checkov (3.2.524)

[low] 1-183: Ensure that HEALTHCHECK instructions have been added to container images

(CKV_DOCKER_2)


[low] 1-183: Ensure that a user for the container has been created

(CKV_DOCKER_3)

🪛 Trivy (0.69.3)

[error] 1-1: Image user should not be 'root'

Specify at least 1 USER command in Dockerfile with non-root user as argument

Rule: DS-0002

Learn more

(IaC/Dockerfile)


[info] 1-1: No HEALTHCHECK defined

Add HEALTHCHECK instruction in your Dockerfile

Rule: DS-0026

Learn more

(IaC/Dockerfile)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Dockerfile.freebsd` around lines 1 - 6, The ARG MARCH_FLAG default
"-march=haswell" is x86_64-specific and will break aarch64 builds; update
Dockerfile.freebsd to either make MARCH_FLAG empty by default (ARG
MARCH_FLAG="") or add a build-time validation that inspects FREEBSD_ARCH and
fails with a clear message if FREEBSD_ARCH="aarch64" while MARCH_FLAG contains
an x86-only flag (mirror the architecture validation logic used elsewhere in the
file). Target the ARG names MARCH_FLAG and FREEBSD_ARCH when implementing the
change so callers can override MARCH_FLAG for x86_64 builds or get a helpful
error for mismatched arch/flags.

@github-actions

Copy link
Copy Markdown

Preview Builds

Commit Release Date
c3475f2f autobuild-preview-pr-197-c3475f2f 2026-04-24 10:20:33 UTC

@Jarred-Sumner Jarred-Sumner merged commit 09f5c54 into main Apr 24, 2026
43 checks passed
Jarred-Sumner added a commit to oven-sh/bun that referenced this pull request Apr 25, 2026
Replaces the preview-pr-197 tag now that the FreeBSD prebuilts are in
a regular autobuild release on WebKit main.
Jarred-Sumner added a commit to oven-sh/bun that referenced this pull request Apr 26, 2026
Adds FreeBSD as a cross-compile target, following the same model as
#29675 (Android): host clang + `--target=x86_64-unknown-freebsd14.3
--sysroot=<base.txz>`.

Closes #29675

**Stacked on #29675** — this PR includes the Android commits since both
share the `crossTarget`/`sysroot` build infrastructure. The
FreeBSD-specific diff starts at `d892fcae0a`.

**Depends on oven-sh/WebKit#197** for `bun-webkit-freebsd-*` prebuilts.

Closes #1524, closes #22991.

## Status

- [x] `zig build check-freebsd` clean (x64+aarch64, Debug+ReleaseFast)
- [x] All C/C++ compiles for FreeBSD
- [x] `bun-debug` + `bun` (release) link as valid FreeBSD 14.3 ELF
- [x] **Runs on real FreeBSD 14.3** ([smoke
test](https://github.com/oven-sh/bun/actions/runs/24879912532)):
`--revision`, `process.platform`, `os.*`, fs, **`Bun.serve()` +
`fetch()`** all work
- [x] **All 4 WebKit FreeBSD prebuilts published** (oven-sh/WebKit#197)
- [x] **All 6 BuildKite FreeBSD jobs pass**
(`{x64,aarch64}-build-{cpp,zig,bun}`)
- [x] BuildKite v32 images baked with FreeBSD sysroot
- [x] 10 bughunt findings fixed (copy_file_range loop, watcher
registration, io.tick, futex wake, detached spawn, getRSS, blob
read_len, os.machine, crash metadata, copyFile fast path)

## Approach

FreeBSD is a separate **OS** (not a Linux abi like Android), so it goes
in `type OS = ...|"freebsd"`, `Environment.isFreeBSD`,
`OperatingSystem.freebsd`. It shares kqueue with macOS but uses plain
`kevent`/`struct kevent` (not Darwin's `kevent64_s`), and FreeBSD 13+
has `eventfd(2)` and `copy_file_range(2)`.

Builtins: FreeBSD ships compiler-rt as `/usr/lib/libgcc.a` and clang's
freebsd driver finds it via `--sysroot` — no resource-dir symlinking
needed (unlike NDK).

aarch64-unknown-freebsd is a Rust Tier 3 target (no prebuilt std), so
lolhtml uses `-Zbuild-std` for that arch.

Host-GCC include leak: on amazonlinux, clang's driver injects
`/usr/include/c++/N` even with `--sysroot`, breaking `#include_next` in
the sysroot's libc++. Fixed with `-nostdlibinc` + explicit `-isystem`
for the two sysroot dirs.

## Prior art

Builds on lwhsu/bun `claude/freebsd-support` (Zig source changes,
adapted from old CMake build to `scripts/build/*.ts`) and nektro's
`af85c02f6d` (`zig build check-freebsd`).

---------

Co-authored-by: Sosuke Suzuki <sosuke@bun.com>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
xhjkl pushed a commit to xhjkl/bun that referenced this pull request May 14, 2026
…#29676)

Adds FreeBSD as a cross-compile target, following the same model as
oven-sh#29675 (Android): host clang + `--target=x86_64-unknown-freebsd14.3
--sysroot=<base.txz>`.

Closes oven-sh#29675

**Stacked on oven-sh#29675** — this PR includes the Android commits since both
share the `crossTarget`/`sysroot` build infrastructure. The
FreeBSD-specific diff starts at `d892fcae0a`.

**Depends on oven-sh/WebKit#197** for `bun-webkit-freebsd-*` prebuilts.

Closes oven-sh#1524, closes oven-sh#22991.

## Status

- [x] `zig build check-freebsd` clean (x64+aarch64, Debug+ReleaseFast)
- [x] All C/C++ compiles for FreeBSD
- [x] `bun-debug` + `bun` (release) link as valid FreeBSD 14.3 ELF
- [x] **Runs on real FreeBSD 14.3** ([smoke
test](https://github.com/oven-sh/bun/actions/runs/24879912532)):
`--revision`, `process.platform`, `os.*`, fs, **`Bun.serve()` +
`fetch()`** all work
- [x] **All 4 WebKit FreeBSD prebuilts published** (oven-sh/WebKit#197)
- [x] **All 6 BuildKite FreeBSD jobs pass**
(`{x64,aarch64}-build-{cpp,zig,bun}`)
- [x] BuildKite v32 images baked with FreeBSD sysroot
- [x] 10 bughunt findings fixed (copy_file_range loop, watcher
registration, io.tick, futex wake, detached spawn, getRSS, blob
read_len, os.machine, crash metadata, copyFile fast path)

## Approach

FreeBSD is a separate **OS** (not a Linux abi like Android), so it goes
in `type OS = ...|"freebsd"`, `Environment.isFreeBSD`,
`OperatingSystem.freebsd`. It shares kqueue with macOS but uses plain
`kevent`/`struct kevent` (not Darwin's `kevent64_s`), and FreeBSD 13+
has `eventfd(2)` and `copy_file_range(2)`.

Builtins: FreeBSD ships compiler-rt as `/usr/lib/libgcc.a` and clang's
freebsd driver finds it via `--sysroot` — no resource-dir symlinking
needed (unlike NDK).

aarch64-unknown-freebsd is a Rust Tier 3 target (no prebuilt std), so
lolhtml uses `-Zbuild-std` for that arch.

Host-GCC include leak: on amazonlinux, clang's driver injects
`/usr/include/c++/N` even with `--sysroot`, breaking `#include_next` in
the sysroot's libc++. Fixed with `-nostdlibinc` + explicit `-isystem`
for the two sysroot dirs.

## Prior art

Builds on lwhsu/bun `claude/freebsd-support` (Zig source changes,
adapted from old CMake build to `scripts/build/*.ts`) and nektro's
`af85c02f6d` (`zig build check-freebsd`).

---------

Co-authored-by: Sosuke Suzuki <sosuke@bun.com>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant