Build multi-arch image (amd64 + arm64) on an Ubuntu base#2
Merged
Conversation
Adds arm64 alongside amd64. Emulation is not viable for a from-source WebRTC build, so each arch builds natively: amd64 on ubuntu-24.04, arm64 on the ubuntu-24.04-arm hosted runner. A manifest job stitches the per-arch tags into a multi-arch :latest for both the image and the tools image. Switches the container base from Arch to Ubuntu. Official Arch is x86_64-only and the community Arch-Linux-ARM images are stale (keyring rot on pacman -Syu), whereas Ubuntu's official image is glibc + multi-arch and continuously rebuilt. glibc keeps the WebRTC/tgcalls compile low-risk (Alpine/musl would need source patching). The cmake build steps are unchanged; only the package layer and base differ. libyuv isn't packaged on Ubuntu, so it's built from the existing vendored submodule as a static PIC lib (the project finds it via find_library(yuv) and uses the vendored headers). The runtime stage copies the binary's shared-library closure via ldd instead of hand-listing version-suffixed Debian runtime packages, keeping the image minimal and arch-agnostic. The Makefile gains BASE_IMAGE and TAG knobs so CI builds/pushes per-arch tags through `make image`/`make push`; local `make image` is unchanged (defaults to ubuntu:24.04, :latest). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The aarch64 leg failed with `unrecognized command-line option '-mavx'`: the vendored Build*.cmake files select arch-specific sources, SIMD flags, and defines off ANDROID_ABI, but CMakeLists.txt hardcoded it to "x86_64". The WebRTC/openh264 cmake already have full arm64-v8a branches (NEON sources, WEBRTC_ARCH_ARM64, HAVE_NEON_AARCH64), so mapping ANDROID_ABI to the real target arch clears the -mavx/-mavx2/-mfma injection automatically. Remaining un-gated x86 assumptions in CMakeLists.txt, now per-arch: - crc32c: the stub crc32c_config.h sets HAVE_SSE42 on x86_64 and HAVE_ARM64_CRC32C on aarch64, so compile the matching hardware impl (crc32c_sse42.cc with -msse4.2 / crc32c_arm64.cc with -march=armv8-a+crc+crypto) or the dispatcher hits an undefined reference. - HAVE_SSE2 → WEBRTC_ARCH_ARM64 + WEBRTC_HAS_NEON on arm64. Also bumps actions/checkout v4 → v5 to clear the Node 20 deprecation warning (v4 runs on the now-deprecated Node 20; v5 uses Node 24). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
WebRTC includes ffmpeg as "third_party/ffmpeg/libav{codec,format,util}/...",
resolved through the vendored vendor/third_party/ffmpeg symlink that targets
/usr/include (Arch's flat header layout). Debian/Ubuntu keep these headers
under a multiarch triplet dir and split libavformat into its own -dev package,
so the amd64 build failed with:
fatal error: third_party/ffmpeg/libavcodec/avcodec.h: No such file or directory
Add libavformat-dev (libavcodec/libavutil were already present) and repoint the
ffmpeg symlink to /usr/include/<triplet> inside the build. avformat is only
included for types, not linked, so the runtime closure is unaffected.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
On aarch64 the stub crc32c_config.h enables HAVE_ARM64_CRC32C, which makes crc32c_arm64_check.h compile `#if defined(__linux__) && (HAVE_STRONG_GETAUXVAL || HAVE_WEAK_GETAUXVAL)`. HAVE_WEAK_GETAUXVAL was defined empty, so the arm64 build failed with "operator '||' has no right operand". Give it a value (0; glibc provides the strong getauxval). x86 was unaffected since the whole block is HAVE_ARM64_CRC32C-gated. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The arm64 link failed with undefined references to openh264's aarch64 NEON routines (WelsDctT4_AArch64_neon, SampleVariance16x16_AArch64_neon, ...). HAVE_NEON_AARCH64 makes the C++ call them, and BuildOpenH264.cmake adds the matching .S sources, but project() only enabled C/CXX, so CMake silently skipped every .S file and their symbols never entered the archive. Add ASM to the project languages. x86 is unaffected (openh264 has no x86 assembly branch; WebRTC's arm64 NEON paths are .c/.cc, already compiled). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
openh264 does ship x86 SIMD, but as NASM/YASM .asm files this build doesn't wire up; x86_64 uses the C++ fallbacks. The old comment claimed there were no x86 assembly sources at all. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
With ASM enabled, openh264's aarch64 .S files failed to assemble: bits/stdint-least.h: Error: unknown mnemonic `typedef' target_compile_options applies to every language, so the GCC-compat "-include stdint.h/stddef.h" force-includes were prepended to the assembler input, feeding C typedefs to the assembler. Gate them to C/CXX via a COMPILE_LANGUAGE generator expression so the .S sources assemble clean. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The arm64 runtime stage failed at `RUN ldconfig` with "exec /bin/sh: No such
file or directory (missing dynamic library?)". The shared-lib closure was
copied path-preserving (install -D {} /rootfs{} then COPY /rootfs/ /). On arm64
ldd reports some libs under /lib/aarch64-linux-gnu, so this recreated a real
/lib and copied it over the base image's /lib -> /usr/lib usrmerge symlink,
breaking the dynamic linker. amd64 only escaped because its libs all resolved
under /usr/lib.
Copy the closure flat (cp -L) and drop it into /usr/local/lib in the runtime
stage, then ldconfig. /usr/local/lib is already on the default loader path, so
no system lib dirs (or the /lib symlink) are touched. Works the same on both
arches.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Adds arm64 alongside amd64 and moves the container base from Arch to Ubuntu.
Why Ubuntu
menci/archlinuxarmlast built 2024-12,agners/archlinuxarm2021) and would hit pacman keyring rot.execinfo/backtrace, glibc guards).CI shape
ubuntu-24.04, arm64 on the free publicubuntu-24.04-armrunner (emulation is not viable for a from-source WebRTC build).--cache-from. master: build +--cache-to+ push per-arch:amd64/:arm64tags, then amanifestjob combines them into:latest(for image and tools image).buildcache-amd64/-arm64); layers aren't shareable across arches.Containerfile port
pacman→ Ubuntuapt(build deps + the hardcoded/usr/include/opusand/usr/include/lamepaths match Debian).vendor/libyuvsubmodule as a static PIC lib (verified targetyuv→libyuv.a; the project finds it viafind_library(yuv)and uses the vendored headers).lddshared-lib closure (minus glibc core) instead of hand-listing version-suffixed Debian runtime packages — minimal and arch-agnostic.ca-certificatesadded for TLS to Telegram.Makefile
BASE_IMAGE(defaultubuntu:24.04) andTAG(defaultlatest) knobs so CI builds/pushes per-arch tags viamake image/make push; localmake imagebehavior is unchanged.Notes / risk
🤖 Generated with Claude Code