Skip to content

Commit 645f0ff

Browse files
committed
feat: build the full V8 matrix from a single branch
Replaces the branch-per-architecture arrangement with one branch and a CI matrix: four Android ABIs on ubuntu, five Apple variants on macOS. Nine branches meant nine places to apply a V8 bump or a patch, and cutting a release needs a single ref to tag. config.env pins everything -- V8 version, NDK release, deployment targets. The gn args live in scripts/matrix/build-*.sh with a comment on every deviation from the defaults; several are load-bearing, notably v8_array_buffer_internal_field_count, which defaulted to 2 in 10.3 and defaults to 0 in 14.9 and silently breaks ArrayBuffer marshalling on android. The matrix runs on push and on PRs touching the build inputs, so it is verified before anything is tagged. A v8-* tag additionally collects the artifacts, writes SHA256SUMS and creates the release; consumers pin a tag and verify rather than trusting the URL. visionOS is deliberately not covered -- V8 has no visionOS support in its build system, and the iOS runtime's arch array lists arm64-xrsimulator but never produces one. See scripts/matrix/README.md.
1 parent 0368bca commit 645f0ff

9 files changed

Lines changed: 1089 additions & 0 deletions

File tree

.github/workflows/build-matrix.yml

Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
name: Build V8 matrix
2+
3+
# Runs on demand and on every push to the branch so the matrix is verified
4+
# before anything is tagged. Pushing a tag additionally cuts a release.
5+
on:
6+
workflow_dispatch:
7+
push:
8+
branches: [feat/full-matrix]
9+
tags: ['v8-*']
10+
pull_request:
11+
paths:
12+
- 'config.env'
13+
- 'patches/**'
14+
- 'scripts/matrix/**'
15+
- '.github/workflows/build-matrix.yml'
16+
17+
permissions:
18+
contents: write
19+
20+
jobs:
21+
config:
22+
runs-on: ubuntu-24.04
23+
outputs:
24+
v8_version: ${{ steps.cfg.outputs.v8_version }}
25+
ndk_release: ${{ steps.cfg.outputs.ndk_release }}
26+
steps:
27+
- uses: actions/checkout@v4
28+
- id: cfg
29+
run: |
30+
set -a; . ./config.env; set +a
31+
echo "v8_version=$V8_VERSION" >> "$GITHUB_OUTPUT"
32+
echo "ndk_release=$ANDROID_NDK_RELEASE" >> "$GITHUB_OUTPUT"
33+
34+
android:
35+
needs: config
36+
runs-on: ubuntu-24.04
37+
timeout-minutes: 300
38+
strategy:
39+
fail-fast: false
40+
matrix:
41+
abi: [arm64-v8a, x86_64, armeabi-v7a, x86]
42+
steps:
43+
- uses: actions/checkout@v4
44+
45+
# A 32-bit target builds mksnapshot and the bytecode-builtins generator
46+
# as 32-bit x86 host binaries. Without the i386 runtime they link and
47+
# then fail to execute, which surfaces only as a failed
48+
# generate_bytecode_builtins_list action.
49+
- name: Enable i386 multiarch
50+
run: |
51+
sudo dpkg --add-architecture i386
52+
sudo apt-get update -qq
53+
sudo apt-get install -y -qq --no-install-recommends \
54+
libc6:i386 libstdc++6:i386 libatomic1:i386 zlib1g:i386 rsync
55+
56+
- name: Install the Android NDK ${{ needs.config.outputs.ndk_release }}
57+
run: |
58+
curl -fsSL -o /tmp/ndk.zip \
59+
"https://dl.google.com/android/repository/android-ndk-${{ needs.config.outputs.ndk_release }}-linux.zip"
60+
unzip -q /tmp/ndk.zip -d "$HOME"
61+
echo "ANDROID_NDK_ROOT=$HOME/android-ndk-${{ needs.config.outputs.ndk_release }}" >> "$GITHUB_ENV"
62+
63+
- name: Install depot_tools
64+
run: |
65+
git clone -q --depth 1 https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools"
66+
echo "$HOME/depot_tools" >> "$GITHUB_PATH"
67+
68+
- name: Fetch and patch V8
69+
run: scripts/matrix/fetch.sh --platform android
70+
71+
- name: Build ${{ matrix.abi }}
72+
run: scripts/matrix/build-android.sh --abi ${{ matrix.abi }}
73+
74+
- name: Package
75+
run: |
76+
tar -czf "v8-${{ needs.config.outputs.v8_version }}-android-${{ matrix.abi }}.tar.gz" \
77+
-C dist "android-${{ matrix.abi }}"
78+
79+
- uses: actions/upload-artifact@v4
80+
with:
81+
name: v8-android-${{ matrix.abi }}
82+
path: v8-*-android-${{ matrix.abi }}.tar.gz
83+
retention-days: 7
84+
85+
ios:
86+
needs: config
87+
runs-on: macos-15
88+
timeout-minutes: 300
89+
strategy:
90+
fail-fast: false
91+
matrix:
92+
variant: [arm64-device, arm64-simulator, x64-simulator, arm64-catalyst, x64-catalyst]
93+
steps:
94+
- uses: actions/checkout@v4
95+
96+
- name: Install depot_tools
97+
run: |
98+
git clone -q --depth 1 https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools"
99+
echo "$HOME/depot_tools" >> "$GITHUB_PATH"
100+
101+
- name: Fetch and patch V8
102+
run: scripts/matrix/fetch.sh --platform ios
103+
104+
- name: Build ${{ matrix.variant }}
105+
run: scripts/matrix/build-ios.sh --variant ${{ matrix.variant }}
106+
107+
- name: Package
108+
run: |
109+
tar -czf "v8-${{ needs.config.outputs.v8_version }}-ios-${{ matrix.variant }}.tar.gz" \
110+
-C dist "ios-${{ matrix.variant }}"
111+
112+
- uses: actions/upload-artifact@v4
113+
with:
114+
name: v8-ios-${{ matrix.variant }}
115+
path: v8-*-ios-${{ matrix.variant }}.tar.gz
116+
retention-days: 7
117+
118+
release:
119+
needs: [config, android, ios]
120+
if: startsWith(github.ref, 'refs/tags/v8-')
121+
runs-on: ubuntu-24.04
122+
steps:
123+
- uses: actions/checkout@v4
124+
125+
- uses: actions/download-artifact@v4
126+
with:
127+
path: artifacts
128+
merge-multiple: true
129+
130+
# The checksums are the point of shipping this way: consumers pin a tag
131+
# and verify the archive rather than trusting whatever the URL returns.
132+
- name: Generate checksums
133+
working-directory: artifacts
134+
run: |
135+
sha256sum *.tar.gz | tee SHA256SUMS
136+
ls -la
137+
138+
- name: Create the release
139+
env:
140+
GH_TOKEN: ${{ github.token }}
141+
run: |
142+
{
143+
echo "V8 \`${{ needs.config.outputs.v8_version }}\` built from \`${GITHUB_SHA}\`."
144+
echo
145+
echo "Built against Android NDK \`${{ needs.config.outputs.ndk_release }}\`; it must match the"
146+
echo "NDK the Android runtime is built with, because libc++ is only ABI-compatible"
147+
echo "with itself across a static link."
148+
echo
149+
echo "Patches applied: \`v8_resurrecting_finalizers.patch\` (restores"
150+
echo "\`WeakCallbackType::kFinalizer\`), \`android_build.patch\` (API 21 floor,"
151+
echo "selectable \`android_ndk_root\`, macOS host support)."
152+
echo
153+
echo "Verify with \`sha256sum -c SHA256SUMS\`. The gn args are in \`scripts/matrix/build-*.sh\`."
154+
} > notes.md
155+
gh release create "${GITHUB_REF_NAME}" \
156+
--title "${GITHUB_REF_NAME}" \
157+
--notes-file notes.md \
158+
artifacts/*.tar.gz artifacts/SHA256SUMS

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package-lock.json
22
/build
33
dist/
4+
.v8/
45

56
scripts/depot_tools
67
v8

config.env

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# Single source of truth for everything the matrix is pinned to.
2+
# Sourced by scripts/v8/*.sh and read by .github/workflows/build.yml.
3+
4+
V8_VERSION=14.9.207.39
5+
6+
# The NDK the Android runtime is built with. It must match: libc++ is only
7+
# ABI-compatible with itself across a static link, and V8's own bundled NDK is
8+
# newer than any released one. Keep in step with android's
9+
# test-app/runtime/build.gradle defaultNdkVersion.
10+
ANDROID_NDK_RELEASE=r29
11+
12+
IOS_DEPLOYMENT_TARGET=13.0
13+
# arm64 macabi does not exist below 14.0.
14+
CATALYST_DEPLOYMENT_TARGET=14.0

patches/android_build.patch

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
Build V8 for Android at API 21, against a chosen NDK, from either a Linux or a
2+
macOS host.
3+
4+
Applies to //build (the chromium build tree pulled in by DEPS), not to V8
5+
itself. Only the first change is host-specific; the other two are needed
6+
everywhere, so this patch is applied on every host.
7+
8+
1. build/config/BUILDCONFIG.gn -- Chromium hard-asserts a Linux host for
9+
Android targets. Everything below that assert still handles macOS: the
10+
host-arch block maps arm64 hosts to the "darwin-x86_64" NDK tag on purpose,
11+
and android_toolchain_root is only consumed for the (host-independent)
12+
sysroot. Widening the assert is a no-op on Linux. See fetch_v8.sh for the
13+
darwin-x86_64 NDK symlink and the Android compiler-rt builtins that the
14+
macOS clang package omits.
15+
16+
2. build/config/android/config.gni -- the minimum supported SDK is 21 rather
17+
than 23. The 23 floor exists for Java/dex tooling ("no longer supports
18+
legacy multidex"); this build produces only the native v8_monolith target
19+
and the runtime still ships minSdk 21.
20+
21+
3. build/config/android/config.gni -- android_ndk_root becomes a gn arg. The
22+
runtime links libv8_monolith.a into a library it builds with its own NDK,
23+
and libc++ is only ABI-compatible with itself, so both sides have to use the
24+
same NDK. Left at its default the build uses V8's bundled CIPD NDK, which is
25+
newer than any released one.
26+
27+
diff --git a/config/BUILDCONFIG.gn b/config/BUILDCONFIG.gn
28+
index 00d3892f3..94c9fc906 100644
29+
--- a/config/BUILDCONFIG.gn
30+
+++ b/config/BUILDCONFIG.gn
31+
@@ -250,7 +250,8 @@ _default_toolchain = ""
32+
33+
if (target_os == "android") {
34+
# Targeting android on Mac is best-effort and not guaranteed to work.
35+
- assert(host_os == "linux", "Android builds are only supported on Linux.")
36+
+ assert(host_os == "linux" || host_os == "mac",
37+
+ "Android builds are only supported on Linux and macOS.")
38+
_default_toolchain = "//build/toolchain/android:android_clang_$target_cpu"
39+
} else if (target_os == "chromeos" || target_os == "linux") {
40+
# See comments in build/toolchain/cros/BUILD.gn about board compiles.
41+
diff --git a/config/android/config.gni b/config/android/config.gni
42+
index 1e07ac0e7..6927ba1ef 100644
43+
--- a/config/android/config.gni
44+
+++ b/config/android/config.gni
45+
@@ -131,7 +131,9 @@ if (is_android) {
46+
}
47+
48+
# Our build system no longer supports legacy multidex.
49+
- min_supported_sdk_version = 23
50+
+ # Lowered from 23: that floor is about Java/dex tooling, and this build
51+
+ # produces only the native v8_monolith target.
52+
+ min_supported_sdk_version = 21
53+
54+
# ASAN requires O MR1.
55+
# https://github.com/google/sanitizers/wiki/AddressSanitizerOnAndroid/01f8df1ac1a447a8475cdfcb03e8b13140042dbd#running-with-wrapsh-recommended
56+
@@ -157,7 +159,12 @@ if (is_android) {
57+
}
58+
}
59+
60+
- android_ndk_root = "//third_party/android_toolchain/ndk"
61+
+ declare_args() {
62+
+ # Overridable so the build can use the same NDK as the embedder that links
63+
+ # the result -- libc++ is only ABI-compatible with itself across a static
64+
+ # link, and the CIPD NDK is newer than any released one.
65+
+ android_ndk_root = "//third_party/android_toolchain/ndk"
66+
+ }
67+
68+
public_android_sdk_root = "//third_party/android_sdk/public"
69+
public_android_sdk_platform_version = "37.0"

0 commit comments

Comments
 (0)