diff --git a/README.md b/README.md index fd11489..eb19062 100644 --- a/README.md +++ b/README.md @@ -3,8 +3,8 @@ A journey to discover RN TurboModules. Each commit is a different stage towards a fully featured Turbo Module. 0. Basic initialization and boilerplate (use `npx create-react-native-library` with C++ template) -1. _TODO:_ Adding `fbjni` for Android - it greatly improves Java - C++ interop. -2. _TODO:_ Migrating from legacy RN bridge to JSI. +1. Adding `fbjni` for Android - it greatly improves Java - C++ interop. +2. Migrating from legacy RN bridge to JSI. 3. _TODO:_ Implementing the "Real" Turbo Module. 4. _TODO:_ Calling Kotlin/Swift code from C++ module. 5. _TODO:_ Multithreading / asynchronous operations diff --git a/android/CMakeLists.txt b/android/CMakeLists.txt index 4a8e8ac..6975e3c 100644 --- a/android/CMakeLists.txt +++ b/android/CMakeLists.txt @@ -11,6 +11,14 @@ include_directories( ../cpp ../node_modules/react-native/React ../node_modules/react-native/React/Base + ../node_modules/react-native/ReactCommon + ../node_modules/react-native/ReactCommon/jsi + ../node_modules/react-native/ReactCommon/callinvoker + ../node_modules/react-native/ReactAndroid/src/main/java/com/facebook/react/turbomodule/core/jni/ReactCommon + ../node_modules/react-native/ReactCommon/turbomodule/core + ../node_modules/react-native/ReactCommon/turbomodule + ../node_modules/react-native/React + ../node_modules/react-native/React/Base ../node_modules/react-native/ReactCommon/jsi ) @@ -22,9 +30,22 @@ find_package(fbjni REQUIRED CONFIG) add_library(${PACKAGE_NAME} SHARED ../node_modules/react-native/ReactCommon/jsi/jsi/jsi.cpp + ../node_modules/react-native/ReactAndroid/src/main/java/com/facebook/react/turbomodule/core/jni/ReactCommon/CallInvokerHolder.cpp + ../node_modules/react-native/ReactCommon/turbomodule/core/TurboModule.cpp ../cpp/TurboUtilsModule.cpp cpp-adapter.cpp ) # link fbjni and logger to my_turbo_utils target_link_libraries(${PACKAGE_NAME} fbjni::fbjni android log) + +# A workaround to avoid runtime error: +# E/SoLoader: couldn't find DSO to load: libturbomodulejsijni.so +add_library( + turbomodulejsijni + # Sets the library as a shared library. + SHARED + # an empty cpp file + ../cpp/empty.cpp +) + diff --git a/android/build.gradle b/android/build.gradle index 222b980..0c963b8 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -5,7 +5,7 @@ buildscript { } dependencies { - classpath 'com.android.tools.build:gradle:4.2.0' + classpath 'com.android.tools.build:gradle:4.2.1' // noinspection DifferentKotlinGradleVersion classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.3.50" } diff --git a/android/cpp-adapter.cpp b/android/cpp-adapter.cpp index e5b1f41..c2bcb19 100644 --- a/android/cpp-adapter.cpp +++ b/android/cpp-adapter.cpp @@ -1,10 +1,11 @@ #include +#include +#include +#include + #include "TurboUtilsModule.h" #include "Logging.h" -#include - -#include using namespace facebook; @@ -43,10 +44,17 @@ struct NativeProxy : jni::JavaClass { } private: - static void installNativeJsi(jni::alias_ref thiz, jlong jsiRuntimePtr) { + static void installNativeJsi(jni::alias_ref thiz, + jlong jsiRuntimePtr, + jni::alias_ref jsCallInvokerHolder) { auto jsiRuntime = reinterpret_cast(jsiRuntimePtr); + auto jsCallInvoker = jsCallInvokerHolder->cthis()->getCallInvoker(); + // initialize jsi module turboutils::installJsi(*jsiRuntime); + + // initialize turbo module + turboutils::installTurboModule(*jsiRuntime, jsCallInvoker); } private: diff --git a/android/src/main/java/com/myturboutils/NativeProxy.java b/android/src/main/java/com/myturboutils/NativeProxy.java index a7d0648..e0e905a 100644 --- a/android/src/main/java/com/myturboutils/NativeProxy.java +++ b/android/src/main/java/com/myturboutils/NativeProxy.java @@ -4,7 +4,10 @@ // just not to make mess in MyTurboUtilsModule // c++ counterparts are in cpp-adapter.cpp +import android.util.Log; + import com.facebook.react.bridge.ReactContext; +import com.facebook.react.turbomodule.core.CallInvokerHolderImpl; // see https://github.com/facebookincubator/fbjni/blob/master/docs/quickref.md public class NativeProxy { @@ -14,10 +17,12 @@ public class NativeProxy { public static native String nativeMakeGreeting(String name); /*** jsi stuff ***/ //these could be static as well - private native void installNativeJsi(long jsContextNativePointer); + private native void installNativeJsi(long jsContextNativePointer, CallInvokerHolderImpl jsCallInvokerHolder); public void installJsi(ReactContext context) { + Log.d("Turboutils", "Installing native..."); + CallInvokerHolderImpl holder = (CallInvokerHolderImpl)context.getCatalystInstance().getJSCallInvokerHolder(); long contextPointer = context.getJavaScriptContextHolder().get(); - installNativeJsi(contextPointer); + installNativeJsi(contextPointer, holder); } } diff --git a/cpp/TurboUtilsModule.cpp b/cpp/TurboUtilsModule.cpp index c729c18..abdb8ff 100644 --- a/cpp/TurboUtilsModule.cpp +++ b/cpp/TurboUtilsModule.cpp @@ -11,7 +11,65 @@ namespace turboutils return a*a + b*b; } + /*** TurboModule implementation ***/ + void installTurboModule(jsi::Runtime& runtime, std::shared_ptr jsCallInvoker) { + std::shared_ptr nativeModule = + std::make_shared(jsCallInvoker); + // register UtilsTurboModule instance as global._myUtilsTurboModule + runtime.global().setProperty( + runtime, + jsi::PropNameID::forAscii(runtime, "_myUtilsTurboModule"), + jsi::Object::createFromHostObject(runtime, nativeModule)); + } + + static jsi::Value + _hostFunction_TurboUtilsSpecJSI_nativeSumSquares(jsi::Runtime &rt, react::TurboModule &turboModule, + const jsi::Value *args, size_t arg_count) { + // We can do input validation here + if (arg_count != 2 || !args[0].isNumber() || !args[1].isNumber()) { + jsi::detail::throwJSError(rt, "Invalid input for sumSquares()"); + return {}; + } + auto a = args[0].asNumber(); + auto b = args[1].asNumber(); + + LOG("Calling UtilsTurboModule.sumSquares(%f, %f)", a, b); + return dynamic_cast(&turboModule)->nativeSumSquares(rt, a, b); + } + + static jsi::Value _hostFunction_TurboUtilsSpecJSI_nativeGreeting(jsi::Runtime &rt, react::TurboModule &turboModule, + const jsi::Value *args, size_t arg_count) { + if (arg_count != 1 || !args[0].isString()) { + jsi::detail::throwJSError(rt, "Invalid input for makeGreetingFor()"); + return {}; + } + return dynamic_cast(&turboModule)->nativeGreeting(rt, args[0].getString(rt)); + } + + TurboUtilsSpecJSI::TurboUtilsSpecJSI(std::shared_ptr jsInvoker) + : TurboModule("UtilsTurboModule", jsInvoker) { + //here we assign our TurboModule object properties + LOG("Initializing TurboModule MethodMap"); + methodMap_["makeGreetingFor"] = MethodMetadata{1, _hostFunction_TurboUtilsSpecJSI_nativeGreeting}; + methodMap_["sumSquares"] = MethodMetadata{2, _hostFunction_TurboUtilsSpecJSI_nativeSumSquares}; + } + + /**************************************************************************/ + + jsi::String UtilsTurboModule::nativeGreeting(jsi::Runtime &rt, const jsi::String &name) { + auto msg = std::string("Greeting not implemented yet for ") + name.utf8(rt); + return jsi::String::createFromAscii(rt, msg); + } + + jsi::Value UtilsTurboModule::nativeSumSquares(jsi::Runtime &rt, double a, double b) { + return jsi::Value(sumSquares(a, b)); + } + + /**************************************************************************/ + + + // JSI non-turbomodule implementation void installJsi(jsi::Runtime& rt) { LOG("Installing JSI..."); diff --git a/cpp/TurboUtilsModule.h b/cpp/TurboUtilsModule.h index 3510ff2..bc1175d 100644 --- a/cpp/TurboUtilsModule.h +++ b/cpp/TurboUtilsModule.h @@ -3,10 +3,43 @@ #include +#ifdef __ANDROID__ + #include +#else + #include +#endif + namespace turboutils { + using namespace facebook; + double sumSquares(double a, double b); - void installJsi(facebook::jsi::Runtime& rt); + void installJsi(jsi::Runtime& rt); + + /****** TURBO MODULE STUFF BELOW *******/ + void installTurboModule(jsi::Runtime& runtime, std::shared_ptr jsCallInvoker); + + // This abstract class defines JSI interfaces for the turbo module + class JSI_EXPORT TurboUtilsSpecJSI : public facebook::react::TurboModule { + protected: + TurboUtilsSpecJSI(std::shared_ptr jsInvoker); + + public: + // define our interface methods + virtual jsi::String nativeGreeting(jsi::Runtime &rt, const jsi::String &name) = 0; + virtual jsi::Value nativeSumSquares(jsi::Runtime &rt, double a, double b) = 0; + + }; + + // This is the actual implementation of the module methods + class UtilsTurboModule : public TurboUtilsSpecJSI { + public: + UtilsTurboModule(std::shared_ptr jsInvoker) + : TurboUtilsSpecJSI(jsInvoker) {} + + jsi::String nativeGreeting(jsi::Runtime &rt, const jsi::String &name) override; + jsi::Value nativeSumSquares(jsi::Runtime &rt, double a, double b) override; + }; } #endif /* TURBOUTILSMODULE_H */ diff --git a/cpp/empty.cpp b/cpp/empty.cpp new file mode 100644 index 0000000..99aa8b4 --- /dev/null +++ b/cpp/empty.cpp @@ -0,0 +1,5 @@ +/* + * An empty cpp file just to avoid + * "E/SoLoader: couldn't find DSO to load: libturbomodulejsijni.so" + * error + */ diff --git a/example/ios/MyTurboUtilsExample.xcodeproj/project.pbxproj b/example/ios/MyTurboUtilsExample.xcodeproj/project.pbxproj index 118909f..d15bdd4 100644 --- a/example/ios/MyTurboUtilsExample.xcodeproj/project.pbxproj +++ b/example/ios/MyTurboUtilsExample.xcodeproj/project.pbxproj @@ -15,8 +15,8 @@ 2D02E4BD1E0B4A84006451C7 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; }; 2D02E4BF1E0B4AB3006451C7 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; }; 2DCD954D1E0B4F2C00145EB5 /* MyTurboUtilsExampleTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 00E356F21AD99517003FC87E /* MyTurboUtilsExampleTests.m */; }; - 4C39C56BAD484C67AA576FFA /* libPods-MyTurboUtilsExample.a in Frameworks */ = {isa = PBXBuildFile; fileRef = CA3E69C5B9553B26FBA2DF04 /* libPods-MyTurboUtilsExample.a */; }; 81AB9BB82411601600AC10FF /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */; }; + 9B74B19C8FC414C82EE0351D /* libPods-MyTurboUtilsExample.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 66F73A44D9E6EF75381CBAF4 /* libPods-MyTurboUtilsExample.a */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -50,8 +50,8 @@ 2D02E47B1E0B4A5D006451C7 /* MyTurboUtilsExample-tvOS.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "MyTurboUtilsExample-tvOS.app"; sourceTree = BUILT_PRODUCTS_DIR; }; 2D02E4901E0B4A5D006451C7 /* MyTurboUtilsExample-tvOSTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "MyTurboUtilsExample-tvOSTests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; 47F7ED3B7971BE374F7B8635 /* Pods-MyTurboUtilsExample.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-MyTurboUtilsExample.debug.xcconfig"; path = "Target Support Files/Pods-MyTurboUtilsExample/Pods-MyTurboUtilsExample.debug.xcconfig"; sourceTree = ""; }; + 66F73A44D9E6EF75381CBAF4 /* libPods-MyTurboUtilsExample.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-MyTurboUtilsExample.a"; sourceTree = BUILT_PRODUCTS_DIR; }; 81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = LaunchScreen.storyboard; path = MyTurboUtilsExample/LaunchScreen.storyboard; sourceTree = ""; }; - CA3E69C5B9553B26FBA2DF04 /* libPods-MyTurboUtilsExample.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-MyTurboUtilsExample.a"; sourceTree = BUILT_PRODUCTS_DIR; }; E00ACF0FDA8BF921659E2F9A /* Pods-MyTurboUtilsExample.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-MyTurboUtilsExample.release.xcconfig"; path = "Target Support Files/Pods-MyTurboUtilsExample/Pods-MyTurboUtilsExample.release.xcconfig"; sourceTree = ""; }; ED297162215061F000B7C4FE /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = System/Library/Frameworks/JavaScriptCore.framework; sourceTree = SDKROOT; }; ED2971642150620600B7C4FE /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = Platforms/AppleTVOS.platform/Developer/SDKs/AppleTVOS12.0.sdk/System/Library/Frameworks/JavaScriptCore.framework; sourceTree = DEVELOPER_DIR; }; @@ -69,7 +69,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 4C39C56BAD484C67AA576FFA /* libPods-MyTurboUtilsExample.a in Frameworks */, + 9B74B19C8FC414C82EE0351D /* libPods-MyTurboUtilsExample.a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -126,7 +126,7 @@ children = ( ED297162215061F000B7C4FE /* JavaScriptCore.framework */, ED2971642150620600B7C4FE /* JavaScriptCore.framework */, - CA3E69C5B9553B26FBA2DF04 /* libPods-MyTurboUtilsExample.a */, + 66F73A44D9E6EF75381CBAF4 /* libPods-MyTurboUtilsExample.a */, ); name = Frameworks; sourceTree = ""; @@ -205,7 +205,7 @@ 13B07F8C1A680F5B00A75B9A /* Frameworks */, 13B07F8E1A680F5B00A75B9A /* Resources */, 00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */, - C1D60D28B925C94BD88E79D7 /* [CP] Copy Pods Resources */, + 4C836E49FD1186B282D4EEA9 /* [CP] Copy Pods Resources */, ); buildRules = ( ); @@ -363,44 +363,44 @@ shellPath = /bin/sh; shellScript = "export NODE_BINARY=node\n../node_modules/react-native/scripts/react-native-xcode.sh"; }; - 4F0A6FC082772762E3E4C96C /* [CP] Check Pods Manifest.lock */ = { + 4C836E49FD1186B282D4EEA9 /* [CP] Copy Pods Resources */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); - inputFileListPaths = ( - ); inputPaths = ( - "${PODS_PODFILE_DIR_PATH}/Podfile.lock", - "${PODS_ROOT}/Manifest.lock", - ); - name = "[CP] Check Pods Manifest.lock"; - outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-MyTurboUtilsExample/Pods-MyTurboUtilsExample-resources.sh", + "${PODS_CONFIGURATION_BUILD_DIR}/React-Core/AccessibilityResources.bundle", ); + name = "[CP] Copy Pods Resources"; outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-MyTurboUtilsExample-checkManifestLockResult.txt", + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/AccessibilityResources.bundle", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-MyTurboUtilsExample/Pods-MyTurboUtilsExample-resources.sh\"\n"; showEnvVarsInLog = 0; }; - C1D60D28B925C94BD88E79D7 /* [CP] Copy Pods Resources */ = { + 4F0A6FC082772762E3E4C96C /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); + inputFileListPaths = ( + ); inputPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-MyTurboUtilsExample/Pods-MyTurboUtilsExample-resources.sh", - "${PODS_CONFIGURATION_BUILD_DIR}/React-Core/AccessibilityResources.bundle", + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( ); - name = "[CP] Copy Pods Resources"; outputPaths = ( - "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/AccessibilityResources.bundle", + "$(DERIVED_FILE_DIR)/Pods-MyTurboUtilsExample-checkManifestLockResult.txt", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-MyTurboUtilsExample/Pods-MyTurboUtilsExample-resources.sh\"\n"; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; showEnvVarsInLog = 0; }; FD10A7F022414F080027D42C /* Start Packager */ = { diff --git a/example/ios/Podfile.lock b/example/ios/Podfile.lock index 25417da..fd37b46 100644 --- a/example/ios/Podfile.lock +++ b/example/ios/Podfile.lock @@ -20,7 +20,12 @@ PODS: - glog - glog (0.3.5) - my-turbo-utils (0.1.0): + - Folly + - React + - React-callinvoker - React-Core + - React-jsi + - ReactCommon/turbomodule/core - RCTRequired (0.63.4) - RCTTypeSafety (0.63.4): - FBLazyVector (= 0.63.4) @@ -347,7 +352,7 @@ SPEC CHECKSUMS: FBReactNativeSpec: f2c97f2529dd79c083355182cc158c9f98f4bd6e Folly: b73c3869541e86821df3c387eb0af5f65addfab4 glog: 40a13f7840415b9a77023fbcae0f1e6f43192af3 - my-turbo-utils: e87b8f0115e6b5d09306e170ec560c4ab2545c79 + my-turbo-utils: 1a46edba67f0865a7cc4bc7808142223625e760c RCTRequired: 082f10cd3f905d6c124597fd1c14f6f2655ff65e RCTTypeSafety: 8c9c544ecbf20337d069e4ae7fd9a377aadf504b React: b0a957a2c44da4113b0c4c9853d8387f8e64e615 @@ -370,6 +375,6 @@ SPEC CHECKSUMS: ReactCommon: 73d79c7039f473b76db6ff7c6b159c478acbbb3b Yoga: 4bd86afe9883422a7c4028c00e34790f560923d6 -PODFILE CHECKSUM: 376455e5c18f190445dbfb465c87ec2cc527f890 +PODFILE CHECKSUM: bc14b2a6003af2a6d858f70d6ad69c61ffcdd73c COCOAPODS: 1.10.1 diff --git a/example/src/App.tsx b/example/src/App.tsx index 2dc6beb..72c17db 100644 --- a/example/src/App.tsx +++ b/example/src/App.tsx @@ -1,7 +1,7 @@ import * as React from 'react'; import { StyleSheet, View, Text } from 'react-native'; -import { MyUtilsJSI /* MyUtilsBridged */ } from 'my-turbo-utils'; +import { MyUtilsTurbo /* MyUtilsJSI, MyUtilsBridged */ } from 'my-turbo-utils'; export default function App() { const [result, setResult] = React.useState(); @@ -11,8 +11,8 @@ export default function App() { // Bridged // MyUtilsBridged.sumSquares(3, 4).then(setResult); // MyUtilsBridged.makeGreetingFor('Bridge').then(setGreeting); - setResult(MyUtilsJSI.sumSquares(3, 4)); - setGreeting(MyUtilsJSI.makeGreetingFor('JSI')); + setResult(MyUtilsTurbo.sumSquares(3, 4)); + setGreeting(MyUtilsTurbo.makeGreetingFor('TurboModule')); }, []); return ( diff --git a/ios/MyTurboUtils.mm b/ios/MyTurboUtils.mm index 7ec2701..92c4e81 100644 --- a/ios/MyTurboUtils.mm +++ b/ios/MyTurboUtils.mm @@ -5,7 +5,10 @@ #include "Logging.h" #import +#import +#import #import +#import using namespace facebook; @@ -30,8 +33,13 @@ - (void)setBridge:(RCTBridge *)bridge { } jsi::Runtime* jsiRuntime = (jsi::Runtime *)cxxBridge.runtime; + auto callInvoker = bridge.jsCallInvoker; + // init jsi-based module turboutils::installJsi(*jsiRuntime); + + // init turbo module + turboutils::installTurboModule(*jsiRuntime, callInvoker); } diff --git a/my-turbo-utils.podspec b/my-turbo-utils.podspec index ba32e43..fcb623f 100644 --- a/my-turbo-utils.podspec +++ b/my-turbo-utils.podspec @@ -2,6 +2,26 @@ require "json" package = JSON.parse(File.read(File.join(__dir__, "package.json"))) +reactVersion = '0.0.0' + +begin + reactVersion = JSON.parse(File.read(File.join(__dir__, "..", "react-native", "package.json")))["version"] +rescue + reactVersion = '0.63.0' +end + +rnVersion = reactVersion.split('.')[1] + +folly_prefix = "" +if rnVersion.to_i >= 64 + folly_prefix = "RCT-" +end + + +folly_flags = '-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1 -DRNVERSION=' + rnVersion +folly_compiler_flags = folly_flags + ' ' + '-Wno-comma -Wno-shorten-64-to-32' +folly_version = '2020.01.13.00' + Pod::Spec.new do |s| s.name = "my-turbo-utils" s.version = package["version"] @@ -15,5 +35,23 @@ Pod::Spec.new do |s| s.source_files = "ios/**/*.{h,m,mm}", "cpp/**/*.{h,cpp}" + s.xcconfig = { + "CLANG_CXX_LANGUAGE_STANDARD" => "c++14", + "HEADER_SEARCH_PATHS" => "\"$(PODS_ROOT)/#{folly_prefix}Folly\"", + "OTHER_CFLAGS" => "$(inherited)" + " " + folly_flags + } + s.pod_target_xcconfig = { + "DEFINES_MODULE" => "YES", + "USE_HEADERMAP" => "YES", + "HEADER_SEARCH_PATHS" => "\"$(PODS_TARGET_SRCROOT)/ReactCommon\" \"$(PODS_TARGET_SRCROOT)\" \"$(PODS_ROOT)/#{folly_prefix}Folly\" \"$(PODS_ROOT)/Headers/Private/React-Core\" " + } + s.requires_arc = true + + # probably some deps are redundant + s.dependency "React" s.dependency "React-Core" + s.dependency 'React-jsi' + s.dependency 'ReactCommon/turbomodule/core' + s.dependency 'React-callinvoker' + s.dependency "#{folly_prefix}Folly" end diff --git a/src/index.tsx b/src/index.tsx index 05aa0cc..91423ee 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -20,3 +20,11 @@ interface MyTurboUtilsJSI { // we can get global variable defined in C++ declare var _jsiTurboUtils: MyTurboUtilsJSI; export const MyUtilsJSI = _jsiTurboUtils; + +// TurboModule +interface MyTurboUtilsTM extends MyTurboUtilsJSI { + // I made both interfaces equal +} + +declare var _myUtilsTurboModule: MyTurboUtilsTM; +export const MyUtilsTurbo = _myUtilsTurboModule;