Skip to main content

build-compilation-dependencies

Build system overview for react-native-audio-api across all platforms — CMakeLists.txt, android/build.gradle, RNAudioAPI.podspec, prebuilt external libraries, and the standalone C++ test build. Use this skill when adding a new source file, modifying CMakeLists or podspec, debugging compilation errors, integrating a new dependency, or understanding why includes work differently in tests vs the app. Trigger phrases: "add source file", "CMakeLists", "podspec", "build.gradle", "prebuilt binaries", "FFmpeg disabled", "pod install", "new architecture", "compile error", "undefined symbol", "SIMD", "worklets build flag", "C++ tests", "conditional compilation", "include path", "gradle build fails", "link error", "yarn catalog", "catalog:", "add a dependency", "bump a dependency", "yarn workspaces", "npmMinimalAgeGate", "shared dependency version".

Informations de source

Dépôt
software-mansion/react-native-audio-api
Dernière activité de la source
6 octobre 2026 à 14:47
Langue détectée de SKILL.md
anglais
Étoiles
848
Forks
94

Options d'installation

Le prompt qui vérifie d'abord la source est sélectionné par défaut. Vous pouvez passer à une commande directe ou télécharger une copie locale.

Vérifiez les fichiers source

Lisez SKILL.md et les fichiers associés affichés par SkillsMP avant de décider de l'installer.

Explorateur de fichiers
3 fichiers

Affichage de SKILL.md

