Aktivasi New Architecture pada React Native (Fabric dan TurboModules) memindahkan beban render dan bridging ke layer C++. Konsekuensinya, Android NDK dan CMake harus mengompilasi puluhan dependensi native seperti Folly, Glog, Yoga, dan ReactCommon dari source code. Di lingkungan CI yang bersifat ephemeral, kompilasi ulang kode C++ ini terjadi berulang kali pada setiap commit, membuang waktu eksekusi runner dan memperlambat feedback loop tim.
Ccache (Compiler Cache) memangkas durasi tersebut dengan menyimpan output kompilasi C/C++ ke dalam disk cache berdasarkan hash input preprosesor. Artikel ini menguraikan langkah integrasi Ccache ke dalam pipeline GitHub Actions untuk proyek React Native Android.
1. Injeksi Ccache ke CMake via Gradle
Android Gradle Plugin (AGP) mengeksekusi CMake untuk mengompilasi file native. Agar CMake menggunakan Ccache sebagai wrapper compiler Clang/Clang++, oper flag CMAKE_C_COMPILER_LAUNCHER dan CMAKE_CXX_COMPILER_LAUNCHER melalui block externalNativeBuild di android/app/build.gradle.
Gunakan deteksi binary agar konfigurasi tetap aman dijalankan di mesin lokal pengembang yang belum tentu memasang Ccache:
// android/app/build.gradle
android {
...
defaultConfig {
...
externalNativeBuild {
cmake {
def ccacheExecutable = "which ccache".execute().text.trim()
if (ccacheExecutable) {
arguments "-DCMAKE_C_COMPILER_LAUNCHER=${ccacheExecutable}",
"-DCMAKE_CXX_COMPILER_LAUNCHER=${ccacheExecutable}"
}
}
}
}
}Logika ini memeriksa keberadaan executable ccache melalui perintah shell. Jika ditemukan di PATH, CMake akan mengarahkan pemanggilan Clang melalui launcher Ccache.
2. Konfigurasi Environment dan Normalisasi Path
Kesalahan umum integrasi Ccache pada CI adalah cache miss akibat path absolut runner yang berbeda di setiap workflow run. Variabel environment CCACHE_BASEDIR wajib disetel ke root repository untuk menormalkan path file dalam debug symbols dan tracking dependensi.
Variabel penting yang perlu disetel sebelum build:
- CCACHE_DIR: Lokasi direktori cache di runner, misalnya
~/.ccache. - CCACHE_BASEDIR: Direktori root proyek (
${{ github.workspace }}) agar hashing file tidak terpengaruh lokasi absolut. - CCACHE_MAXSIZE: Batas ukuran cache (misal
2Gatau5G) untuk mencegah cache melebihi quota runner. - CCACHE_COMPRESS: Bernilai
1untuk mengompresi object files, menghemat transfer IO dan space cache storage.
3. Setup Workflow GitHub Actions
Pasang Ccache runner runner via apt-get, atur persistent cache menggunakan actions/cache, lalu jalankan task build. Tambahkan pembacaan metrik sebelum dan sesudah kompilasi.
name: Android Fabric Build
on: [push, pull_request]
jobs:
build-android:
runs-on: ubuntu-latest
steps:
- name: Checkout Repository
uses: actions/checkout@v4
- name: Setup Java
uses: actions/setup-java@v4
with:
distribution: 'zulu'
java-version: '17'
- name: Install Ccache
run: sudo apt-get update && sudo apt-get install -y ccache
- name: Restore Ccache
uses: actions/cache@v4
with:
path: ~/.ccache
key: ccache-android-${{ runner.os }}-${{ hashFiles('package-lock.json', 'android/app/build.gradle') }}
restore-keys: |
ccache-android-${{ runner.os }}-
- name: Setup Ccache Environment
run: |
echo "CCACHE_DIR=${HOME}/.ccache" >> $GITHUB_ENV
echo "CCACHE_BASEDIR=${{ github.workspace }}" >> $GITHUB_ENV
echo "CCACHE_COMPRESS=1" >> $GITHUB_ENV
echo "CCACHE_MAXSIZE=2G" >> $GITHUB_ENV
ccache -z # Reset statistik sebelum build
- name: Compile Android APK
run: |
cd android
./gradlew assembleRelease --no-daemon
- name: Evaluasi Metrik Ccache
if: always()
run: ccache -s4. Memantau Hit Rate via `ccache -s`
Perintah ccache -s menghasilkan ringkasan utilisasi cache. Parameter utama yang menentukan efektivitas integrasi adalah Cache hit rate.
- Direct cache hit: Source code dan macro identik, file objek langsung dipakai dari cache tanpa pemanggilan preprosesor compiler.
- Preprocessed cache hit: Source code berubah pada baris komentar atau whitespace, namun hasil preprosesor menghasilkan token identik.
- Cache miss: Terjadi pada build awal (cold cache) atau ketika file C++ diubah.
Pada pipeline warm cache, hit rate Fabric builds idealnya berada di atas 75% - 90% untuk kode ReactCommon, Folly, dan TurboModules third-party yang tidak mengalami perubahan.
5. Strategi Invalidasi Cache
Cache C++ yang tidak di-invalidasi saat compiler berubah dapat menyebabkan build error misterius atau binary mismatch. Invalidasi harus dipicu secara ketat oleh parameter berikut:
- Update NDK: Perubahan versi Android NDK membawa toolchain dan standard library (libc++) baru. Sertakan versi NDK pada primary cache key GitHub Actions jika Anda mengontrol versinya via
build.gradle. - Update React Native Core: Perubahan versi di
package.jsonsering kali membawa patch source code native C++ internal. Menyertakan lockfile (yarn.lockataupackage-lock.json) pada hash key mencegah pemakaian cache dari source lama. - Build Flags Compiler: Perubahan flag optimasi (seperti
-O2ke-O3) otomatis di-hash oleh Ccache, tetapi perubahan macro global sebaiknya diimbangi dengan mereset cache jika terjadi anomali linking.
Catatan: Hindari menyertakan timestamp atau commit SHA pada primary key cache, karena hal itu akan mengubah primary key di setiap push dan mematikan fungsi pemanfaatan kembali cache branch sebelumnya. Gunakan restore-keys prefix untuk fallback.
Komentar
0 komentar
Masuk ke akun kamu untuk ikut berkomentar.
Belum ada komentar
Jadilah yang pertama ikut berdiskusi!