Skip to content

Commit

Permalink
feat: add support for react-native 0.71
Browse files Browse the repository at this point in the history
When upgrading to this version, please update your `build.gradle` to
using `getReactNativeDependencies()`. This will reduce breakages when
moving to 0.71 and beyond:

```diff
diff --git a/example/android/build.gradle b/example/android/build.gradle
index 984a681..29ef8ce 100644
--- a/example/android/build.gradle
+++ b/example/android/build.gradle
@@ -1,7 +1,6 @@
 buildscript {
     def androidTestAppDir = "../node_modules/react-native-test-app/android"
     apply(from: "${androidTestAppDir}/dependencies.gradle")
-    apply(from: "${androidTestAppDir}/test-app-util.gradle")

     repositories {
         mavenCentral()
@@ -9,12 +8,8 @@ buildscript {
     }

     dependencies {
-        classpath("com.android.tools.build:gradle:${androidPluginVersion}")
-
-        def isNightly = getPackageVersionNumber("react-native", rootDir) == 0
-        if (isNightly || isNewArchitectureEnabled(project)) {
-            classpath("com.facebook.react:react-native-gradle-plugin")
-            classpath("de.undercouch:gradle-download-task:5.3.0")
+        getReactNativeDependencies().each { dependency ->
+            classpath(dependency)
         }
     }
 }
```
  • Loading branch information
