Skip to content

fix(linux): make the Linux build work on arm64 - #293

Merged
EtienneLescot merged 2 commits into
getopenscreen:mainfrom
zebster-cmd:fix/linux-arm64-build
Aug 8, 2026
Merged

fix(linux): make the Linux build work on arm64#293
EtienneLescot merged 2 commits into
getopenscreen:mainfrom
zebster-cmd:fix/linux-arm64-build

Conversation

@zebster-cmd

@zebster-cmd zebster-cmd commented Aug 6, 2026

Copy link
Copy Markdown

Summary

npm run build:linux cannot complete on an aarch64 host. This fixes four independent x86-only assumptions in the Linux build path, so the same command produces a working arm64 deb/AppImage.

Change Problem it fixes
scripts/fetch-ffmpeg.mjs SHARED_PINNED has no linux-arm64 entry, so the SDK fetch bails. BtbN publishes the asset in the already-pinned release — only the pin was missing. Digest taken from that release's checksums.sha256.
scripts/build-linux-compositor-addon.mjs /usr/lib/x86_64-linux-gnu and /usr/lib/gcc/x86_64-linux-gnu are hardcoded, hiding both libclang and gcc's stddef.h on arm64. Now derived from process.arch.
scripts/build-linux-pipewire-helper.mjs bindgen dies with 'limits.h' file not found — Ubuntu ships libclang.so.1 with no resource dir. Now passes BINDGEN_EXTRA_CLANG_ARGS at gcc's includes, the same fallback build-linux-compositor-addon.mjs already applies.
crates/compositor/src/audio.rs, electron/native/pipewire-capture/src/ffmpeg.rs [0i8; 256] passed to av_strerror's *mut c_char. c_char is signed on x86_64 but unsigned on aarch64, so this is a hard type error there. Uses c_char.

No behaviour change on x86_64: the ffmpeg pin is additive, both path constants resolve to their previous values, and c_char is i8 there.

Related issue

No existing issue — found while building for an aarch64 machine.

Type of change

  • Bug fix
  • Feature
  • Enhancement
  • Documentation
  • Refactor / maintenance
  • Performance
  • Security

Release impact

  • Patch
  • Minor
  • Major / breaking change
  • No release note needed

Desktop impact

  • Windows
  • macOS
  • Linux
  • Installer / packaging

Screenshots / video

No visual change. The packaged arm64 build boots and renders its recorder toolbar correctly under Xvfb.

Testing

Ubuntu 24.04, aarch64 (NVIDIA GB10), Rust 1.95, Node 22.22.

Build & packagenpm run build:linux

  • Openscreen-Linux-1.9.0.debArchitecture: arm64; apt-get -s install resolves every dependency with no extras.
  • Installs and launches with the Chromium sandbox enabled (no --no-sandbox), and renders under xvfb-run.

Unitnpm test1677 passed, 1 skipped, 0 failed (140 files).

E2Enpm run test:e2e under xvfb-run7 passed, 4 skipped, 0 failed. The 4 skips are windows-native-checklist.spec.ts (test.skip(process.platform !== "win32")).

Both export paths pass end-to-end on arm64:

  • exports an MP4 from a loaded video — software libopenh264
  • exports a GIF from a loaded video — compositor selected the hardware backend: [d3d] adaptateur Vulkan : NVIDIA GB10 (IntegratedGpu, Vulkan) -> backend Hardware

That last line is the useful one: the natively-built compositor addon negotiates a hardware Vulkan backend on arm64, not just a CPU fallback.

Staticnpx tsc clean; biome check clean on the three changed scripts. cargo test in pipewire-capture: 54 passed, 1 failed — see below.

Not verified on x86_64 (no host available), though the reasoning for why each change is a no-op there is above.

Note for anyone reproducing the e2e run on Linux

npm run dev aborts before serving because node_modules/electron/dist/chrome-sandbox isn't root:root 4755, which takes the Vite server down with it and fails every spec on ERR_CONNECTION_REFUSED. NO_ELECTRON=1 npm run dev avoids it. Pre-existing and unrelated to arm64 — mentioning it only so the run is reproducible.

One caveat, not fixed here

BtbN's linuxarm64 ffmpeg ships no h264_vaapi, so every_ladder_entry_names_a_codec_this_build_has fails on arm64. The encoder ladder probes and falls through at runtime, and h264_nvenc, h264_v4l2m2m and libopenh264 are all present — so this looks like a gap in the test's assumption rather than a broken export path. Left alone to keep this PR to the build fix; happy to follow up if you'd like the assertion made arch-aware.

🤖 Generated with Claude Code

https://claude.ai/code/session_014iYUHw6DyT4CSBNyvr4zsY

Summary by CodeRabbit

  • Bug Fixes

    • Improved audio error handling compatibility across supported CPU architectures.
    • Fixed architecture-specific Linux build configuration for ARM64 and x86_64 systems.
  • New Features

    • Added support for provisioning shared FFmpeg on Linux ARM64.
    • Improved automatic compiler include-path detection for Linux builds.

@coderabbitai

coderabbitai Bot commented Aug 6, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@EtienneLescot, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 44 minutes

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: da9718c4-5a0c-4893-ab72-e4d391ff71a9

📥 Commits

Reviewing files that changed from the base of the PR and between f006525 and 4e7961c.

📒 Files selected for processing (8)
  • crates/compositor/src/audio.rs
  • electron/native/pipewire-capture/build.rs
  • electron/native/pipewire-capture/src/ffmpeg.rs
  • scripts/build-linux-compositor-addon.mjs
  • scripts/build-linux-pipewire-helper.mjs
  • scripts/fetch-ffmpeg.mjs
  • scripts/fetch-ffmpeg.test.mjs
  • vitest.config.ts
