How the React Native Build System Is Configured: Gradle, CMake, and Android Build Setup
The React Native build system is configured through Kotlin DSL Gradle scripts that orchestrate Android library compilation, CMake-based native builds for C++ dependencies, and Hermes engine integration, centered in build.gradle.kts and packages/react-native/ReactAndroid/build.gradle.kts with customization via Gradle properties and environment variables.
React Native's build system is a hybrid architecture spanning Gradle for Android, Xcode for iOS, and Metro for JavaScript bundling. In the facebook/react-native open-source repository, the Android configuration is the most complex, defined entirely in Kotlin DSL scripts that manage versioning, native compilation, and dependency resolution. This guide examines the actual source files that control the build pipeline.
Global Build Configuration in build.gradle.kts
The root build.gradle.kts serves as the central configuration hub that propagates settings to all sub-projects in the monorepo via Gradle's subprojects and allprojects DSL.
Plugin Management and Versioning
Lines 8-16 apply core Gradle plugins including Android, Kotlin, Nexus publishing, and Ktfmt formatting. The build extracts versioning from ReactAndroid/gradle.properties or appends -SNAPSHOT when isSnapshot=true (lines 41-51), assigning the group ID com.facebook.react.
Hermes Engine Substitution
The hermesSubstitution block (lines 14-74) conditionally replaces the local :packages:react-native:ReactAndroid:hermes-engine project with pre-built Maven artifacts. This supports three modes: stable releases, nightly builds, or source compilation, controlled by Gradle properties like react.internal.useHermesStable.
Cleaning and Publishing Tasks
The custom clean task (lines 68-98) extends beyond standard Gradle cleaning to remove generated C++ builds, downloaded third-party artifacts, and temporary files. Maven Central publishing configures Sonatype credentials read from environment variables or Gradle properties (lines 52-56), while nexusPublishing (lines 57-69) and the publishAllToMavenTempLocal task handle artifact distribution.
Android Module Configuration in ReactAndroid/build.gradle.kts
The ReactAndroid module contains the core Android library build logic, handling native C++ compilation through CMake and third-party dependency management.
Native Build and CMake Integration
The externalNativeBuild block (lines 70-82) invokes CMake to compile three critical native libraries: reactnative, jsi, and hermestooling. CMake arguments point to ReactCommon, specify the Android STL, toolchain, and conditionally enable Hermes flags. The actual CMake project resides in packages/react-native/ReactAndroid/src/main/jni/CMakeLists.txt.
Third-Party Dependency Downloads
Tasks defined between lines 96-165 use the de.undercouch.gradle.tasks.download.Download plugin to fetch and extract Boost, double-conversion, Folly, FastFloat, fmt, and glog into the third-party-ndk directory. These tasks execute before native compilation to ensure headers and libraries are present.
Architecture Filters and Build Variants
ABI filters default to armeabi-v7a,x86,x86_64,arm64-v8a via the reactNativeArchitectures() function (lines 93-94), customizable through the REACT_NATIVE_ARCHITECTURES Gradle property. The custom debugOptimized build type (lines 72-79) compiles native code with -DCMAKE_BUILD_TYPE=Release while maintaining Java/Kotlin debug configurations.
Codegen and Prefab Publishing
The buildCodegenCLI task (lines 53-67) executes JavaScript-to-Java/Kotlin code generation before any native build, ensuring bridge code artifacts exist. Prefab publishing (lines 154-158) exposes C++ headers and pre-compiled libraries via prefab { create("jsi") ... }, allowing downstream Android consumers to link against React Native's native interfaces directly from the AAR.
Dependency Configuration
The module declares dependencies on AndroidX, FBJNI, Fresco, SoLoader, Yoga, and OkHttp (lines 88-114). The Hermes engine is declared as a compileOnly dependency, enabling the substitution logic defined in the root project.
Key Configuration Files and Customization Points
| Path | Purpose |
|---|---|
gradle.properties (root) |
Defines versions for Boost, Folly, Glog, and toggles like hermesV1Enabled |
packages/react-native/ReactAndroid/gradle.properties |
Supplies VERSION_NAME and binary-compatibility validator settings |
packages/react-native/ReactAndroid/hermes-engine/build.gradle.kts |
Builds the Hermes JavaScript engine from source when not substituted |
packages/react-native/ReactAndroid/src/main/jni/CMakeLists.txt |
CMake script compiling native libraries (reactnative, jsi, hermestooling) |
packages/react-native/ReactAndroid/publish.gradle |
Maven publishing configuration applied to the module |
scripts/releases/ |
Release automation scripts (e.g., set-version) manipulating version numbers |
Common Build Commands and Workflows
Standard Build Operations
# Clean all generated artifacts, native builds, and downloaded dependencies
./gradlew clean
# Build the Android AAR in debug mode
./gradlew :packages:react-native:ReactAndroid:assembleDebug
# Build release version with pre-built Hermes from Maven Central
./gradlew -Preact.internal.useHermesStable=true \
:packages:react-native:ReactAndroid:assembleRelease
Advanced Configuration
# Specify custom NDK path (useful for CI on Apple Silicon)
./gradlew -PndkPath=/opt/android/ndk/25.1.8937393 assembleDebug
# Build debugOptimized variant (optimized native code, debuggable Java)
./gradlew :packages:react-native:ReactAndroid:assembleDebugOptimized
# Publish to temporary local Maven repository for consumer testing
./gradlew publishAllToMavenTempLocal
Environment Variables and Properties
REACT_NATIVE_DOWNLOADS_DIR: Specifies custom directory for third-party C++ dependency downloadsREACT_NATIVE_ARCHITECTURES: Comma-separated list of ABIs to build (e.g.,arm64-v8a,x86_64)ndkPath: Gradle property pointing to Android NDK installation, consumed inbuild.gradle.kts(lines 52-56)
Summary
- The React Native build system relies on Kotlin DSL Gradle scripts defined in the
facebook/react-nativerepository to configure Android artifacts - Root
build.gradle.ktsmanages global plugins, versioning, Hermes substitution, and Maven publishing to Sonatype ReactAndroid/build.gradle.ktshandles Android library compilation, CMake native builds, third-party C++ dependency downloads, and Prefab publishing forjsi- Native compilation occurs through CMake configured in
ReactAndroid/src/main/jni/CMakeLists.txt, producing libraries for the JNI bridge and Hermes tooling - Customization is achieved through Gradle properties (
ndkPath,reactNativeArchitectures) and environment variables controlling download directories and build targets - Hermes flexibility allows switching between source builds and pre-built Maven artifacts (stable or nightly) via the root project's substitution mechanism
Frequently Asked Questions
How do I customize the NDK path in React Native's build system?
Pass the ndkPath property when running Gradle tasks: ./gradlew -PndkPath=/opt/android/ndk/25.1.8937393 assembleDebug. The build script reads this value in build.gradle.kts (lines 52-56) and configures the Android Gradle Plugin accordingly. You can also set this in gradle.properties or as an environment variable for CI environments.
What is the debugOptimized build type and when should I use it?
The debugOptimized variant (defined in ReactAndroid/build.gradle.kts lines 72-79) compiles native C++ code with -DCMAKE_BUILD_TYPE=Release flags while keeping Java/Kotlin bytecode in debug mode. Use this when you need to debug Java code but want near-release performance from native modules, as standard debug builds use unoptimized native code that runs significantly slower.
How does the build system handle third-party C++ dependencies like Boost and Folly?
The ReactAndroid/build.gradle.kts defines explicit download tasks (lines 96-165) using the de.undercouch.gradle.tasks.download plugin. These tasks fetch versioned archives from remote repositories, verify checksums, and extract them into third-party-ndk. The CMake configuration in ReactAndroid/src/main/jni/CMakeLists.txt then references these extracted headers and libraries during compilation.
Can I use a pre-built Hermes engine instead of compiling from source?
Yes. The root build.gradle.kts implements a hermesSubstitution block (lines 14-74) that replaces the local :packages:react-native:ReactAndroid:hermes-engine project with Maven artifacts. Pass -Preact.internal.useHermesStable=true for stable releases or -Preact.internal.useHermesNightly=true for nightly builds. When enabled, the build declares Hermes as a compileOnly dependency in ReactAndroid/build.gradle.kts (lines 88-114) and downloads pre-built binaries from Maven Central instead of compiling local source.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →