Skip to content

Commit f575155

Browse files
committed
feat: add support for TurboModule
1 parent a3c9c55 commit f575155

File tree

13 files changed

+315
-50
lines changed

13 files changed

+315
-50
lines changed

android/app/build.gradle

Lines changed: 79 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,11 @@ buildscript {
66

77
plugins {
88
id("com.android.application")
9-
id("kotlin-android")
10-
id("kotlin-kapt")
9+
id("org.jetbrains.kotlin.android") version "${kotlinVersion}"
10+
id("org.jetbrains.kotlin.kapt") version "${kotlinVersion}"
11+
12+
// TODO: This is only available on react-native 0.68+
13+
//id("com.facebook.react")
1114
}
1215

1316
// `react-native run-android` is hard-coded to look for the output APK at a very
@@ -50,11 +53,12 @@ apply(from: "${projectDir}/../../test-app.gradle")
5053
applyTestAppModule(project)
5154

5255
project.ext.react = [
53-
appName : getAppName(),
54-
applicationId: getApplicationId(),
55-
enableFabric : isFabricEnabled(rootDir),
56-
enableFlipper: getFlipperVersion(rootDir),
57-
enableHermes : true,
56+
appName : getAppName(),
57+
applicationId : getApplicationId(),
58+
enableFabric : isFabricEnabled(rootDir),
59+
enableFlipper : getFlipperVersion(rootDir),
60+
enableHermes : true,
61+
enableTurboModule: false,
5862
]
5963

6064
project.ext.signingConfigs = getSigningConfigs()
@@ -69,14 +73,20 @@ android {
6973

7074
// TODO: Remove this block when minSdkVersion >= 24. See
7175
// https://stackoverflow.com/q/53402639 for details.
72-
compileOptions {
73-
sourceCompatibility JavaVersion.VERSION_1_8
74-
targetCompatibility JavaVersion.VERSION_1_8
76+
if (getReactNativeVersionNumber(rootDir) < 6900) {
77+
compileOptions {
78+
sourceCompatibility(JavaVersion.VERSION_1_8)
79+
targetCompatibility(JavaVersion.VERSION_1_8)
80+
}
7581
}
7682

7783
kotlinOptions {
7884
allWarningsAsErrors = true
79-
jvmTarget = JavaVersion.VERSION_1_8
85+
if (getReactNativeVersionNumber(rootDir) < 6900) {
86+
jvmTarget = JavaVersion.VERSION_1_8
87+
} else {
88+
jvmTarget = JavaVersion.VERSION_11
89+
}
8090
}
8191

8292
defaultConfig {
@@ -99,6 +109,51 @@ android {
99109
resValue "string", "app_name", project.ext.react.appName
100110

101111
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
112+
113+
if (project.ext.react.enableTurboModule) {
114+
externalNativeBuild {
115+
ndkBuild {
116+
arguments "APP_PLATFORM=android-${minSdkVersion}",
117+
"APP_STL=c++_shared",
118+
"NDK_TOOLCHAIN_VERSION=clang",
119+
"GENERATED_SRC_DIR=${buildDir}/generated/source",
120+
"NODE_MODULES_DIR=${reactNativeDir}/..",
121+
"PROJECT_BUILD_DIR=${buildDir}",
122+
"REACT_ANDROID_DIR=${reactNativeDir}/ReactAndroid",
123+
"REACT_ANDROID_BUILD_DIR=${reactNativeDir}/ReactAndroid/build"
124+
cFlags "-Wall", "-Werror", "-frtti", "-fexceptions", "-DWITH_INSPECTOR=1"
125+
cppFlags "-std=c++17"
126+
targets "reacttestapp_appmodules"
127+
}
128+
}
129+
}
130+
}
131+
132+
if (project.ext.react.enableTurboModule) {
133+
externalNativeBuild {
134+
ndkBuild {
135+
path "${projectDir}/src/main/jni/Android.mk"
136+
}
137+
}
138+
139+
def reactAndroidProjectDir = project(":ReactAndroid").projectDir
140+
def packageReactNdkLibs = tasks.register("packageReactNdkLibs", Copy) {
141+
dependsOn(":ReactAndroid:packageReactNdkLibsForBuck")
142+
dependsOn("generateCodegenArtifactsFromSchema")
143+
from("${reactAndroidProjectDir}/src/main/jni/prebuilt/lib")
144+
into("${buildDir}/react-ndk/exported")
145+
}
146+
147+
afterEvaluate {
148+
preBuild.dependsOn(packageReactNdkLibs)
149+
configureNdkBuildDebug.dependsOn(preBuild)
150+
configureNdkBuildRelease.dependsOn(preBuild)
151+
}
152+
153+
packagingOptions {
154+
pickFirst("**/libhermes.so")
155+
pickFirst("**/libjsc.so")
156+
}
102157
}
103158

104159
lintOptions {
@@ -211,3 +266,16 @@ dependencies {
211266
}
212267
}
213268
}
269+
270+
if (project.ext.react.enableTurboModule) {
271+
configurations.all {
272+
resolutionStrategy.dependencySubstitution {
273+
substitute(module("com.facebook.react:react-native"))
274+
.using(project(":ReactAndroid"))
275+
.because("On New Architecture we are building React Native from source")
276+
substitute(module("com.facebook.react:hermes-engine"))
277+
.using(project(":ReactAndroid:hermes-engine"))
278+
.because("On New Architecture we are building Hermes from source")
279+
}
280+
}
281+
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
THIS_DIR := $(call my-dir)
2+
3+
include $(REACT_ANDROID_DIR)/Android-prebuilt.mk
4+
5+
# If you wish to add a custom TurboModule or Fabric component in your app you
6+
# will have to include the following autogenerated makefile.
7+
# include $(GENERATED_SRC_DIR)/codegen/jni/Android.mk
8+
include $(CLEAR_VARS)
9+
10+
LOCAL_PATH := $(THIS_DIR)
11+
12+
# You can customize the name of your application .so file here.
13+
LOCAL_MODULE := reacttestapp_appmodules
14+
15+
LOCAL_C_INCLUDES := $(LOCAL_PATH)
16+
LOCAL_SRC_FILES := $(wildcard $(LOCAL_PATH)/*.cpp)
17+
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)
18+
19+
# If you wish to add a custom TurboModule or Fabric component in your app you
20+
# will have to uncomment those lines to include the generated source
21+
# files from the codegen (placed in $(GENERATED_SRC_DIR)/codegen/jni)
22+
#
23+
# LOCAL_C_INCLUDES += $(GENERATED_SRC_DIR)/codegen/jni
24+
# LOCAL_SRC_FILES += $(wildcard $(GENERATED_SRC_DIR)/codegen/jni/*.cpp)
25+
# LOCAL_EXPORT_C_INCLUDES += $(GENERATED_SRC_DIR)/codegen/jni
26+
27+
# Here you should add any native library you wish to depend on.
28+
LOCAL_SHARED_LIBRARIES := \
29+
libfabricjni \
30+
libfbjni \
31+
libfolly_runtime \
32+
libglog \
33+
libjsi \
34+
libreact_codegen_rncore \
35+
libreact_debug \
36+
libreact_nativemodule_core \
37+
libreact_render_componentregistry \
38+
libreact_render_core \
39+
libreact_render_debug \
40+
libreact_render_graphics \
41+
librrc_view \
42+
libruntimeexecutor \
43+
libturbomodulejsijni \
44+
libyoga
45+
46+
LOCAL_CFLAGS := -std=c++17 -Wall -frtti -fexceptions -DLOG_TAG=\"ReactNative\"
47+
48+
include $(BUILD_SHARED_LIBRARY)

example/android/build.gradle

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ buildscript {
88
}
99

1010
dependencies {
11-
classpath "com.android.tools.build:gradle:$androidPluginVersion"
12-
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion"
11+
classpath("com.android.tools.build:gradle:${androidPluginVersion}")
12+
classpath("de.undercouch:gradle-download-task:5.1.0")
1313
}
1414
}
1515

example/android/settings.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
pluginManagement {
22
repositories {
33
gradlePluginPortal()
4-
mavenLocal()
4+
mavenCentral()
55
google()
66
}
77
}

example/ios/Podfile

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,13 @@ workspace 'Example.xcworkspace'
44

55
use_flipper! false if ENV['DISABLE_FLIPPER']
66

7-
use_test_app! :fabric_enabled => false, :hermes_enabled => false do |target|
7+
options = {
8+
:fabric_enabled => false,
9+
:hermes_enabled => false,
10+
:turbomodule_enabled => false,
11+
}
12+
13+
use_test_app! options do |target|
814
target.tests do
915
pod 'Example-Tests', :path => '..'
1016
end

ios/ReactTestApp.xcodeproj/project.pbxproj

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
/* Begin PBXBuildFile section */
1010
1914199A234B2DD800D856AE /* RCTDevSupport+UIScene.m in Sources */ = {isa = PBXBuildFile; fileRef = 19141999234B2DD800D856AE /* RCTDevSupport+UIScene.m */; };
1111
192DD201240FCAF5004E9CEB /* Manifest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 192DD200240FCAF5004E9CEB /* Manifest.swift */; };
12+
193B614D27F5CD7D00080064 /* React+TurboModule.mm in Sources */ = {isa = PBXBuildFile; fileRef = 193B614B27F5CD7D00080064 /* React+TurboModule.mm */; };
1213
1963A06227C82E730013D276 /* React+Fabric.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1963A06127C82E730013D276 /* React+Fabric.mm */; };
1314
196C22622490CB7600449D3C /* React+Compatibility.m in Sources */ = {isa = PBXBuildFile; fileRef = 196C22602490CB7600449D3C /* React+Compatibility.m */; };
1415
196C7215232F1788006556ED /* ReactInstance.swift in Sources */ = {isa = PBXBuildFile; fileRef = 196C7214232F1788006556ED /* ReactInstance.swift */; };
@@ -48,6 +49,8 @@
4849
192F052624AD3CC500A48456 /* ReactTestApp.release.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = ReactTestApp.release.xcconfig; sourceTree = "<group>"; };
4950
192F052724AD3CC500A48456 /* ReactTestApp.common.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = ReactTestApp.common.xcconfig; sourceTree = "<group>"; };
5051
192F052824AD3CC500A48456 /* ReactTestApp.debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = ReactTestApp.debug.xcconfig; sourceTree = "<group>"; };
52+
193B614B27F5CD7D00080064 /* React+TurboModule.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = "React+TurboModule.mm"; sourceTree = "<group>"; };
53+
193B614C27F5CD7D00080064 /* React+TurboModule.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "React+TurboModule.h"; sourceTree = "<group>"; };
5154
1963A06027C82E730013D276 /* React+Fabric.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "React+Fabric.h"; sourceTree = "<group>"; };
5255
1963A06127C82E730013D276 /* React+Fabric.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = "React+Fabric.mm"; sourceTree = "<group>"; };
5356
196C22602490CB7600449D3C /* React+Compatibility.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "React+Compatibility.m"; sourceTree = "<group>"; };
@@ -137,6 +140,8 @@
137140
196C22602490CB7600449D3C /* React+Compatibility.m */,
138141
1963A06027C82E730013D276 /* React+Fabric.h */,
139142
1963A06127C82E730013D276 /* React+Fabric.mm */,
143+
193B614C27F5CD7D00080064 /* React+TurboModule.h */,
144+
193B614B27F5CD7D00080064 /* React+TurboModule.mm */,
140145
1988282224105BCC005057FF /* UIViewController+ReactTestApp.h */,
141146
1988284424105BEC005057FF /* UIViewController+ReactTestApp.m */,
142147
19ECD0DB232ED427003D8557 /* Assets.xcassets */,
@@ -349,6 +354,7 @@
349354
1914199A234B2DD800D856AE /* RCTDevSupport+UIScene.m in Sources */,
350355
196C22622490CB7600449D3C /* React+Compatibility.m in Sources */,
351356
1963A06227C82E730013D276 /* React+Fabric.mm in Sources */,
357+
193B614D27F5CD7D00080064 /* React+TurboModule.mm in Sources */,
352358
196C7215232F1788006556ED /* ReactInstance.swift in Sources */,
353359
19ECD0D8232ED425003D8557 /* SceneDelegate.swift in Sources */,
354360
19A624A4258C95F000032776 /* Session.swift in Sources */,
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#if USE_TURBOMODULE
2+
3+
#import <React/RCTBridgeDelegate.h>
4+
5+
NS_ASSUME_NONNULL_BEGIN
6+
7+
@interface RTATurboModuleManagerDelegate : NSObject <RCTBridgeDelegate>
8+
- (instancetype)initWithBridgeDelegate:(id<RCTBridgeDelegate>)bridgeDelegate;
9+
@end
10+
11+
NS_ASSUME_NONNULL_END
12+
13+
#endif // USE_TURBOMODULE
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
#import "React+TurboModule.h"
2+
3+
#if USE_TURBOMODULE
4+
5+
#import <React/CoreModulesPlugins.h>
6+
#import <React/RCTAppSetupUtils.h>
7+
#import <React/RCTCxxBridgeDelegate.h>
8+
#import <React/RCTDataRequestHandler.h>
9+
#import <React/RCTFileRequestHandler.h>
10+
#import <React/RCTGIFImageDecoder.h>
11+
#import <React/RCTHTTPRequestHandler.h>
12+
#import <React/RCTImageLoader.h>
13+
#import <React/RCTJSIExecutorRuntimeInstaller.h>
14+
#import <React/RCTLocalAssetImageLoader.h>
15+
#import <React/RCTNetworking.h>
16+
#import <ReactCommon/RCTTurboModuleManager.h>
17+
18+
@interface RTATurboModuleManagerDelegate () <RCTCxxBridgeDelegate, RCTTurboModuleManagerDelegate>
19+
@end
20+
21+
@implementation RTATurboModuleManagerDelegate {
22+
__weak id<RCTBridgeDelegate> _bridgeDelegate;
23+
RCTTurboModuleManager *_turboModuleManager;
24+
}
25+
26+
- (instancetype)initWithBridgeDelegate:(id<RCTBridgeDelegate>)bridgeDelegate
27+
{
28+
if (self = [super init]) {
29+
_bridgeDelegate = bridgeDelegate;
30+
}
31+
return self;
32+
}
33+
34+
// MARK: - RCTBridgeDelegate details
35+
36+
- (NSURL *)sourceURLForBridge:(RCTBridge *)bridge
37+
{
38+
return [_bridgeDelegate sourceURLForBridge:bridge];
39+
}
40+
41+
- (NSArray<id<RCTBridgeModule>> *)extraModulesForBridge:(RCTBridge *)bridge
42+
{
43+
return [_bridgeDelegate extraModulesForBridge:bridge];
44+
}
45+
46+
// MARK: - RCTCxxBridgeDelegate details
47+
48+
- (std::unique_ptr<facebook::react::JSExecutorFactory>)jsExecutorFactoryForBridge:
49+
(RCTBridge *)bridge
50+
{
51+
if (_turboModuleManager == nil) {
52+
_turboModuleManager = [[RCTTurboModuleManager alloc] initWithBridge:bridge
53+
delegate:self
54+
jsInvoker:bridge.jsCallInvoker];
55+
}
56+
return RCTAppSetupDefaultJsExecutorFactory(bridge, _turboModuleManager);
57+
}
58+
59+
// MARK: - RCTTurboModuleManagerDelegate details
60+
61+
- (Class)getModuleClassFromName:(const char *)name
62+
{
63+
return RCTCoreModulesClassProvider(name);
64+
}
65+
66+
- (std::shared_ptr<facebook::react::TurboModule>)
67+
getTurboModule:(const std::string &)name
68+
jsInvoker:(std::shared_ptr<facebook::react::CallInvoker>)jsInvoker
69+
{
70+
return nullptr;
71+
}
72+
73+
- (id<RCTTurboModule>)getModuleInstanceFromClass:(Class)moduleClass
74+
{
75+
return RCTAppSetupDefaultModuleFromClass(moduleClass);
76+
}
77+
78+
@end
79+
80+
#endif // USE_TURBOMODULE

ios/ReactTestApp/ReactInstance.swift

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,15 +18,20 @@ final class ReactInstance: NSObject, RCTBridgeDelegate {
1818
private(set) var bridge: RCTBridge?
1919
private var bundleRoot: String?
2020

21+
#if USE_TURBOMODULE
22+
private lazy var turboModuleManagerDelegate = RTATurboModuleManagerDelegate(bridgeDelegate: self)
23+
#endif
24+
2125
override init() {
2226
#if DEBUG
2327
remoteBundleURL = ReactInstance.jsBundleURL()
2428
#endif
2529

2630
super.init()
2731

28-
// Turbo Modules is incompatible with remote JS debugging
29-
RCTEnableTurboModule(false)
32+
#if USE_TURBOMODULE
33+
RCTEnableTurboModule(true)
34+
#endif
3035

3136
RCTSetFatalHandler { (error: Error?) in
3237
guard let error = error else {
@@ -114,10 +119,17 @@ final class ReactInstance: NSObject, RCTBridgeDelegate {
114119
object: nil
115120
)
116121

117-
guard let bridge = RCTBridge(delegate: self, launchOptions: nil) else {
118-
assertionFailure("Failed to instantiate RCTBridge")
119-
return
120-
}
122+
#if USE_TURBOMODULE
123+
guard let bridge = RCTBridge(delegate: turboModuleManagerDelegate, launchOptions: nil) else {
124+
assertionFailure("Failed to instantiate RCTBridge with TurboModule")
125+
return
126+
}
127+
#else
128+
guard let bridge = RCTBridge(delegate: self, launchOptions: nil) else {
129+
assertionFailure("Failed to instantiate RCTBridge")
130+
return
131+
}
132+
#endif // USE_TURBOMODULE
121133

122134
surfacePresenterBridgeAdapter = RTACreateSurfacePresenterBridgeAdapter(bridge)
123135
self.bridge = bridge

ios/ReactTestApp/ReactTestApp-Bridging-Header.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,4 +27,5 @@
2727

2828
#import "React+Compatibility.h"
2929
#import "React+Fabric.h"
30+
#import "React+TurboModule.h"
3031
#import "UIViewController+ReactTestApp.h"

0 commit comments

Comments
 (0)