Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
5a5ad23
first successful build and run in simulator using in-repo test app
matthargett Oct 17, 2025
ea40648
adjust optimization and C++ flags. -Oz produces a 2MB smaller intl bi…
matthargett Oct 18, 2025
4b4310f
Update scripts/start.sh
matthargett Oct 19, 2025
bf0a760
clang bug in NDK 27 makes loop vectorization pass error. disable the …
matthargett Oct 19, 2025
daf4c7e
[ci] cleanup ubuntu runner disk (#188)
Kudo Oct 19, 2025
055fcd8
patches on top of bun, scripts to make things more dynamically discov…
matthargett Nov 2, 2025
b2e4240
lto=thin is clang-only, even in Ubuntu 24.x, and we only really care …
matthargett Nov 3, 2025
79cf238
be more flexible with suboptimal ABI requests, but still favor armv8a…
matthargett Nov 3, 2025
509e65b
filter 32bit platforms out
matthargett Nov 4, 2025
abbf732
upstream update fixes a problem where Promise reactions weren't first…
matthargett Nov 5, 2025
d7dbeb7
build and publish separate artifacts for NDK 27, 28, and 29 so decoup…
matthargett Nov 5, 2025
940c071
cache the NDKs instead of re-downloading and re-unpacking each time. …
matthargett Nov 5, 2025
3951b75
nointl build was broken due to incorrect codepoint comparison that wa…
matthargett Nov 7, 2025
aa5d326
ignore NDK-specific dist directories
matthargett Nov 7, 2025
74de2cf
fix overly specific shell usage
matthargett Nov 11, 2025
dbab32c
don't add clang flags to gcc. I thought for sure this would be fine, …
matthargett Nov 11, 2025
5ba223a
fix corrupt patch
matthargett Nov 12, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 29 additions & 5 deletions .github/actions/cleanup-linux-disk-space/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,37 @@ runs:
run: |
echo 'Disk space before cleanup'
df -aH
sudo apt-get remove -y --purge '^mysql-.*' '^mongodb-.*' '^mssql-.*' '^postgresql-.*' '^aspnetcore-*' '^dotnet-.*' '^php.*-.*' 'mono-complete' '^llvm-.*' 'powershell' 'google-chrome-*' 'microsoft-edge-*' 'firefox' 'nginx' 'apache2'

# Regular package cleanup
sudo apt-get remove -y --purge '^mysql-.*' '^mongodb-.*' '^mssql-.*' '^postgresql-.*' '^aspnetcore-*' '^dotnet-.*' '^php.*-.*' 'mono-complete' '^llvm-.*' 'powershell' 'google-chrome-*' 'microsoft-edge-*' 'firefox' 'nginx' 'apache2' 'ghc' '^ghc-*'
sudo apt-get autoremove -y

# Remove unnecessary large directories
sudo rm -rf /usr/share/dotnet
echo 'Showing Android SDKs'
${ANDROID_SDK_ROOT}/cmdline-tools/latest/bin/sdkmanager --list
${ANDROID_SDK_ROOT}/cmdline-tools/latest/bin/sdkmanager --uninstall 'ndk;24.0.8215888' 'ndk;25.2.9519653' 'ndk;26.2.11394342'
sudo rm -rf /usr/local/.ghcup /opt/ghc

# Android SDK cleanup
echo 'Showing installed Android SDKs'
${ANDROID_SDK_ROOT}/cmdline-tools/latest/bin/sdkmanager --list_installed

echo 'Cleaning unnecessary Android SDK components...'
echo 'Removing old build tools...'
${ANDROID_SDK_ROOT}/cmdline-tools/latest/bin/sdkmanager --uninstall "build-tools;31.0.0" "build-tools;32.0.0" "build-tools;33.0.0" "build-tools;33.0.1" "build-tools;33.0.2" "build-tools;33.0.3" "build-tools;34.0.0"

echo 'Removing old platforms...'
${ANDROID_SDK_ROOT}/cmdline-tools/latest/bin/sdkmanager --uninstall "platforms;android-31" "platforms;android-32" "platforms;android-33" "platforms;android-33-ext4" "platforms;android-33-ext5" "platforms;android-34" "platforms;android-34-ext8" "platforms;android-34-ext10" "platforms;android-34-ext11" "platforms;android-34-ext12"

echo 'Removing NDKs...'
${ANDROID_SDK_ROOT}/cmdline-tools/latest/bin/sdkmanager --uninstall "ndk;26.3.11579264"

echo 'Removing extras...'
${ANDROID_SDK_ROOT}/cmdline-tools/latest/bin/sdkmanager --uninstall "extras;android;m2repository" "extras;google;google_play_services" "extras;google;m2repository"

# Docker cleanup
echo 'Cleaning up Docker resources'
docker system prune -af || true
echo 'Removing all Docker images'
docker rmi -f $(docker images -aq)
docker rmi -f $(docker images -aq) || true

echo 'Disk space after cleanup'
df -aH
255 changes: 237 additions & 18 deletions .github/workflows/build_and_test.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,20 @@
name: Build jsc-android and test

on:
workflow_dispatch: {}
workflow_dispatch:
inputs:
publish:
description: 'Publish npm packages after build/test succeed'
type: boolean
default: false
npm-tag:
description: 'npm dist-tag'
required: false
default: latest
dry-run:
description: 'Run npm publish in dry-run mode'
type: boolean
default: true
push:
branches: [main]
pull_request:
Expand All @@ -12,10 +25,17 @@ jobs:
env:
ORG_GRADLE_PROJECT_signingKey: ${{ secrets.GPG_SIGNING_KEY }}
ORG_GRADLE_PROJECT_signingPassword: ${{ secrets.GPG_SIGNING_PASSWORD }}
NDK_VERSION_27: '27.1.12297006'
NDK_VERSION_28: '28.2.13676358'
NDK_VERSION_29: '29.0.14206865'
BUILD_CACHE_VERSION: v1

steps:
- uses: actions/checkout@v4

- name: 🧹 Cleanup GitHub Linux runner disk space
uses: ./.github/actions/cleanup-linux-disk-space

- name: 🔨 Use JDK 17
uses: actions/setup-java@v4
with:
Expand All @@ -27,39 +47,170 @@ jobs:
with:
node-version: 22

- name: Compute build cache key
id: build-hash
run: |
HASH=$(node scripts/build-hash.js)
echo "hash=$HASH" >> "$GITHUB_OUTPUT"

- name: Restore JSC build artifacts
id: cache-dist
uses: actions/cache@v4
with:
path: |
dist-ndk27
dist-ndk27.unstripped
dist-ndk28
dist-ndk28.unstripped
dist-ndk29
dist-ndk29.unstripped
key: jsc-dist-${{ env.BUILD_CACHE_VERSION }}-${{ steps.build-hash.outputs.hash }}

- name: Restore WebKit sources
id: cache-download
uses: actions/cache@v4
with:
path: build/download
key: jsc-download-${{ env.BUILD_CACHE_VERSION }}-${{ steps.build-hash.outputs.hash }}
restore-keys: |
jsc-download-${{ env.BUILD_CACHE_VERSION }}-

- name: Install packages
run: |
sudo apt-get update
sudo apt-get install coreutils curl git wget python3 ruby gperf -y
sudo apt-get install coreutils curl git wget python3 ruby gperf ccache -y
shell: bash

- name: Restore ccache
id: cache-ccache
uses: actions/cache@v4
with:
path: ~/.cache/ccache
key: ccache-${{ env.BUILD_CACHE_VERSION }}-${{ runner.os }}-${{ env.NDK_VERSION_27 }}-${{ env.NDK_VERSION_28 }}-${{ env.NDK_VERSION_29 }}-${{ steps.build-hash.outputs.hash }}
restore-keys: |
ccache-${{ env.BUILD_CACHE_VERSION }}-${{ runner.os }}-${{ env.NDK_VERSION_27 }}-${{ env.NDK_VERSION_28 }}-${{ env.NDK_VERSION_29 }}-

- name: Configure ccache
run: |
mkdir -p ~/.cache/ccache
if command -v ccache >/dev/null 2>&1; then
ccache --max-size=5G
ccache --zero-stats || true
fi
shell: bash

- name: Cache Android NDK r27
id: cache-ndk-27
uses: actions/cache@v4
with:
path: ${{ env.ANDROID_HOME }}/ndk/${{ env.NDK_VERSION_27 }}
key: android-ndk-${{ runner.os }}-${{ env.NDK_VERSION_27 }}

- name: Cache Android NDK r28
id: cache-ndk-28
uses: actions/cache@v4
with:
path: ${{ env.ANDROID_HOME }}/ndk/${{ env.NDK_VERSION_28 }}
key: android-ndk-${{ runner.os }}-${{ env.NDK_VERSION_28 }}

- name: Cache Android NDK r29
id: cache-ndk-29
uses: actions/cache@v4
with:
path: ${{ env.ANDROID_HOME }}/ndk/${{ env.NDK_VERSION_29 }}
key: android-ndk-${{ runner.os }}-${{ env.NDK_VERSION_29 }}

- name: Install Android packages
run: |
export PATH=$PATH:$ANDROID_HOME/cmdline-tools/latest/bin:$ANDROID_HOME/platform-tools
yes | sdkmanager --licenses || true
sdkmanager \
"cmake;3.22.1" \
"ndk;27.1.12297006"
# move out builtin icu headers from ndk and prevent icu build errors
mv "${ANDROID_HOME}/ndk/27.1.12297006/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include/unicode" "${ANDROID_HOME}/ndk/27.1.12297006/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include/unicode2"

echo "ANDROID_NDK=$ANDROID_HOME/ndk/27.1.12297006" >> $GITHUB_ENV
echo "PATH=$PATH:$ANDROID_HOME/cmdline-tools/latest/bin:$ANDROID_HOME/platform-tools" >> $GITHUB_ENV
sdkmanager "cmake;3.22.1"
for version in "${NDK_VERSION_27}" "${NDK_VERSION_28}" "${NDK_VERSION_29}"; do
if [[ -z "$version" ]]; then
continue
fi
if [[ ! -d "${ANDROID_HOME}/ndk/${version}" ]]; then
sdkmanager "ndk;${version}"
fi
UNICODE_DIR="${ANDROID_HOME}/ndk/${version}/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include/unicode"
if [[ -d "${UNICODE_DIR}" ]]; then
mv "${UNICODE_DIR}" "${UNICODE_DIR}2"
fi
done
echo "ANDROID_NDK=$ANDROID_HOME/ndk/${NDK_VERSION_27}" >> $GITHUB_ENV
echo "PATH=$PATH" >> $GITHUB_ENV
shell: bash

- name: Install dependencies
run: yarn install --frozen-lockfile
shell: bash

- name: Clean previous build outputs
if: steps.cache-dist.outputs.cache-hit != 'true'
run: |
rm -rf dist dist.unstripped dist-ndk* build/target* build/compiled* build/cppruntime*
shell: bash

- name: Download sources
if: steps.cache-download.outputs.cache-hit != 'true'
run: yarn download
shell: bash

- name: Build
if: steps.cache-dist.outputs.cache-hit != 'true'
run: |
yarn install --frozen-lockfile
yarn clean
yarn download
yarn start
variants=(ndk27 ndk28c ndk29)
for variant in "${variants[@]}"; do
case "$variant" in
ndk27)
export ANDROID_NDK="$ANDROID_HOME/ndk/${NDK_VERSION_27}"
;;
ndk28c)
export ANDROID_NDK="$ANDROID_HOME/ndk/${NDK_VERSION_28}"
;;
ndk29)
export ANDROID_NDK="$ANDROID_HOME/ndk/${NDK_VERSION_29}"
;;
*)
echo "Unknown variant $variant" >&2
exit 1
esac