tido64 committed Jan 2, 2023
1 parent 4d94242 commit 5469a1d
Show file tree
Hide file tree
Showing 18 changed files with 208 additions and 157 deletions.
27 changes: 27 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -191,3 +191,30 @@ To avoid issues, remember to clear out `node_modules` folders before you run
yarn clean
yarn
```

## Adding Support For New React Native Versions

First, create a new issue using the "New `react-native` version" template,
update the title, and fill out all the required fields.

When opening a PR, link to the issue that was created, and use the table below
to paste in screenshots as you test the different configurations:

```markdown
| Configuration | Android | iOS | macOS | Windows |
| :-------------- | :-----: | :--: | :---: | :-----: |
| JSC | TODO | TODO | TODO | TODO |
| Hermes | TODO | TODO | TODO | TODO |
| Fabric | TODO | TODO | TODO | TODO |
| Fabric + Hermes | TODO | TODO | TODO | TODO |
```

You can use the test script to both test and capture screenshots. For instance,
to test 0.71, run:

```sh
scripts/test-matrix.sh 0.71
```

At the minimum, we should be testing the lowest supported version (0.64 at the
time of writing) in addition to the new version.
173 changes: 92 additions & 81 deletions android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,22 @@ plugins {
id("org.jetbrains.kotlin.kapt") version "${kotlinVersion}"
}

def enableNewArchitecture = isNewArchitectureEnabled(project)
def reactNativeVersion = getPackageVersionNumber("react-native", rootDir)
def reactNativePath = file(findNodeModulesPath("react-native", rootDir))

if (reactNativeVersion == 0 || enableNewArchitecture) {
if (autodetectReactNativeVersion || enableNewArchitecture) {
apply(plugin: "com.facebook.react")

if (enableNewArchitecture) {
react {
codegenDir = file(findNodeModulesPath("react-native-codegen", reactNativePath))
reactNativeDir = reactNativePath
react {
reactNativeDir = reactNativePath
codegenDir = file(findNodeModulesPath("react-native-codegen", reactNativePath))
}

// We don't want the React plugin to bundle.
tasks.whenTaskAdded { task ->
// The task name can be found in `react-native-gradle-plugin`:
// https://github.com/facebook/react-native/blob/0.71-stable/packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/TaskConfiguration.kt#L54
if (task.name.startsWith("createBundle") && task.name.endsWith("JsAndAssets")) {
task.enabled = false
}
}
}
Expand Down Expand Up @@ -67,6 +72,7 @@ project.ext.react = [
appName : getAppName(),
applicationId : getApplicationId(),
architectures : getArchitectures(),
bundleInRelease : false,
enableCamera : !getSingleAppMode(),
enableFabric : isFabricEnabled(project),
enableFlipper : getFlipperVersion(rootDir),
Expand All @@ -85,6 +91,12 @@ android {
ndkVersion project.ext.ndkVersion
}

if (usePrefabs) {
buildFeatures {
prefab true
}
}

// TODO: Remove this block when minSdkVersion >= 24. See
// https://stackoverflow.com/q/53402639 for details.
if (reactNativeVersion > 0 && reactNativeVersion < 6900) {
Expand Down Expand Up @@ -128,7 +140,7 @@ android {

testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"

if (project.ext.react.enableNewArchitecture) {
if (enableNewArchitecture) {
externalNativeBuild {
if (reactNativeVersion > 0 && reactNativeVersion < 7000) {
ndkBuild {
Expand Down Expand Up @@ -171,7 +183,7 @@ android {
}
}

if (project.ext.react.enableNewArchitecture) {
if (enableNewArchitecture) {
externalNativeBuild {
if (reactNativeVersion > 0 && reactNativeVersion < 7000) {
ndkBuild {
Expand All @@ -184,50 +196,52 @@ android {
}
}

def reactAndroidProjectDir = project(":ReactAndroid").projectDir
def packageReactNdkDebugLibs = tasks.register("packageReactNdkDebugLibs", Copy) {
dependsOn(":ReactAndroid:packageReactNdkDebugLibsForBuck")
from("${reactAndroidProjectDir}/src/main/jni/prebuilt/lib")
into("${buildDir}/react-ndk/exported")
}
def packageReactNdkReleaseLibs = tasks.register("packageReactNdkReleaseLibs", Copy) {
dependsOn(":ReactAndroid:packageReactNdkReleaseLibsForBuck")
from("${reactAndroidProjectDir}/src/main/jni/prebuilt/lib")
into("${buildDir}/react-ndk/exported")
}

afterEvaluate {
preDebugBuild.dependsOn(packageReactNdkDebugLibs)
preReleaseBuild.dependsOn(packageReactNdkReleaseLibs)
if (!usePrefabs) {
def reactAndroidProjectDir = project(":ReactAndroid").projectDir
def packageReactNdkDebugLibs = tasks.register("packageReactNdkDebugLibs", Copy) {
dependsOn(":ReactAndroid:packageReactNdkDebugLibsForBuck")
from("${reactAndroidProjectDir}/src/main/jni/prebuilt/lib")
into("${buildDir}/react-ndk/exported")
}
def packageReactNdkReleaseLibs = tasks.register("packageReactNdkReleaseLibs", Copy) {
dependsOn(":ReactAndroid:packageReactNdkReleaseLibsForBuck")
from("${reactAndroidProjectDir}/src/main/jni/prebuilt/lib")
into("${buildDir}/react-ndk/exported")
}

if (reactNativeVersion > 0 && reactNativeVersion < 7000) {
// Due to a bug in AGP, we have to explicitly set a dependency
// between configureNdkBuild* tasks and the preBuild tasks. This can
// be removed once this issue is resolved:
// https://issuetracker.google.com/issues/207403732
configureNdkBuildRelease.dependsOn(preReleaseBuild)
configureNdkBuildDebug.dependsOn(preDebugBuild)
project.ext.react.architectures.each { architecture ->
tasks.findByName("configureNdkBuildDebug[${architecture}]")?.configure {
dependsOn("preDebugBuild")
}
tasks.findByName("configureNdkBuildRelease[${architecture}]")?.configure {
dependsOn("preReleaseBuild")
}
}
} else if (reactNativeVersion > 0 && reactNativeVersion < 7100) {
// Due to a bug in AGP, we have to explicitly set a dependency
// between configureCMakeDebug* tasks and the preBuild tasks. This can
// be removed once this issue is resolved:
// https://issuetracker.google.com/issues/207403732
configureCMakeDebug.dependsOn(preDebugBuild)
configureCMakeRelWithDebInfo.dependsOn(preReleaseBuild)
project.ext.react.architectures.each { architecture ->
tasks.findByName("configureCMakeDebug[${architecture}]")?.configure {
dependsOn("preDebugBuild")
afterEvaluate {
preDebugBuild.dependsOn(packageReactNdkDebugLibs)
preReleaseBuild.dependsOn(packageReactNdkReleaseLibs)

if (reactNativeVersion < 7000) {
// Due to a bug in AGP, we have to explicitly set a dependency
// between configureNdkBuild* tasks and the preBuild tasks. This can
// be removed once this issue is resolved:
// https://issuetracker.google.com/issues/207403732
configureNdkBuildRelease.dependsOn(preReleaseBuild)
configureNdkBuildDebug.dependsOn(preDebugBuild)
project.ext.react.architectures.each { architecture ->
tasks.findByName("configureNdkBuildDebug[${architecture}]")?.configure {
dependsOn("preDebugBuild")
}
tasks.findByName("configureNdkBuildRelease[${architecture}]")?.configure {
dependsOn("preReleaseBuild")
}
}
tasks.findByName("configureCMakeRelWithDebInfo[${architecture}]")?.configure {
dependsOn("preReleaseBuild")
} else {
// Due to a bug in AGP, we have to explicitly set a dependency
// between configureCMakeDebug* tasks and the preBuild tasks. This can
// be removed once this issue is resolved:
// https://issuetracker.google.com/issues/207403732
configureCMakeDebug.dependsOn(preDebugBuild)
configureCMakeRelWithDebInfo.dependsOn(preReleaseBuild)
project.ext.react.architectures.each { architecture ->
tasks.findByName("configureCMakeDebug[${architecture}]")?.configure {
dependsOn("preDebugBuild")
}
tasks.findByName("configureCMakeRelWithDebInfo[${architecture}]")?.configure {
dependsOn("preReleaseBuild")
}
}
}
}
Expand All @@ -239,12 +253,7 @@ android {
}
}

// Nightlies are downloaded from Sonatype and cannot be found under
// `node_modules`. Instead, they can be found in Gradle's cache folder,
// `.gradle/caches/modules-2/files-2.1/com.facebook.react/react-native`.
// For now, we will simply disable this step as we only need to verify
// that things build.
if (reactNativeVersion > 0 && reactNativeVersion < 7100) {
if (!usePrefabs) {
def version = getPackageVersion("react-native", rootDir)
def allAar = file("${reactNativePath}/android/com/facebook/react/react-native/${version}/react-native-${version}.aar")

Expand Down Expand Up @@ -320,7 +329,7 @@ android {
}

// TODO: Remove this block when we drop support for 0.65.
if (project.ext.react.enableNewArchitecture) {
if (enableNewArchitecture) {
main.java.srcDirs += "src/turbomodule/java"
} else {
main.java.srcDirs += "src/no-turbomodule/java"
Expand Down Expand Up @@ -349,8 +358,8 @@ dependencies {
implementation project(":support")

if (project.ext.react.enableHermes) {
if (reactNativeVersion == 0) {
implementation("com.facebook.react:hermes-engine")
if (autodetectReactNativeVersion) {
implementation("com.facebook.react:hermes-android")
} else if (reactNativeVersion >= 6900) {
implementation("com.facebook.react:hermes-engine:+") {
exclude(group: "com.facebook.fbjni")
Expand All @@ -370,10 +379,12 @@ dependencies {
}
}

if (project.ext.react.enableNewArchitecture) {
if (autodetectReactNativeVersion) {
implementation("com.facebook.react:react-android")
} else if (enableNewArchitecture) {
// This is only valid for 0.68 - 0.70. From 0.71 and on, we should be
// using prefabs.
implementation project(":ReactAndroid")
} else if (reactNativeVersion == 0 || reactNativeVersion >= 7100) {
implementation("com.facebook.react:react-native")
} else {
def version = getPackageVersion("react-native", rootDir)
implementation("com.facebook.react:react-native:${version}")
Expand Down Expand Up @@ -425,25 +436,25 @@ dependencies {
}
}

if (project.ext.react.enableNewArchitecture) {
configurations.all {
resolutionStrategy.dependencySubstitution {
substitute(module("com.facebook.react:react-native"))
.using(project(":ReactAndroid"))
.because("On New Architecture, we are building React Native from source")
substitute(module("com.facebook.react:hermes-engine"))
.using(project(":ReactAndroid:hermes-engine"))
.because("On New Architecture, we are building Hermes from source")
}
}
} else if (reactNativeVersion > 0 && reactNativeVersion < 7100) {
if (!usePrefabs) {
configurations.all {
resolutionStrategy {
// Force version here otherwise Gradle will pick up a newer version:
// https://github.com/facebook/react-native/issues/35210
def version = getPackageVersion("react-native", rootDir)
force("com.facebook.react:react-native:${version}")
force("com.facebook.react:hermes-engine:${version}")
if (enableNewArchitecture) {
resolutionStrategy.dependencySubstitution {
substitute(module("com.facebook.react:react-native"))
.using(project(":ReactAndroid"))
.because("On New Architecture, we are building React Native from source")
substitute(module("com.facebook.react:hermes-engine"))
.using(project(":ReactAndroid:hermes-engine"))
.because("On New Architecture, we are building Hermes from source")
}
} else {
resolutionStrategy {
// Force version here otherwise Gradle will pick up a newer version:
// https://github.com/facebook/react-native/issues/35210
def version = getPackageVersion("react-native", rootDir)
force("com.facebook.react:react-native:${version}")
force("com.facebook.react:hermes-engine:${version}")
}
}
}
}
Expand Down
16 changes: 7 additions & 9 deletions android/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.microsoft.reacttestapp">

package="com.microsoft.reacttestapp"
>
<uses-feature android:name="android.hardware.camera.any" />

<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
Expand All @@ -18,13 +19,11 @@
android:supportsRtl="true"
android:theme="@style/AppTheme"
android:usesCleartextTraffic="true"
tools:targetApi="m">

tools:targetApi="m"
>
<activity android:name="com.facebook.react.devsupport.DevSettingsActivity" />

<activity
android:name="com.microsoft.reacttestapp.MainActivity"
android:exported="true">
<activity android:name="com.microsoft.reacttestapp.MainActivity" android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
Expand All @@ -33,5 +32,4 @@

<activity android:name="com.microsoft.reacttestapp.component.ComponentActivity" />
</application>

</manifest>
32 changes: 20 additions & 12 deletions android/app/src/main/jni/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12,23 +12,31 @@ set(REACTTESTAPP_SOURCE_FILES
AppRegistry.h
)

# Suppress 'Manually-specified variables were not used by the project' warning
set(UNUSED_VARIABLES ${REACT_COMMON_DIR} ${REACT_JNILIBS_DIR})

if(DEFINED REACT_ANDROID_DIR)
# New architecture
include(${REACT_ANDROID_DIR}/cmake-utils/ReactNative-application.cmake)
target_sources(${THIS_LIBRARY} PRIVATE ${REACTTESTAPP_SOURCE_FILES})
else()
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
set(BUILD_VARIANT debug)
else()
set(BUILD_VARIANT release)
endif()
set(JSI_LIBRARY ${REACT_JNILIBS_DIR}/${BUILD_VARIANT}/jni/${ANDROID_ABI}/libjsi.so)

if(EXISTS ${JSI_LIBRARY})
add_library(${THIS_LIBRARY} SHARED ${REACTTESTAPP_SOURCE_FILES})
target_include_directories(${THIS_LIBRARY} PRIVATE ${REACT_COMMON_DIR}/jsi)
target_link_libraries(${THIS_LIBRARY} ${JSI_LIBRARY})
# On old architecture, use prefabs if they can be found. Otherwise, look for
# the `libjsi.so` we extracted from the `.aar`.
add_library(${THIS_LIBRARY} SHARED ${REACTTESTAPP_SOURCE_FILES})
find_package(ReactAndroid CONFIG)
if(ReactAndroid_FOUND)
target_link_libraries(${THIS_LIBRARY} ReactAndroid::jsi)
else()
add_library(${THIS_LIBRARY} SHARED ${REACTTESTAPP_SOURCE_FILES})
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
set(BUILD_VARIANT debug)
else()
set(BUILD_VARIANT release)
endif()
set(JSI_LIBRARY ${REACT_JNILIBS_DIR}/${BUILD_VARIANT}/jni/${ANDROID_ABI}/libjsi.so)
if(EXISTS ${JSI_LIBRARY})
target_include_directories(${THIS_LIBRARY} PRIVATE ${REACT_COMMON_DIR}/jsi)
target_link_libraries(${THIS_LIBRARY} ${JSI_LIBRARY})
endif()
endif()
endif()

Expand Down
7 changes: 5 additions & 2 deletions android/app/src/main/jni/ComponentsRegistry.cpp
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
#include "ComponentsRegistry.h"

#include <CoreComponentsRegistry.h>
#include <rncli.h>

#include <fbjni/fbjni.h>
#if __has_include(<react/fabric/CoreComponentsRegistry.h>) // >= 0.71
#include <react/fabric/CoreComponentsRegistry.h>
#else // < 0.71
#include <CoreComponentsRegistry.h>
#endif

#include <react/renderer/componentregistry/ComponentDescriptorProviderRegistry.h>
#include <react/renderer/componentregistry/ComponentDescriptorRegistry.h>
Expand Down
Loading

0 comments on commit 5469a1d

Please sign in to comment.