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".

معلومات المصدر

المستودع
software-mansion/react-native-audio-api
آخر نشاط في المصدر
٦ أكتوبر ٢٠٢٦ في ١٤:٤٧
لغة SKILL.md المكتشفة
الإنجليزية
النجوم
٨٤٨
التفرعات
٩٤

خيارات التثبيت

يُحدَّد Prompt الذي يراجع المصدر أولًا بشكل افتراضي. يمكنك التبديل إلى أمر مباشر أو تنزيل نسخة محلية.

مراجعة ملفات المصدر

اقرأ SKILL.md وأي ملفات مرافقة يعرضها SkillsMP قبل أن تقرر التثبيت.

مستكشف الملفات
3 ملفات

عرض SKILL.md

SKILL.md
تعليمات المصدر · معاينة للقراءة فقط
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). ---
عرض على GitHub
ملف SKILL.md هذا كبير جدا، لذلك يعرض SkillsMP القسم الاول فقط هنا. عرض على GitHub