if [[ ! -d "$ANDROID_NDK" ]]; then
echo "Android NDK not found at $ANDROID_NDK for variant $variant" >&2
exit 1
fi

export JSC_NDK_VARIANT="$variant"
yarn start
done
shell: bash

- name: Show ccache stats
if: steps.cache-dist.outputs.cache-hit != 'true'
run: |
if command -v ccache >/dev/null 2>&1; then
ccache --show-stats
fi
shell: bash

- name: Archive
run: |
rm -rf archive
mkdir -p archive
mv dist archive/
mv dist.unstripped archive/
shopt -s nullglob
found=0
for dir in dist-ndk*; do
if [[ -d "$dir" ]]; then
cp -R "$dir" archive/
found=1
fi
done
shopt -u nullglob
if [[ $found -eq 0 ]]; then
echo "No distribution directories were produced." >&2
exit 1
fi
shell: bash

- uses: actions/upload-artifact@v4
Expand Down Expand Up @@ -96,8 +247,12 @@ jobs:

- name: Extract archive
run: |
mv archive/dist dist
mv archive/dist.unstripped dist.unstripped
shopt -s nullglob
for dir in archive/dist-ndk*; do
dest=$(basename "$dir")
mv "$dir" "$dest"
done
shopt -u nullglob
rmdir archive
shell: bash

