Skip to content

Commit 438a577

Browse files
authored
feat(tvos): build Apple TV V8 release variants (#8)
1 parent 9dfc18b commit 438a577

4 files changed

Lines changed: 68 additions & 2 deletions

File tree

.github/workflows/build-matrix.yml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ on:
1818
- 'config.env'
1919
- 'patches/**'
2020
- 'scripts/matrix/**'
21+
- 'tests/apple-args.py'
2122
- '.github/workflows/build-matrix.yml'
2223

2324
permissions:
@@ -199,7 +200,7 @@ jobs:
199200
strategy:
200201
fail-fast: false
201202
matrix:
202-
variant: [arm64-device, arm64-simulator, x64-simulator, arm64-catalyst, x64-catalyst]
203+
variant: [arm64-device, arm64-simulator, x64-simulator, arm64-catalyst, x64-catalyst, arm64-tvdevice, arm64-tvsimulator]
203204
# See the android job for the R2 bucket layout and the missing-secrets
204205
# fallback; this job mirrors it.
205206
env:
@@ -217,6 +218,9 @@ jobs:
217218
steps:
218219
- uses: actions/checkout@v7
219220

221+
- name: Check Apple build arguments
222+
run: python3 tests/apple-args.py
223+
220224
- name: Check R2 for a prebuilt artifact
221225
id: cache
222226
if: env.AWS_ACCESS_KEY_ID != ''

README.md

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ from a pinned revision, with the gn args under review, is the point of this repo
4040
| Platform | Targets | Runner |
4141
|---|---|---|
4242
| Android | `arm64-v8a`, `x86_64`, `armeabi-v7a`, `x86` | `ubuntu-24.04` |
43-
| Apple | `arm64-device`, `arm64-simulator`, `x64-simulator`, `arm64-catalyst`, `x64-catalyst` | `macos-15` |
43+
| Apple | `arm64-device`, `arm64-simulator`, `x64-simulator`, `arm64-catalyst`, `x64-catalyst`, `arm64-tvdevice`, `arm64-tvsimulator` | `macos-15` |
4444

4545
Each target is its own job with its own checkout. That costs one `gclient sync`
4646
per job, but the sync is about 6 minutes against 90–145 minutes of compile, so
@@ -173,3 +173,16 @@ most of the reason this repo exists.
173173
Forked from [Kudo/v8-android-buildscripts](https://github.com/Kudo/v8-android-buildscripts)
174174
by Kudo Chien, which the original Android build pipeline came from. See
175175
[LICENSE](LICENSE).
176+
177+
### tvOS source builds
178+
179+
Use `scripts/matrix/build-ios.sh --variant arm64-tvdevice` and
180+
`--variant arm64-tvsimulator` after the normal iOS source fetch. These use
181+
the Apple TV SDK and tvOS target triples, with the same deployment minimum
182+
as iOS. They remain release, jitless builds without WebAssembly. Chromium
183+
requires `use_blink=true` for its tvOS toolchain; DrumBrake is explicitly
184+
disabled so that this does not enable an incomplete Wasm configuration.
185+
The existing iOS and Catalyst arguments are unchanged.
186+
187+
Run `python3 tests/apple-args.py` on macOS to check the emitted GN arguments
188+
for all seven Apple variants without compiling V8.

scripts/matrix/build-ios.sh

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ Usage: $(basename "$0") --variant <variant> [--v8-dir <path>]
2929
3030
--variant arm64-device | arm64-simulator | x64-simulator
3131
| arm64-catalyst | x64-catalyst
32+
| arm64-tvdevice | arm64-tvsimulator
3233
--cc-wrapper <bin> Compiler launcher (e.g. sccache), passed to gn as
3334
cc_wrapper. Must be on PATH.
3435
EOF
@@ -54,6 +55,8 @@ case "$VARIANT" in
5455
x64-simulator) CPU=x64; TARGET_ENV=simulator ;;
5556
arm64-catalyst) CPU=arm64; TARGET_ENV=catalyst ;;
5657
x64-catalyst) CPU=x64; TARGET_ENV=catalyst ;;
58+
arm64-tvdevice) CPU=arm64; TARGET_ENV=device ;;
59+
arm64-tvsimulator) CPU=arm64; TARGET_ENV=simulator ;;
5760
*) echo "Invalid --variant '$VARIANT'" >&2; usage >&2; exit 1 ;;
5861
esac
5962

@@ -132,6 +135,13 @@ else
132135
ios_deployment_target=\"$IOS_DEPLOYMENT_TARGET\""
133136
fi
134137

138+
# Chromium requires Blink configuration for tvOS even for standalone V8.
139+
# Disable DrumBrake explicitly: tvOS otherwise enables it independently of
140+
# v8_enable_webassembly, producing references to omitted Wasm types.
141+
if [[ "$VARIANT" = arm64-tv* ]]; then
142+
GN_ARGS="$GN_ARGS target_platform=\"tvos\" use_blink=true v8_enable_drumbrake=false"
143+
fi
144+
135145
if [ -n "$CC_WRAPPER" ]; then
136146
GN_ARGS="$GN_ARGS cc_wrapper=\"$CC_WRAPPER\""
137147
fi

tests/apple-args.py

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
#!/usr/bin/env python3
2+
"""Exercise the build entry point, stopping at GN before compiling V8."""
3+
import os
4+
from pathlib import Path
5+
import subprocess
6+
import tempfile
7+
import unittest
8+
9+
ROOT = Path(__file__).resolve().parents[1]
10+
11+
class AppleArgs(unittest.TestCase):
12+
def args_for(self, variant):
13+
with tempfile.TemporaryDirectory() as tmp:
14+
directory = Path(tmp)
15+
gn = directory / 'gn'
16+
gn.write_text('#!/bin/sh\nprintf "%s\\n" "$@" > "$ARGS_CAPTURE"\nexit 77\n')
17+
gn.chmod(0o755)
18+
env = dict(os.environ, PATH=tmp + ':' + os.environ['PATH'], ARGS_CAPTURE=str(directory / 'args'))
19+
result = subprocess.run([str(ROOT / 'scripts/matrix/build-ios.sh'), '--variant', variant, '--v8-dir', tmp], env=env, capture_output=True, text=True)
20+
self.assertEqual(result.returncode, 77, result.stderr)
21+
return (directory / 'args').read_text()
22+
23+
def test_tvos_is_release_jitless_and_without_wasm(self):
24+
for variant, environment in [('arm64-tvdevice', 'device'), ('arm64-tvsimulator', 'simulator')]:
25+
args = self.args_for(variant)
26+
for flag in ['target_platform="tvos"', 'use_blink=true', 'v8_enable_drumbrake=false', 'v8_enable_webassembly=false', 'is_debug=false', 'v8_enable_lite_mode=true', f'target_environment="{environment}"']:
27+
self.assertIn(flag, args)
28+
29+
def test_ios_and_catalyst_do_not_receive_tvos_overrides(self):
30+
for variant in ['arm64-device', 'arm64-simulator', 'x64-simulator', 'arm64-catalyst', 'x64-catalyst']:
31+
args = self.args_for(variant)
32+
self.assertNotIn('target_platform=', args)
33+
self.assertNotIn('use_blink=', args)
34+
self.assertNotIn('v8_enable_drumbrake=', args)
35+
self.assertIn('is_debug=false', args)
36+
self.assertEqual('v8_enable_lite_mode=true' in args, 'catalyst' not in variant)
37+
38+
if __name__ == '__main__':
39+
unittest.main()

0 commit comments

Comments
 (0)