# chromium-fourier — first-build status (2026-04-26 00:42 UTC) ## Where we are Build environment: **chromium-builder LXD container on boltzmann** (8 cores, 28 GB RAM cap, 824 GB NVMe, Beryllium OS rkr3 host kernel). Source: chromium-147.0.7727.116 release tarball extracted at `/build/chromium/src` (25 GB extracted). `gn gen out/Default` **succeeds** with our 7Ji-style args (`use_v4l2_codec=true use_v4lplugin=true use_linux_v4l2_only=true use_vaapi=false`, system toolchain via `unbundle:default`, system clang at `/usr/bin/clang`, version-symlink `/usr/lib/clang/23` → `/usr/lib/clang/22`, compiler-rt-adjust-paths style suffix patch manually applied). 28057 targets generated. `ninja -C out/Default chrome` **fails immediately** with two distinct walls: ### Wall 1 — clang version mismatch (chromium 147 ↔ Arch clang 22) Chromium 147's compile flags include `-fno-lifetime-dse` and `-fsanitize-ignore-for-ubsan-feature=array-bounds`. Both are clang 23+ features. Arch Linux ARM ships **clang 22.1.3** (extra repo). Every single C++ compile fails with `clang++: error: unknown argument`. Resolutions, in order of effort: - **(a)** Wait for Arch ARM to bump clang to 23. Tracking package upstream — happens whenever LLVM 23 lands in extra. Days to weeks. - **(b)** Use chromium's bundled clang via `tools/clang/scripts/update.py`. That hits the same CIPD/gs:// "linux-arm64 isn't a first-class target" issue we saw with `gclient sync` earlier — chromium's clang prebuilts are x86_64-only for many platforms. - **(c)** Fork an older chromium (e.g., 132 or 138) that compiles cleanly with clang 22. 7Ji's chromium-mpp PKGBUILD targets 132 and builds clean on Arch ARM today. Loses 15 versions of upstream chromium evolution but ships fast. - **(d)** Patch chromium 147 to drop the offending flags (`build/config/compiler/BUILD.gn` has the cflags lists). 50–200 line patch, brittle across version bumps but tractable. Fights every rebase. ### Wall 2 — bundled x86_64 esbuild under qemu After Wall 1 (or independently for Action targets): `qemu-x86_64-static: Could not open '/lib64/ld-linux-x86-64.so.2'` when chromium runs the bundled x86_64 `esbuild` from `third_party/devtools-frontend/.../scripts/build/typescript/ts_library.py`. Same shape as the bundled `node-linux-x64` issue we already fixed (we symlinked system node into that path). `esbuild` needs the same treatment — install system esbuild via `npm install -g esbuild` and symlink it into the path chromium expects. Or install `qemu-user-static` + `glibc-x86_64` to make the bundled binary actually run. **Wall 2 is much smaller than Wall 1** — a handful of bundled-x86_64 binaries to identify and replace, vs. fundamental clang version mismatch. ## What worked - LXD container provisioning on boltzmann via his recommendation — the host environment is right. - Tarball-instead-of-gclient approach — sidesteps CIPD-doesn't-have- linux-arm64 problem for source acquisition, leaves only a few bundled binary issues at build time. - Wall 1 / Wall 2 are both **identifiable and bounded**. We're past the "is this even doable" phase; this is now down to grinding the patches. ## Options — needs your call 1. **Grind through Wall 1 with patches** — patch `build/config/compiler/BUILD.gn` to drop flags clang 22 doesn't know. Iterate per build error. Estimated 5–15 patch-and-retry cycles to compile clean. Then 6–10 h actual build. 2. **Pin to chromium 132** — match 7Ji's known-working version on Arch ARM. Drop our STUDY focus on "current upstream Chromium" and ship a 1-year-old binary. Build should work much sooner. 3. **Pin to chromium 138 or 140** — middle ground. Likely uses clang 22 features and not 23. Some research needed to find the cutover. 4. **Use chromium's bundled clang** — not viable on linux-arm64 without extensive sysroot setup; same CIPD issue as gclient sync. 5. **Wait for Arch ARM clang 23** — passive, days-to-weeks horizon. Recommended (FWIW): **start with (3)** — find the latest chromium version that builds clean against clang 22 (probably 138-141 range), ship that as `chromium-fourier`, then bump as Arch ARM bumps clang. That gives us a working browser in a few hours rather than days, on mainline Linux + Wayland + V4L2 unlock — which is the actual goal. The "current upstream Chromium" requirement was nice-to-have, not essential. ## State of the build host (preserved) - Container: `chromium-builder` on boltzmann (running, idle) - Source: `/build/chromium/src` (extracted tarball, 25 GB) - Build dir: `/build/chromium/src/out/Default` (gn-gen'd, no artifacts) - Tools installed: gn, ninja, clang 22, lld, gperf, nodejs (system), rust, qt5/6, all the gtk/wayland/va/v4l deps from the long pacman shopping list - Patches applied to source: `compiler-rt-adjust-paths` style (manual) - Symlinks: `/usr/lib/clang/23` → `/usr/lib/clang/22`, `third_party/node/linux/node-linux-x64/bin/node` → `/usr/bin/node` - Service unit history: `chromium-fetch.service` (one-shot, succeeded on tarball + extract); `chromium-build.service` (one-shot, three failed attempts above). Discard the container and start over with option 2 if you pick that direction; otherwise iterate from current state. ## Pivot 2026-04-26 — cross-compile from x86_64 After the analysis above, the framing shifted. The real wall isn't "Arch ARM clang 22 vs LLVM 23" — Arch x86_64 is also on llvm 22.1.3, no LLVM 23 anywhere in extra/staging. The flags chromium 147 emits (`-fno-lifetime-dse`, `-fsanitize-ignore-for-ubsan-feature=array-bounds`, the `/usr/lib/clang/23/...` path) come from **chromium's clang fork**, not upstream LLVM 23. Chromium ships its own LLVM with chromium-specific passes; the "23" in the path is chromium-internal versioning. Implication: PKGBUILD'ing clang 23 is the wrong tree. The right tree is either pin to an older chromium (option 2 above) or **cross-compile from an x86_64 host** so chromium's x86_64 bundled clang prebuilt is reachable and `target_cpu="arm64"` produces the aarch64 binary cleanly. Cross-compile sidesteps every wall we hit: - CIPD has full `linux-amd64` prebuilts (the gap was `linux-arm64`) - Chromium's bundled clang downloads cleanly on x86_64 - No qemu-x86_64-static dance for tools (host IS x86_64) - `tools/clang/scripts/update.py` works as Google intends - `gclient sync` works; no DEPS surgery needed his provisioned a cross-build host for this on 2026-04-26: - **CT 220 `chromium-builder-x86` on data**, x86_64 Ryzen 7 1700, 14 cores, 32 GiB RAM + 8 GiB swap, 200 GiB ZFS rootfs. - Reach via `mcp__hub-tools__remote_shell host=hertz` → `ssh root@192.168.88.30` (data) → `pct exec 220 -- ...` - `builder` user uid 1001, NOPASSWD sudo, `DisableSandbox` in pacman.conf. Source fetch started 2026-04-26 05:45 UTC as transient unit `chromium-fetch.service` on CT 220. Estimated 1-2 h for `fetch --no-history chromium` over the LAN. Then `tools/clang/scripts/update.py` to install chromium's bundled clang (x86_64 host, arm64 sysroot), then `gn gen` with `target_cpu="arm64"` + cross-compile flags, then build. The boltzmann `chromium-builder` LXD container is preserved as fallback but no longer the active build host. If cross-compile pans out, that container can be torn down. ## First runtime validation on ohm — 2026-04-26 22:26 UTC Cross-compile produced a working aarch64 binary (chrome 647 MB ELF + chrome_crashpad_handler 4.3 MB + .pak + locales). Tarball `chromium-fourier-147.tar.gz` (226 MB) transferred CT 220 → hertz → ohm. Launched in mfritsche's KWin Wayland session (tty2, panfrost render node) playing `bbb_1080p30_h264.mp4` from file:// with `LIBVA_DRIVER_NAME=v4l2_request`, `LIBVA_V4L2_REQUEST_VIDEO_PATH=/dev/video0`, `--use-gl=egl --ozone-platform=wayland --enable-features=VaapiVideoDecodeLinuxGL,AcceleratedVideoDecodeLinuxGL --disable-features=UseChromeOSDirectVideoDecoder --autoplay-policy=no-user-gesture-required`. **Result: V4L2 path NOT engaged.** Chrome 147 routes the H.264 stream through `MojoVideoDecoderService` → `media/filters/ffmpeg_video_decoder.cc` (software FFmpeg). Renderer pegs at ~92 % CPU, `/dev/video0` is never opened (`fuser` returns empty), no `V4L2VideoDecoder` / `VaapiVideoDecoder` log lines appear at `--v=1 --vmodule="*/vaapi/*=2,*/v4l2/*=2,*video_decoder*=2,*media/gpu/*=2"`. Compositor also fell back to software (`Switching to software compositing.` even though panfrost render node was picked) — secondary issue, separate from the codec wall. **Conclusion**: 7Ji-style gn args (`use_v4l2_codec=true use_v4lplugin=true use_linux_v4l2_only=true`) alone are insufficient on chromium 147. The V4L2VideoDecoder factory is still gated behind `BUILDFLAG(IS_CHROMEOS)` — `media/mojo/services/gpu_mojo_media_client_*.cc` and `media/gpu/gpu_video_decode_accelerator_factory.cc` only register the V4L2 path on ChromeOS targets. ## Validation pass 2 — 2026-04-26 22:38 UTC — V4L2VDA proven engaged Two distinct issues were diagnosed and the codec one was fully resolved without source surgery beyond a 2-line patch: ### Issue 1 — runtime master gate `media::kAcceleratedVideoDecodeLinux` (user-visible feature name "AcceleratedVideoDecoder") is hard-coded in `media/base/media_switches.cc:750` to `FEATURE_ENABLED_BY_DEFAULT` only when `BUILDFLAG(USE_VAAPI)` is set. On a USE_V4L2_CODEC-only build it defaults DISABLED, the linux gpu_mojo_media_client returns `VideoDecoderType::kUnknown`, and chrome silently falls back to `media/filters/ffmpeg_video_decoder.cc`. **Fix**: 2-line patch (now `patches/enable-v4l2-decoder-default.patch`): ``` -#if BUILDFLAG(USE_VAAPI) +#if BUILDFLAG(USE_VAAPI) || BUILDFLAG(USE_V4L2_CODEC) ``` The placeholder `chromeos-pipeline-bypass.patch` was deleted; PKGBUILD now references the real patch. **Verified to apply cleanly on the CT 220 tree** (chromium 149 main). ### Issue 2 — bundled GL libs missing from tarball The first runtime tarball shipped only `chrome` + `.pak` + locales + `chrome_crashpad_handler`. It omitted `libEGL.so` / `libGLESv2.so` (ANGLE) plus `libvk_swiftshader.so` and `libvulkan.so.1`. Without these, the GPU process logs `gl::init::InitializeStaticGLBindingsOneOff failed` and chrome falls into "Switching to software compositing." mode — which *also* gates the V4L2 path off because the gpu_mojo_media_client never gets a chance to dispatch. Additionally, `--use-gl=egl` is rejected ("Requested GL implementation gl=egl-gles2,angle=none not found in allowed implementations: [(gl=egl-angle,angle=opengl|opengles|vulkan)]"): the build only allows ANGLE-mediated paths. Right launcher invocation: `--use-gl=angle --use-angle=gles`. **Fix**: package the four libs alongside `chrome` and update the launcher flag set. Both will be encoded in the next iteration of the PKGBUILD's `package()` and a `chromium-fourier` launcher script. ### What we observed once both fixes were in place With patch + bundled libs + `--enable-features=AcceleratedVideoDecoder` + `--use-gl=angle --use-angle=gles`, chrome on RK3566 hantro logs: ``` [gpu]: V4L2VideoDecoder() [gpu]: Open(): No devices supporting H264 for type: 0 <- type=0 is single-planar; chrome retries multi-planar [gpu]: InitializeBackend(): Using a stateless API for profile: h264 main and fourcc: S264 [gpu]: SetupInputFormat(): Input (OUTPUT queue) Fourcc: S264 [gpu]: AllocateInputBuffers(): Requesting: 17 OUTPUT buffers of type V4L2_MEMORY_MMAP [gpu]: SetExtCtrlsInit(): Setting EXT_CTRLS for H264 [gpu]: SetupOutputFormat(): Output (CAPTURE queue) candidate: NV12 [gpu]: ContinueChangeResolution(): Requesting: 6 CAPTURE buffers of type V4L2_MEMORY_MMAP [renderer]: OnDecoderSelected