Expand Down Expand Up @@ -125,11 +280,22 @@ jobs:
target: google_apis
working-directory: test
script: |
export JSC_GRADLE_DIST_PATH=../../dist-ndk27
npx expo run:android --variant release --no-bundler
adb logcat -c
set +e
maestro test maestro.yaml
STATUS=$?
if [ $STATUS -eq 0 ]; then
for variant in ndk27 ndk28c ndk29; do
../scripts/run-js-smoketest.sh "$variant"
EXIT_CODE=$?
if [ $EXIT_CODE -ne 0 ]; then
STATUS=$EXIT_CODE
break
fi
done
fi
adb logcat -d > adb.log
exit $STATUS

Expand All @@ -142,3 +308,56 @@ jobs:
$HOME/.maestro/tests/**/*
test/android/app/build/outputs/apk/release/app-release.apk
test/adb.log

publish:
if: github.event_name == 'workflow_dispatch' && github.event.inputs.publish == 'true'
needs:
- build
- test
runs-on: ubuntu-latest
environment:
name: npm-publish
url: https://www.npmjs.com/package/jsc-android
permissions:
contents: read
steps:
- uses: actions/checkout@v4

- name: ⬢ Setup Node
uses: actions/setup-node@v4
with:
node-version: 22

- uses: actions/download-artifact@v4
with:
name: archive
path: archive

