# How the React Native Build System Is Configured: Gradle, CMake, and Android Build Setup

> Discover how the React Native build system configures Gradle, CMake, and Android setup using Kotlin DSL scripts. Understand C++ dependencies and Hermes integration for efficient mobile app development.

- Repository: [Meta/react-native](https://github.com/facebook/react-native)
- Tags: internals
- Published: 2026-02-25

---

**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`](https://github.com/facebook/react-native/blob/main/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`](https://github.com/facebook/react-native/blob/main/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

```bash

# 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

```bash

# 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 downloads
- **`REACT_NATIVE_ARCHITECTURES`**: Comma-separated list of ABIs to build (e.g., `arm64-v8a,x86_64`)
- **`ndkPath`**: Gradle property pointing to Android NDK installation, consumed in `build.gradle.kts` (lines 52-56)

## Summary

- The React Native build system relies on **Kotlin DSL Gradle scripts** defined in the `facebook/react-native` repository to configure Android artifacts
- **Root `build.gradle.kts`** manages global plugins, versioning, Hermes substitution, and Maven publishing to Sonatype
- **`ReactAndroid/build.gradle.kts`** handles Android library compilation, CMake native builds, third-party C++ dependency downloads, and Prefab publishing for `jsi`
- **Native compilation** occurs through CMake configured in [`ReactAndroid/src/main/jni/CMakeLists.txt`](https://github.com/facebook/react-native/blob/main/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`](https://github.com/facebook/react-native/blob/main/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.