SKILL.md
Instructions source · Aperçu en lecture seule
name
build-compilation-dependencies
description
Build system overview for react-native-audio-api across all platforms — CMakeLists.txt, android/build.gradle, RNAudioAPI.podspec, prebuilt external libraries, and the standalone C++ test build. Use this skill when adding a new source file, modifying CMakeLists or podspec, debugging compilation errors, integrating a new dependency, or understanding why includes work differently in tests vs the app. Trigger phrases: "add source file", "CMakeLists", "podspec", "build.gradle", "prebuilt binaries", "FFmpeg disabled", "pod install", "new architecture", "compile error", "undefined symbol", "SIMD", "worklets build flag", "C++ tests", "conditional compilation", "include path", "gradle build fails", "link error", "yarn catalog", "catalog:", "add a dependency", "bump a dependency", "yarn workspaces", "npmMinimalAgeGate", "shared dependency version".
# Skill: Build, Compilation & Dependencies For deep CMake/Gradle/podspec analysis see [build-details.md](build-details.md). --- ## Repository Build Overview ``` react-native-audio-api/ ├── package.json # Yarn 4 workspaces root ├── packages/react-native-audio-api/ # Main library │ ├── android/ │ │ ├── build.gradle # Android build config (Gradle) │ │ ├── CMakeLists.txt # Android CMake root (delegates to subdirectory) │ │ └── src/main/cpp/audioapi/ │ │ └── CMakeLists.txt # Actual Android C++ build target │ ├── common/cpp/audioapi/ # Shared C++ (used by all platforms) │ │ ├── decoding/ # Decoder factory, backends, SeekDecoderDaemon, AudioDecoding │ │ ├── encoding/ # AudioEncoder interface, EncoderCapabilities, OS encoder/remux selector headers, AudioFileConcatenator │ │ ├── libs/ # Third-party wrappers (FFmpeg, miniaudio, pffft, …) │ │ └── external/ # Prebuilt binaries per platform │ │ ├── android/ # .a static libs (Opus, Ogg, Vorbis, OpenSSL) │ │ ├── iphoneos/ # iOS device .a libs │ │ ├── iphonesimulator/ # iOS sim .a libs │ │ ├── macosx/ # macOS .a libs │ │ ├── ffmpeg_ios/ # FFmpeg .xcframeworks (iOS only) │ │ ├── include/ # Headers for Opus/Ogg/Vorbis/OpenSSL │ │ └── include_ffmpeg/ # Headers for FFmpeg │ ├── common/cpp/test/ │ │ ├── CMakeLists.txt # Standalone test build (no Android/iOS) │ │ ├── run-tests.sh / filters.sh # smoke|extended|full (+ categories, CI path filters) │ │ └── src/ # Google Test files │ ├── RNAudioAPI.podspec # CocoaPods spec for iOS │ └── scripts/ │ ├── download-prebuilt-binaries.sh # Downloads externals from GitHub Releases │ ├── rnaa_utils.rb # Ruby helpers for podspec (path resolution, worklets check) │ └── validate-worklets-version.js └── apps/ └── fabric-example/ └── ios/ └── Podfile # Consumer Podfile (new arch enabled) ``` --- ## Yarn Workspaces & Dependency Catalog Dependency versions live in a single catalog in the root `.yarnrc.yml`, referenced from manifests as `"<dep>": "catalog:"`. Bump once there and every workspace follows. Needs Yarn >= 4.10 (repo is on 4.18). **What belongs in the catalog** — anything that must move in lockstep, which is broader than "used more than once": - used by two or more workspaces, **or** - version-locked to something already catalogued even if only one workspace uses it — `react-test-renderer` must equal `react`; `@react-native-community/cli*` and `@babel/runtime` move with `react-native` / `@babel/core`. A dependency used in exactly one workspace with no such coupling stays a literal range: it has no second copy to drift from, and catalogue membership is meant to *signal* "keep this in lockstep". There is no CI check enforcing this — review is the enforcement, which is why membership has to carry meaning. **Workflow when touching dependencies:** 1. Changing the version of a catalogued dep → edit the catalog entry, not the manifest. 2. Adding a dep → check the catalog first. Already there? Use `"catalog:"`. Not there but lockstep-coupled or now used twice? Add the entry and switch both call sites over. Three kinds of dependency must **never** be given `catalog:`: | Never catalogue | Why | |---|---| | `peerDependencies` | Public API surface of the published packages, deliberately loose (`"*"`). Pinning narrows what consumers may install. | | Runtime `dependencies` of published packages (`semver`, `chalk`, `commander`, `fs-extra`) | The release pipeline packs with `npm pack` (`scripts/create-package.sh`, `npm-custom-node-generator-build.yml`) and npm does not understand `catalog:`. It publishes the literal string, producing an uninstallable package. Only `yarn pack` / `yarn npm publish` perform the swap. | | `workspace:*` ranges | Not version ranges — nothing to centralise. | Other constraints: - **`resolutions` does not accept `catalog:`** — install fails with `typescript@catalog: isn't supported by any available resolver`. Root `package.json` pins `typescript` literally; keep it in sync with the catalog entry. It is *not* redundant with the catalog: it forces `@commitlint/load`'s optional `typescript` peer (`^4.6.4 || ^5.2.2`) onto our version, and catalogs only rewrite workspace manifests, never transitive dependencies. - **`packages/audiodocs` is a separate Yarn 1 project** with its own lockfile and `node_modules`. It is not in root `workspaces`, so the catalog does not reach it. - **`yarn pack` is not a drop-in for `npm pack` here.** It drops `development/react/` (a nested `package.json` listed in `files[]`) and strips the executable bit from 29 prebuilt FFmpeg binaries. Do not switch the release pipeline to it without re-verifying the tarball contents. Supply-chain gate: `npmMinimalAgeGate: '1w'` refuses versions published in the last 7 days. Bypass one command with `yarn add --no-time-gate` / `yarn up --no-time-gate`, or exempt specific packages permanently via `npmPreapprovedPackages`. --- ## C++ Header File Extensions In `common/cpp/audioapi/`: `.hpp` = header-only templates; `.h` = non-template (usually with a `.cpp`). Vendored code is excluded. --- ## Prebuilt Binaries External libraries (Opus, Ogg, Vorbis, OpenSSL, FFmpeg) are **not compiled from source** — they are downloaded as prebuilt `.a` / `.so` / `.xcframework` archives from: ``` https://github.com/software-mansion-labs/rn-audio-libs/releases/download/<TAG>/ ``` Current tag: **v3.0.0** (see `scripts/download-prebuilt-binaries.sh`). The download script is triggered automatically: - **iOS**: by podspec `prepare_command` during `pod install` **and** by a `script_phase` (`[CP-User] Download RNAudioAPI prebuilt binaries`, `:before_headers`, always-out-of-date) on every Xcode build — downloads `ffmpeg_ios`, `iphoneos`, `iphonesimulator`, `macosx`. `prepare_command` ensures all vendored `.xcframework`s exist when CocoaPods generates `[CP] Copy XCFrameworks` (required for correct FFmpeg linking). The build-time phase handles CI setups that cache `Pods/` independently from `node_modules/` — it is a fast no-op when binaries are already present. **It must use `:before_headers`, not `:before_compile`** — CocoaPods inserts its own `[CP] Copy XCFrameworks` phase right after `Headers`; `:before_compile` would land *after* it. The phase's `output_files` declares both the `-force_load` static libs and the four FFmpeg xcframeworks. The whole phase is skipped only when *both* `DISABLE_AUDIOAPI_STATIC_EXTERNAL_LIBS` and `DISABLE_AUDIOAPI_FFMPEG` are set. - **Android**: by `downloadPrebuiltBinaries` Gradle task, which runs before `preBuild` — downloads `android`, `jniLibs` The script is idempotent — it skips any archive whose destination directory already exists, so the per-build invocations are fast no-ops once binaries are present. Downloaded artifacts land in: - `common/cpp/audioapi/external/android/<ABI>/` — `.a` static libs for Android ABIs - `android/src/main/jniLibs/<ABI>/` — FFmpeg `.so` shared libs for Android (loaded at runtime) - `common/cpp/audioapi/external/ffmpeg_ios/` — FFmpeg `.xcframework` files for iOS - `common/cpp/audioapi/external/iphoneos/` / `iphonesimulator/` / `macosx/` — Opus/Ogg/etc `.a` **These directories are gitignored.** If they're missing, run `pod install` (iOS) or Gradle build (Android) to re-download them. Do not commit them. --- ## Android Build — high-level summary ### Files - `android/build.gradle` — Gradle library config - `android/fix-prefab.gradle` — prefab publication workaround (ported from react-native-worklets) - `android/CMakeLists.txt` — Android CMake root (SIMD detection, RN version flags, delegates to subdirectory) - `android/src/main/cpp/audioapi/CMakeLists.txt` — actual build target (sources, prebuilt libs, include paths) - `common/cpp/audioapi/EXTENSION_API.md` — stable C++ extension contract for dependent native modules - `common/cpp/audioapi/compatibility/StableAPI.h` — single public C++ compatibility header for extensions ### Key behaviors - Feature flags (`newArchEnabled`, `disableAudioapiFFmpeg`) are read from app's `gradle.properties` and forwarded to both CMake and Kotlin `BuildConfig` - DSP sources always compiled with `-O3` regardless of overall build type - Sources gathered with `GLOB_RECURSE CONFIGURE_DEPENDS` — CMake re-runs automatically when files are added/removed - 16KB page size alignment enabled for Android 15+ - **Extension API (prefab)**: single public C++ header `<audioapi/compatibility/StableAPI.h>`; prefab publishes transitive headers needed to compile it (`prepareAudioApiHeadersForPrefabs`); `fix-prefab.gradle` ensures the `.so` is in prefab metadata. Contract: `EXTENSION_API.md` - CMake exposes `COMMON_CPP_DIR` and `ANDROID_CPP_DIR` as **PUBLIC** include dirs so prefab consumers resolve `<audioapi/...>` For full per-line analysis see [build-details.md](build-details.md#android-androidcmakeliststxt-root--detailed-analysis). --- ## iOS Build (CocoaPods) — high-level summary ### Files - `RNAudioAPI.podspec` — library spec with subspecs - `scripts/rnaa_utils.rb` — Ruby helpers called by podspec - `apps/fabric-example/ios/Podfile` — consumer ### Key behaviors - Four subspecs split compilation: `audioapi` (core C++), `audioapi/ios` (ObjC++), `audioapi/audioapi_dsp` (DSP with `-O3`), `audioapi/miniaudio_impl` (compiled as `-x objective-c++`) - Static prebuilt libs linked with `-force_load` to prevent dead-stripping - FFmpeg xcframeworks listed in `s.ios.vendored_frameworks` — CocoaPods handles embedding and signing - `Accelerate` framework linked, enabling `HAVE_ACCELERATE=1` for vDSP SIMD on iOS - Header search paths split: `pod_target_xcconfig` (library compilation) vs `xcconfig` (app consumers) - `rnaa_utils.rb` resolves dynamic paths at `pod install` time (not hardcoded) - JSI internals use distinct names (`HostObject`, `RuntimeInstanceCache`, `RuntimeObserver`) instead of generic names like `JsiHostObject` / `RuntimeAwareCache` / `RuntimeLifecycleMonitor` — `react-native-skia` publishes headers with those generic names and CocoaPods can resolve the wrong file when both libraries are in the same app For full per-line analysis see [build-details.md](build-details.md#ios-rnaudioapipodspec--detailed-analysis). --- ## Building the Apps ### iOS (fabric-example) ```bash # From the monorepo root first: yarn install # Then install pods — must be done from the ios/ directory: cd apps/fabric-example/ios pod install # Run the app (from repo root): yarn workspace fabric-example ios # or open Xcode: open apps/fabric-example/ios/FabricExample.xcworkspace ``` **When to re-run `pod install`**: - After `yarn install` (any dependency change) - After changing `RNAudioAPI.podspec` - After adding/removing iOS source files that need to be picked up - After changing `rnaa_utils.rb` or `scripts/validate-worklets-version.js` - When prebuilt binaries need to be re-downloaded (podspec `prepare_command` runs on `pod install`) **Disable FFmpeg on iOS**: ```bash DISABLE_AUDIOAPI_FFMPEG=1 pod install ``` ### Android (fabric-example) ```bash yarn workspace fabric-example android # or open in Android Studio: open apps/fabric-example/android ``` **Disable FFmpeg on Android**: set in `android/gradle.properties`: ``` disableAudioapiFFmpeg=true ``` **Clean CMake cache** (fixes most mysterious native build failures): ```bash yarn workspace react-native-audio-api clean # or manually: rm -rf packages/react-native-audio-api/android/.cxx ``` --- ## Local Full Validation CI intentionally skips native Android/iOS builds (expensive). Use the tiered local validation script for pre-PR checks: ```bash yarn validate:fast # CI parity (format, lint, typecheck, enum sync, build, C++ + JS tests) yarn validate:cpp # C++ smoke yarn validate:cpp-extended # C++ extended (all categories) yarn validate:android # yarn workspace … build:android yarn validate:ios # yarn workspace … build:ios (macOS only) yarn validate:full # --fast + C++ extended + --android + --ios ``` Script: [`scripts/validate.sh`](../../../scripts/validate.sh) at monorepo root. ### What CI covers vs what validation tiers add | Layer | CI (`ci.yml` + `tests.yml`) | Local tiers | |---|---|---| | TS build (`bob build`) | Yes | `--fast` | | C++ smoke (`run-tests.sh`) | Yes | `--fast` | | C++ coverage (`run-coverage.sh`, smoke, Clang) | Yes (`cpp-coverage` artifact) | `yarn test:cpp:coverage` | | Jest | Yes | `--fast` | | Extended C++ by category (e.g. graph) | Path change or manual dispatch in `tests.yml` | `--cpp-extended` | | HostObjects (26 JSI `.cpp` files) | **No** | `--android` + `--ios` | | Android JNI C++ + Kotlin | **No** | `--android` | | iOS ObjC++ | **No** | `--ios` | | Prebuilt libs (Opus, FFmpeg, etc.) | **No** | `--android` / `--ios` (via `download-prebuilt-binaries.sh`) | | TurboModule codegen, worklets linking | **No** | `--android` / `--ios` | The C++ test build excludes HostObjects, `AudioContext.cpp`, `FFmpegDecoding.cpp`, and worklet nodes — see [C++ Tests](#c-tests-standalone-build) below. Passing `yarn test` alone does not prove native layers compile. ### Shared prebuild phase (before native tiers) Before `--android` or `--ios`, the script runs once: 1. `yarn install --immutable` + `yarn build` 2. [`download-prebuilt-binaries.sh`](../../../packages/react-native-audio-api/scripts/download-prebuilt-binaries.sh) `{android|ios}` (must run from `packages/react-native-audio-api/scripts/`) 3. `yarn workspace react-native-audio-api test:cpp` Android (NDK) and iOS (Clang) cannot share object files — reuse is at the prebuild/download level. If `ccache` is installed, `validate.sh` wraps host `CC`/`CXX`; only the host C++ tests (`test:cpp`) honor that — Gradle/NDK and `xcodebuild` use their own toolchains and are unaffected. ### Platform skip behavior - `--ios` on Linux → skip with message (exit 0) - `--android` without `ANDROID_HOME` → fail on explicit `--android`; skip with warning inside `--full` - `--full` includes C++ extended (all categories) after `--fast`’s smoke, so local full covers C++ full + native builds ### Which tier to run See the decision table in [post-work-checks](../post-work-checks/SKILL.md). ---
Voir sur GitHub
Ce SKILL.md est tres volumineux, SkillsMP affiche donc ici seulement la premiere section. Voir sur GitHub