- name: Install dependencies
run: yarn install --frozen-lockfile
shell: bash

- name: Verify npm token availability
if: github.event.inputs.dry-run != 'true'
run: |
if [[ -z "${NPM_TOKEN:-}" ]]; then
echo "NPM_TOKEN secret is required for publishing." >&2
exit 1
fi
env:
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
shell: bash

- name: Publish packages
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
NPM_CONFIG_PROVENANCE: 'true'
run: |
TAG="${{ github.event.inputs.npm-tag }}"
DRY_RUN="${{ github.event.inputs.dry-run }}"
PUBLISH_ARGS=("-T" "$TAG")
if [[ "$DRY_RUN" == 'true' ]]; then
PUBLISH_ARGS+=("--dry-run")
fi
node scripts/publish.js "${PUBLISH_ARGS[@]}" archive
shell: bash
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package-lock.json
/build
/dist
/dist.unstripped
/dist-ndk*

# Created by https://www.gitignore.io/api/node,android,reactnative,intellij+all,androidstudio,visualstudiocode

Expand Down
4 changes: 4 additions & 0 deletions lib/jsc-android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@ android {
versionCode 1
versionName "1.0"

ndk {
abiFilters 'arm64-v8a', 'x86_64'
}

externalNativeBuild {
cmake {
arguments '-DANDROID_STL=c++_shared',
Expand Down
Loading
Loading