/* * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ plugins { id("maven-publish") id("com.facebook.react") alias(libs.plugins.android.library) alias(libs.plugins.download) alias(libs.plugins.kotlin.android) } import com.facebook.react.tasks.internal.* import com.facebook.react.tasks.internal.utils.* import java.nio.file.Paths import kotlin.Pair import de.undercouch.gradle.tasks.download.Download version = VERSION_NAME group = "com.facebook.react" // We download various C++ open-source dependencies into downloads. // We then copy both the downloaded code and our custom makefiles and headers into third-party-ndk. // After that we build native code from src/main/jni with module path pointing at third-party-ndk. def customDownloadsDir = System.getenv("REACT_NATIVE_DOWNLOADS_DIR") def downloadsDir = customDownloadsDir ? new File(customDownloadsDir) : new File("$buildDir/downloads") def thirdPartyNdkDir = new File("$buildDir/third-party-ndk") def reactNativeRootDir = projectDir.parent // We put the publishing version from gradle.properties inside ext. so other // subprojects can access it as well. ext.publishing_version = VERSION_NAME // This is the version of CMake we're requesting to the Android SDK to use. // If missing it will be downloaded automatically. Only CMake versions shipped with the // Android SDK are supported (you can find them listed in the SDK Manager of Android Studio). def cmakeVersion = System.getenv("CMAKE_VERSION") ?: "3.22.1" ext.cmake_version = cmakeVersion // You need to have following folders in this directory: // - boost_1_83_0 // - double-conversion-1.1.6 // - folly-deprecate-dynamic-initializer // - glog-0.3.5 def dependenciesPath = System.getenv("REACT_NATIVE_DEPENDENCIES") // The Boost library is a very large download (>100MB). // If Boost is already present on your system, define the REACT_NATIVE_BOOST_PATH env variable // and the build will use that. def boostPath = dependenciesPath ?: System.getenv("REACT_NATIVE_BOOST_PATH") // By setting REACT_NATIVE_SKIP_PREFAB we can skip prefab publishing, to // reduce the size of the React Native published .AAR. def skipPrefabPublishing = System.getenv("REACT_NATIVE_SKIP_PREFAB") != null def prefabHeadersDir = project.file("$buildDir/prefab-headers") // Native versions which are defined inside the version catalog (libs.versions.toml) def BOOST_VERSION = libs.versions.boost.get() def DOUBLE_CONVERSION_VERSION = libs.versions.doubleconversion.get() def FMT_VERSION = libs.versions.fmt.get() def FOLLY_VERSION = libs.versions.folly.get() def GLOG_VERSION = libs.versions.glog.get() def LIBEVENT_VERSION = libs.versions.libevent.get() def GTEST_VERSION = libs.versions.gtest.get() final def preparePrefab = tasks.register("preparePrefab", PreparePrefabHeadersTask) { dependsOn(prepareBoost, prepareDoubleConversion, prepareFolly, prepareGlog) dependsOn("generateCodegenArtifactsFromSchema") // To export to a ReactNativePrefabProcessingEntities.kt once all // libraries have been moved. We keep it here for now as it make easier to // migrate one library at a time. it.input.set( [ new PrefabPreprocessingEntry( "react_render_debug", new Pair("../ReactCommon/react/renderer/debug/", "react/renderer/debug/") ), new PrefabPreprocessingEntry( "turbomodulejsijni", new Pair("src/main/jni/react/turbomodule", "") ), new PrefabPreprocessingEntry( "runtimeexecutor", new Pair("../ReactCommon/runtimeexecutor/", "") ), new PrefabPreprocessingEntry( "react_codegen_rncore", new Pair(new File(buildDir, "generated/source/codegen/jni/").absolutePath, "") ), new PrefabPreprocessingEntry( "react_debug", new Pair("../ReactCommon/react/debug/", "react/debug/") ), new PrefabPreprocessingEntry( "react_render_componentregistry", new Pair("../ReactCommon/react/renderer/componentregistry/", "react/renderer/componentregistry/") ), new PrefabPreprocessingEntry( "react_newarchdefaults", new Pair("src/main/jni/react/newarchdefaults", "") ), new PrefabPreprocessingEntry( "react_render_animations", new Pair("../ReactCommon/react/renderer/animations/", "react/renderer/animations/") ), new PrefabPreprocessingEntry( "react_render_core", new Pair("../ReactCommon/react/renderer/core/", "react/renderer/core/") ), new PrefabPreprocessingEntry( "react_render_graphics", [ new Pair("../ReactCommon/react/renderer/graphics/", "react/renderer/graphics/"), new Pair("../ReactCommon/react/renderer/graphics/platform/android/", ""), ] ), new PrefabPreprocessingEntry( "rrc_root", new Pair("../ReactCommon/react/renderer/components/root/", "react/renderer/components/root/") ), new PrefabPreprocessingEntry( "rrc_view", [ new Pair("../ReactCommon/react/renderer/components/view/", "react/renderer/components/view/"), new Pair("../ReactCommon/react/renderer/components/view/platform/android/", ""), ] ), new PrefabPreprocessingEntry( "rrc_legacyviewmanagerinterop", new Pair("../ReactCommon/react/renderer/components/legacyviewmanagerinterop/", "react/renderer/components/legacyviewmanagerinterop/") ), new PrefabPreprocessingEntry( "jsi", new Pair("../ReactCommon/jsi/", "") ), new PrefabPreprocessingEntry( "glog", new Pair(new File(buildDir, "third-party-ndk/glog/exported/").absolutePath, "") ), new PrefabPreprocessingEntry( "fabricjni", new Pair("src/main/jni/react/fabric", "react/fabric/") ), new PrefabPreprocessingEntry( "react_render_mapbuffer", new Pair("../ReactCommon/react/renderer/mapbuffer/", "react/renderer/mapbuffer/") ), new PrefabPreprocessingEntry( "yoga", [ new Pair("../ReactCommon/yoga/", ""), new Pair("src/main/jni/first-party/yogajni/jni", "") ] ), new PrefabPreprocessingEntry( "folly_runtime", [ new Pair(new File(buildDir, "third-party-ndk/fmt/include/").absolutePath, ""), new Pair(new File(buildDir, "third-party-ndk/folly/").absolutePath, ""), new Pair(new File(buildDir, "third-party-ndk/boost/boost_1_83_0/").absolutePath, ""), new Pair(new File(buildDir, "third-party-ndk/double-conversion/").absolutePath, ""), ] ), new PrefabPreprocessingEntry( "react_nativemodule_core", [ new Pair(new File(buildDir, "third-party-ndk/boost/boost_1_83_0/").absolutePath, ""), new Pair(new File(buildDir, "third-party-ndk/double-conversion/").absolutePath, ""), new Pair(new File(buildDir, "third-party-ndk/fmt/include/").absolutePath, ""), new Pair(new File(buildDir, "third-party-ndk/folly/").absolutePath, ""), new Pair(new File(buildDir, "third-party-ndk/glog/exported/").absolutePath, ""), new Pair("../ReactCommon/butter/", "butter/"), new Pair("../ReactCommon/callinvoker/", ""), new Pair("../ReactCommon/cxxreact/", "cxxreact/"), new Pair("../ReactCommon/react/bridging/", "react/bridging/"), new Pair("../ReactCommon/react/config/", "react/config/"), new Pair("../ReactCommon/react/nativemodule/core/", ""), new Pair("../ReactCommon/react/nativemodule/core/platform/android/", ""), new Pair("../ReactCommon/react/renderer/componentregistry/", "react/renderer/componentregistry/"), new Pair("../ReactCommon/react/renderer/components/root/", "react/renderer/components/root/"), new Pair("../ReactCommon/react/renderer/core/", "react/renderer/core/"), new Pair("../ReactCommon/react/renderer/debug/", "react/renderer/debug/"), new Pair("../ReactCommon/react/renderer/leakchecker/", "react/renderer/leakchecker/"), new Pair("../ReactCommon/react/renderer/mapbuffer/", "react/renderer/mapbuffer/"), new Pair("../ReactCommon/react/renderer/mounting/", "react/renderer/mounting/"), new Pair("../ReactCommon/react/renderer/runtimescheduler/", "react/renderer/runtimescheduler/"), new Pair("../ReactCommon/react/renderer/scheduler/", "react/renderer/scheduler/"), new Pair("../ReactCommon/react/renderer/telemetry/", "react/renderer/telemetry/"), new Pair("../ReactCommon/react/renderer/uimanager/", "react/renderer/uimanager/"), new Pair("../ReactCommon/react/debug/", "react/debug/"), new Pair("../ReactCommon/react/utils/", "react/utils/"), new Pair("src/main/jni/react/jni", "react/jni/"), ] ), new PrefabPreprocessingEntry( "react_utils", new Pair("../ReactCommon/react/utils/", "react/utils/"), ), new PrefabPreprocessingEntry( "react_render_imagemanager", [ new Pair("../ReactCommon/react/renderer/imagemanager/", "react/renderer/imagemanager/"), new Pair("../ReactCommon/react/renderer/imagemanager/platform/cxx/", ""), ] ), new PrefabPreprocessingEntry( "rrc_image", new Pair("../ReactCommon/react/renderer/components/image/", "react/renderer/components/image/") ), // These prefab targets are used by Expo & Reanimated new PrefabPreprocessingEntry( "hermes_executor", // "hermes_executor" is statically linking against "hermes_executor_common" // and "hermes_inspector_modern". Here we expose only the headers that we know are needed. new Pair("../ReactCommon/hermes/inspector-modern/", "hermes/inspector-modern/") ), new PrefabPreprocessingEntry( "jscexecutor", // "jscexecutor" is statically linking against "jscruntime" // Here we expose only the headers that we know are needed. new Pair("../ReactCommon/jsc/", "jsc/") ), new PrefabPreprocessingEntry( "react_render_uimanager", new Pair("../ReactCommon/react/renderer/uimanager/", "react/renderer/uimanager/"), ), new PrefabPreprocessingEntry( "react_render_scheduler", new Pair("../ReactCommon/react/renderer/scheduler/", "react/renderer/scheduler/"), ), new PrefabPreprocessingEntry( "react_render_mounting", new Pair("../ReactCommon/react/renderer/mounting/", "react/renderer/mounting/"), ), new PrefabPreprocessingEntry( "reactnativejni", [ new Pair("src/main/jni/react/jni", "react/jni/"), new Pair("../ReactCommon/cxxreact/", "cxxreact/"), ] ), new PrefabPreprocessingEntry( "jsinspector", new Pair("../ReactCommon/jsinspector-modern/", "jsinspector-modern/"), ), ] ) it.outputDir.set(prefabHeadersDir) } task createNativeDepsDirectories { downloadsDir.mkdirs() thirdPartyNdkDir.mkdirs() } task downloadBoost(dependsOn: createNativeDepsDirectories, type: Download) { src("https://archives.boost.io/release/${BOOST_VERSION.replace("_", ".")}/source/boost_${BOOST_VERSION}.tar.gz") onlyIfModified(true) overwrite(false) retries(5) dest(new File(downloadsDir, "boost_${BOOST_VERSION}.tar.gz")) } final def prepareBoost = tasks.register("prepareBoost", PrepareBoostTask) { it.dependsOn(boostPath ? [] : [downloadBoost]) it.boostPath.setFrom(boostPath ?: tarTree(downloadBoost.dest)) it.boostVersion.set(BOOST_VERSION) it.outputDir.set(new File(thirdPartyNdkDir, "boost")) } task downloadDoubleConversion(dependsOn: createNativeDepsDirectories, type: Download) { src("https://github.com/google/double-conversion/archive/v${DOUBLE_CONVERSION_VERSION}.tar.gz") onlyIfModified(true) overwrite(false) retries(5) dest(new File(downloadsDir, "double-conversion-${DOUBLE_CONVERSION_VERSION}.tar.gz")) } task prepareDoubleConversion(dependsOn: dependenciesPath ? [] : [downloadDoubleConversion], type: Copy) { from(dependenciesPath ?: tarTree(downloadDoubleConversion.dest)) from("src/main/jni/third-party/double-conversion/") include("double-conversion-${DOUBLE_CONVERSION_VERSION}/src/**/*", "CMakeLists.txt") filesMatching("*/src/**/*", { fname -> fname.path = "double-conversion/${fname.name}" }) includeEmptyDirs = false into("$thirdPartyNdkDir/double-conversion") } task downloadFolly(dependsOn: createNativeDepsDirectories, type: Download) { src("https://github.com/facebook/folly/archive/v${FOLLY_VERSION}.tar.gz") onlyIfModified(true) overwrite(false) retries(5) dest(new File(downloadsDir, "folly-${FOLLY_VERSION}.tar.gz")) } task prepareFolly(dependsOn: dependenciesPath ? [] : [downloadFolly], type: Copy) { from(dependenciesPath ?: tarTree(downloadFolly.dest)) from("src/main/jni/third-party/folly/") include("folly-${FOLLY_VERSION}/folly/**/*", "CMakeLists.txt") eachFile { fname -> fname.path = (fname.path - "folly-${FOLLY_VERSION}/") } includeEmptyDirs = false into("$thirdPartyNdkDir/folly") } task downloadFmt(dependsOn: createNativeDepsDirectories, type: Download) { src("https://github.com/fmtlib/fmt/archive/${FMT_VERSION}.tar.gz") onlyIfModified(true) overwrite(false) retries(5) dest(new File(downloadsDir, "fmt-${FMT_VERSION}.tar.gz")) } task prepareFmt(dependsOn: dependenciesPath ? [] : [downloadFmt], type: Copy) { from(dependenciesPath ?: tarTree(downloadFmt.dest)) from("src/main/jni/third-party/fmt/") include("fmt-${FMT_VERSION}/src/**/*", "fmt-${FMT_VERSION}/include/**/*", "CMakeLists.txt") eachFile { fname -> fname.path = (fname.path - "fmt-${FMT_VERSION}/") } includeEmptyDirs = false into("$thirdPartyNdkDir/fmt") } task downloadLibevent(dependsOn: createNativeDepsDirectories, type: Download) { src("https://github.com/libevent/libevent/releases/download/release-${LIBEVENT_VERSION}-stable/libevent-${LIBEVENT_VERSION}-stable.tar.gz") onlyIfModified(true) overwrite(false) retries(5) dest(new File(downloadsDir, "libevent-${LIBEVENT_VERSION}.tar.gz")) } final def prepareLibevent = tasks.register("prepareLibevent", PrepareLibeventTask) { it.dependsOn(dependenciesPath ? [] : [downloadLibevent]) it.libeventPath.setFrom(dependenciesPath ?: tarTree(downloadLibevent.dest)) it.libeventVersion.set(LIBEVENT_VERSION) it.outputDir.set(new File(thirdPartyNdkDir, "libevent")) } task downloadGlog(dependsOn: createNativeDepsDirectories, type: Download) { src("https://github.com/google/glog/archive/v${GLOG_VERSION}.tar.gz") onlyIfModified(true) overwrite(false) retries(5) dest(new File(downloadsDir, "glog-${GLOG_VERSION}.tar.gz")) } task downloadGtest(dependsOn: createNativeDepsDirectories, type: Download) { src("https://github.com/google/googletest/archive/refs/tags/release-${GTEST_VERSION}.tar.gz") onlyIfModified(true) overwrite(false) retries(5) dest(new File(downloadsDir, "gtest.tar.gz")) } task prepareGtest(dependsOn: dependenciesPath ? [] : [downloadGtest], type: Copy) { from(dependenciesPath ?: tarTree(downloadGtest.dest)) eachFile { fname -> { fname.path = (fname.path - "googletest-release-${GTEST_VERSION}/") } } into(new File(thirdPartyNdkDir,"googletest")) } // Prepare glog sources to be compiled, this task will perform steps that normally should've been // executed by automake. This way we can avoid dependencies on make/automake final def prepareGlog = tasks.register("prepareGlog", PrepareGlogTask) { it.dependsOn(dependenciesPath ? [] : [downloadGlog]) it.glogPath.setFrom(dependenciesPath ?: tarTree(downloadGlog.dest)) it.glogVersion.set(GLOG_VERSION) it.outputDir.set(new File(thirdPartyNdkDir, "glog")) } // Create Android native library module based on jsc from npm tasks.register('prepareJSC', PrepareJSCTask) { it.jscPackagePath.set(findNodeModulePath(projectDir, "jsc-android")) it.outputDir = project.layout.buildDirectory.dir("third-party-ndk/jsc") } task prepareKotlinBuildScriptModel { // This task is run when Gradle Sync is running. // We create it here so we can let it depend on preBuild inside the android{} } // As ReactAndroid builds from source, the codegen needs to be built before it can be invoked. // This is not the case for users of React Native, as we ship a compiled version of the codegen. final def buildCodegenCLITask = tasks.register('buildCodegenCLI', BuildCodegenCLITask) { it.codegenDir.set(file("$rootDir/node_modules/@react-native/codegen")) it.bashWindowsHome.set(project.findProperty("react.internal.windowsBashPath")) it.onlyIf { // For build from source scenario, we don't need to build the codegen at all. rootProject.name != "react-native-build-from-source" } } /** * Finds the path of the installed npm package with the given name using Node's * module resolution algorithm, which searches "node_modules" directories up to * the file system root. This handles various cases, including: * * - Working in the open-source RN repo: * Gradle: /path/to/react-native/ReactAndroid * Node module: /path/to/react-native/node_modules/[package] * * - Installing RN as a dependency of an app and searching for hoisted * dependencies: * Gradle: /path/to/app/node_modules/react-native/ReactAndroid * Node module: /path/to/app/node_modules/[package] * * - Working in a larger repo (e.g., Facebook) that contains RN: * Gradle: /path/to/repo/path/to/react-native/ReactAndroid * Node module: /path/to/repo/node_modules/[package] * * The search begins at the given base directory (a File object). The returned * path is a string. */ def findNodeModulePath(baseDir, packageName) { def basePath = baseDir.toPath().normalize() // Node's module resolution algorithm searches up to the root directory, // after which the base path will be null while (basePath) { def candidatePath = Paths.get(basePath.toString(), "node_modules", packageName) if (candidatePath.toFile().exists()) { return candidatePath.toString() } basePath = basePath.getParent() } return null } def reactNativeDevServerPort() { def value = project.getProperties().get("reactNativeDevServerPort") return value != null ? value : "8081" } def reactNativeInspectorProxyPort() { def value = project.getProperties().get("reactNativeInspectorProxyPort") return value != null ? value : reactNativeDevServerPort() } def reactNativeArchitectures() { def value = project.getProperties().get("reactNativeArchitectures") return value ? value.split(",") : ["armeabi-v7a", "x86", "x86_64", "arm64-v8a"] } def enableWarningsAsErrors() { def value = project.getProperties().get("enableWarningsAsErrors") return value != null ? value : false } task packageReactNdkLibsForBuck(type: Copy) { dependsOn("mergeDebugNativeLibs") // Shared libraries (.so) are copied from the merged_native_libs folder instead from("$buildDir/intermediates/merged_native_libs/debug/out/lib/") exclude("**/libjsc.so") exclude("**/libhermes.so") into("src/main/jni/prebuilt/lib") } task installArchives { dependsOn("publishAllPublicationsToNpmRepository") } repositories { // Normally RNGP will set repositories for all modules, // but when consumed from source, we need to re-declare // those repositories as there is no app module there. mavenCentral() google() } android { compileSdk libs.versions.compileSdk.get().toInteger() buildToolsVersion = libs.versions.buildTools.get() namespace "com.facebook.react" // Used to override the NDK path/version on internal CI or by allowing // users to customize the NDK path/version from their root project (e.g. for Apple Silicon support) if (rootProject.hasProperty("ndkPath")) { ndkPath rootProject.ext.ndkPath } if (rootProject.hasProperty("ndkVersion")) { ndkVersion rootProject.ext.ndkVersion } compileOptions { sourceCompatibility = JavaVersion.VERSION_17 targetCompatibility = JavaVersion.VERSION_17 } kotlinOptions { // Using '-Xjvm-default=all' to generate default java methods for interfaces freeCompilerArgs = ['-Xjvm-default=all'] // Using -PenableWarningsAsErrors=true prop to enable allWarningsAsErrors kotlinOptions.allWarningsAsErrors = enableWarningsAsErrors() } defaultConfig { minSdk = libs.versions.minSdk.get().toInteger() targetSdk = libs.versions.targetSdk.get().toInteger() versionCode(1) versionName("1.0") consumerProguardFiles("proguard-rules.pro") buildConfigField("boolean", "IS_INTERNAL_BUILD", "false") buildConfigField("int", "EXOPACKAGE_FLAGS", "0") resValue "integer", "react_native_dev_server_port", reactNativeDevServerPort() resValue "integer", "react_native_inspector_proxy_port", reactNativeInspectorProxyPort() testApplicationId("com.facebook.react.tests.gradle") testInstrumentationRunner("androidx.test.runner.AndroidJUnitRunner") externalNativeBuild { cmake { arguments "-DREACT_COMMON_DIR=${reactNativeRootDir}/ReactCommon", "-DREACT_ANDROID_DIR=$projectDir", "-DREACT_BUILD_DIR=$buildDir", "-DANDROID_STL=c++_shared", "-DANDROID_TOOLCHAIN=clang", "-DANDROID_PLATFORM=android-21", // Due to https://github.com/android/ndk/issues/1693 we're losing Android // specific compilation flags. This can be removed once we moved to NDK 25/26 "-DANDROID_USE_LEGACY_TOOLCHAIN_FILE=ON" targets "jsijniprofiler", "reactnativeblob", "reactperfloggerjni", "bridgeless", "rninstance", "hermesinstancejni", "uimanagerjni", "jscinstance", // prefab targets "reactnativejni", "react_render_debug", "turbomodulejsijni", "runtimeexecutor", "react_codegen_rncore", "react_debug", "react_utils", "react_render_componentregistry", "react_newarchdefaults", "react_render_animations", "react_render_core", "react_render_graphics", "rrc_image", "rrc_root", "rrc_view", "rrc_legacyviewmanagerinterop", "jsi", "glog", "fabricjni", "react_render_mapbuffer", "yoga", "folly_runtime", "react_nativemodule_core", "react_render_imagemanager", "react_render_uimanager", "react_render_scheduler", "react_render_mounting", "hermes_executor", "jscexecutor", "jsinspector" } } ndk { abiFilters(*reactNativeArchitectures()) } } externalNativeBuild { cmake { version cmakeVersion path "src/main/jni/CMakeLists.txt" } } buildTypes { debug { externalNativeBuild { cmake { // We want to build Gtest suite only for the debug variant. targets "reactnative_unittest" } } } } preBuild.dependsOn( buildCodegenCLITask, generateCodegenArtifactsFromSchema, prepareBoost, prepareDoubleConversion, prepareFmt, prepareFolly, prepareGlog, prepareGtest, prepareJSC, prepareLibevent, preparePrefab ) generateCodegenSchemaFromJavaScript.dependsOn(buildCodegenCLITask) prepareKotlinBuildScriptModel.dependsOn( preBuild, ":packages:react-native:ReactAndroid:hermes-engine:preBuild", ) sourceSets.main { res.srcDirs = ["src/main/res/devsupport", "src/main/res/shell", "src/main/res/views/modal", "src/main/res/views/uimanager"] java { srcDirs = ["src/main/java", "src/main/libraries/soloader/java", "src/main/jni/first-party/fb/jni/java"] exclude("com/facebook/react/processing") exclude("com/facebook/react/module/processing") } } lintOptions { abortOnError(false) } packagingOptions { exclude("META-INF/NOTICE") exclude("META-INF/LICENSE") // We intentionally don't want to bundle any JS Runtime inside the Android AAR // we produce. The reason behind this is that we want to allow users to pick the // JS engine by specifying a dependency on either `hermes-engine` or `android-jsc` // that will include the necessary .so files to load. exclude("**/libhermes.so") exclude("**/libjsc.so") } buildFeatures { prefab true prefabPublishing !skipPrefabPublishing buildConfig true } prefab { react_render_debug { headers(new File(prefabHeadersDir, "react_render_debug").absolutePath) } turbomodulejsijni { headers(new File(prefabHeadersDir, "turbomodulejsijni").absolutePath) } runtimeexecutor { headers(new File(prefabHeadersDir, "runtimeexecutor").absolutePath) } react_codegen_rncore { headers(new File(prefabHeadersDir, "react_codegen_rncore").absolutePath) } react_debug { headers(new File(prefabHeadersDir, "react_debug").absolutePath) } react_utils { headers(new File(prefabHeadersDir, "react_utils").absolutePath) } react_render_componentregistry { headers(new File(prefabHeadersDir, "react_render_componentregistry").absolutePath) } react_newarchdefaults { headers(new File(prefabHeadersDir, "react_newarchdefaults").absolutePath) } react_render_animations { headers(new File(prefabHeadersDir, "react_render_animations").absolutePath) } react_render_core { headers(new File(prefabHeadersDir, "react_render_core").absolutePath) } react_render_graphics { headers(new File(prefabHeadersDir, "react_render_graphics").absolutePath) } rrc_image { headers(new File(prefabHeadersDir, "rrc_image").absolutePath) } rrc_root { headers(new File(prefabHeadersDir, "rrc_root").absolutePath) } rrc_view { headers(new File(prefabHeadersDir, "rrc_view").absolutePath) } rrc_legacyviewmanagerinterop { headers(new File(prefabHeadersDir, "rrc_legacyviewmanagerinterop").absolutePath) } jsi { headers(new File(prefabHeadersDir, "jsi").absolutePath) } glog { headers(new File(prefabHeadersDir, "glog").absolutePath) } fabricjni { headers(new File(prefabHeadersDir, "fabricjni").absolutePath) } react_render_mapbuffer { headers(new File(prefabHeadersDir, "react_render_mapbuffer").absolutePath) } yoga { headers(new File(prefabHeadersDir, "yoga").absolutePath) } folly_runtime { headers(new File(prefabHeadersDir, "folly_runtime").absolutePath) } react_nativemodule_core { headers(new File(prefabHeadersDir, "react_nativemodule_core").absolutePath) } react_render_imagemanager { headers(new File(prefabHeadersDir, "react_render_imagemanager").absolutePath) } react_render_uimanager { headers(new File(prefabHeadersDir, "react_render_uimanager").absolutePath) } react_render_scheduler { headers(new File(prefabHeadersDir, "react_render_scheduler").absolutePath) } react_render_mounting { headers(new File(prefabHeadersDir, "react_render_mounting").absolutePath) } reactnativejni { headers(new File(prefabHeadersDir, "reactnativejni").absolutePath) } hermes_executor { headers(new File(prefabHeadersDir, "hermes_executor").absolutePath) } jscexecutor { headers(new File(prefabHeadersDir, "jscexecutor").absolutePath) } jsinspector { headers(new File(prefabHeadersDir, "jsinspector").absolutePath) } } publishing { multipleVariants { withSourcesJar() includeBuildTypeValues('debug', 'release') } } testOptions { unitTests { includeAndroidResources = true } } } dependencies { api(libs.androidx.appcompat) api(libs.androidx.appcompat.resources) api(libs.androidx.autofill) api(libs.androidx.swiperefreshlayout) api(libs.androidx.tracing) api(libs.fbjni) api(libs.fresco) api(libs.fresco.middleware) api(libs.fresco.imagepipeline.okhttp3) api(libs.fresco.ui.common) api(libs.infer.annotation) api(libs.soloader) api(libs.yoga.proguard.annotations) api(libs.jsr305) api(libs.okhttp3.urlconnection) api(libs.okhttp3) api(libs.okio) api(libs.javax.inject) // It's up to the consumer to decide if hermes should be included or not. // Therefore hermes-engine is a compileOnly dependency. compileOnly(project(":packages:react-native:ReactAndroid:hermes-engine")) testImplementation(libs.junit) testImplementation(libs.assertj) testImplementation(libs.mockito) testImplementation(libs.robolectric) testImplementation(libs.thoughtworks) androidTestImplementation(libs.androidx.test.runner) androidTestImplementation(libs.androidx.test.rules) androidTestImplementation(libs.mockito) } react { // TODO: The library name is chosen for parity with Fabric components & iOS // This should be changed to a more generic name, e.g. `ReactCoreSpec`. libraryName = "rncore" jsRootDir = file("../Libraries") } // For build from source, we need to override the privateReact extension. // This is neeeded as the build-from-source won't have a com.android.application // module to apply the plugin to, so it's codegenDir and reactNativeDir won't be evaluated. if (rootProject.name == "react-native-build-from-source") { privateReact { codegenDir = file("$rootDir/../@react-native/codegen") reactNativeDir = file("$rootDir") } } kotlin { jvmToolchain(17) } apply plugin: "org.jetbrains.kotlin.android" /* Publishing Configuration */ apply from: "./publish.gradle" // We need to override the artifact ID as this project is called `ReactAndroid` but // the maven coordinates are on `react-android`. // Please note that the original coordinates, `react-native`, have been voided // as they caused https://github.com/facebook/react-native/issues/35210 publishing { publications { getByName("release") { artifactId 'react-android' } } }