📝 Walkthrough

Walkthrough

The PR adds Linux ARM64 support for FFmpeg provisioning and bindgen paths. It also replaces hardcoded i8 FFmpeg error buffers with platform-specific c_char buffers.

Changes

Linux ARM64 support

Layer / File(s) Summary
Platform-compatible FFmpeg error buffers
crates/compositor/src/audio.rs, electron/native/pipewire-capture/src/ffmpeg.rs
FFmpeg error buffers now use c_char instead of hardcoded i8.
Architecture-aware Linux bindgen setup
scripts/build-linux-compositor-addon.mjs, scripts/build-linux-pipewire-helper.mjs
Build scripts detect the host multiarch triplet and use architecture-specific libclang and GCC include paths. Existing BINDGEN_EXTRA_CLANG_ARGS values remain supported.
Pinned ARM64 FFmpeg provisioning
scripts/fetch-ffmpeg.mjs
Shared FFmpeg provisioning now includes a pinned Linux ARM64 archive and SHA-256 digest.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Possibly related PRs

Suggested reviewers: etiennelescot

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely describes the Linux ARM64 build fix.
Description check ✅ Passed The description includes the required sections and provides detailed scope, impact, testing results, and a documented known caveat.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
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.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@zebster-cmd
zebster-cmd marked this pull request as ready for review August 6, 2026 14:25
zebster-cmd and others added 2 commits August 8, 2026 23:31
`npm run build:linux` could not complete on an aarch64 host. Four
independent x86-only assumptions, each fixed here:

- fetch-ffmpeg: SHARED_PINNED had no `linux-arm64` entry, so the SDK
  fetch bailed out. BtbN publishes the asset in the pinned release;
  only the pin was missing. Digest taken from its checksums.sha256.
- build-linux-compositor-addon: `/usr/lib/x86_64-linux-gnu` and
  `/usr/lib/gcc/x86_64-linux-gnu` were hardcoded, hiding both libclang
  and gcc's stddef.h on arm64. Derived from `process.arch` instead.
- build-linux-pipewire-helper: bindgen failed with "'limits.h' file not
  found" because Ubuntu ships libclang.so.1 without a resource dir. Now
  passes BINDGEN_EXTRA_CLANG_ARGS at gcc's includes, the same fallback
  build-linux-compositor-addon already applied.
- audio.rs / ffmpeg.rs: `[0i8; 256]` passed to av_strerror's
  `*mut c_char`. `c_char` is signed on x86_64 but unsigned on aarch64,
  so this is a hard type error there. Use `c_char`.

No behaviour change on x86_64: the ffmpeg pin is additive, the two path
constants resolve to their previous values, and `c_char` *is* `i8` there.

Verified by building and packaging on aarch64 (Ubuntu 24.04): the deb
reports `Architecture: arm64`, and the app boots and renders under Xvfb.

One caveat worth flagging separately: BtbN's linuxarm64 ffmpeg ships no
h264_vaapi, so `every_ladder_entry_names_a_codec_this_build_has` fails on
arm64. The encoder ladder probes and falls through at runtime, and
h264_nvenc / h264_v4l2m2m / libopenh264 are all present, so this is a
gap in the test's assumption rather than a broken export path. Left
alone here to keep this PR to the build fix.
…ookup at its source

Review follow-ups on the arm64 build fix.

- fetch-ffmpeg: the linux-arm64 shared entry named n8.1.2-32-gcfa62de001,
  a build that is not in the release RELEASE_TAG points at. Nothing
  conflicted — the entry is added just below the lines main had changed —
  so it merged clean and `npm run build:linux` died on a 404 at step one,
  on the only arch that reaches it. Re-pinned to n8.1.2-34-g9b6c8969e0
  with the digest from that release's checksums.sha256, like its siblings.

- fetch-ffmpeg.test.mjs: the guard that was missing. Asserts every pinned
  asset names ONE ffmpeg build, carries a full sha-256, and is an -lgpl
  artifact. It fails on the pin above and names the odd entry out. Reads
  the file as text rather than importing it, which would start a download.
  `scripts` joins vitest's include glob for it.

- pipewire-capture/build.rs: hardcoded /usr/lib/gcc/x86_64-linux-gnu, which
  is the actual arm64 defect. Derived from CARGO_CFG_TARGET_ARCH instead,
  matched on the vendor prefix so Arch's x86_64-pc-linux-gnu also resolves
  while a cross-gcc for the other arch is still refused. Picks the same
  directory as before on x86_64.

- build-linux-pipewire-helper: drops the BINDGEN_EXTRA_CLANG_ARGS wrapper.
  build.rs already owns that fallback and its doc comment says why — doing
  it in the script covers only the npm path and leaves a bare `cargo build`
  broken on arm64, which is the split build.rs exists to prevent.

- build-linux-compositor-addon: bindgenClangArgs() filtered on stddef.h
  while the failure it exists to fix is 'limits.h' file not found, and took
  whatever readdirSync returned first. Now requires both headers and sorts,
  matching build.rs. A dir with stddef.h but no limits.h made it export a
  non-empty BINDGEN_EXTRA_CLANG_ARGS, which suppressed build.rs's own
  fallback and failed with the very error being fixed.

- audio.rs / ffmpeg.rs: std::ffi::c_char rather than the legacy
  std::os::raw alias, matching encoder.rs. audio.rs's comment in French
  like the rest of that file.
@EtienneLescot
EtienneLescot force-pushed the fix/linux-arm64-build branch from f006525 to 4e7961c Compare August 8, 2026 21:33
@EtienneLescot
EtienneLescot merged commit 05cc666 into getopenscreen:main Aug 8, 2026
15 checks passed
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.

2 participants