Repository navigation
The C++ Turbo Module template uses a Kotlin implementation on Android #829
Description
Activity
Zach-Dean-Attractions-io commented
on Apr 25, 2025 AuthorMore actionsI think the fix is relatively straightforward to call the native multiply implementation from the Kotlin implementation
package com.cpplibtest import com.facebook.react.bridge.ReactApplicationContext import com.facebook.react.module.annotations.ReactModule @ReactModule(name = CppLibTestModule.NAME) class CppLibTestModule(reactContext: ReactApplicationContext) : NativeCppLibTestSpec(reactContext) { override fun getName(): String { return NAME } // Example method // See https://reactnative.dev/docs/native-modules-android override fun multiply(a: Double, b: Double): Double { - return a * b + return nativeMultiply(a, b) } companion object { const val NAME = "CppLibTest" + @JvmStatic + external fun nativeMultiply(a: Double, b: Double): Double + init { + System.loadLibrary("cpp-lib-test") + } } }I think it should be possible to use a pure C++ implementation as described here though whereas this methodology is more of a Kotlin implementation which calls into shared C++ code using the JNI. I'll try take a look into this.
Zach-Dean-Attractions-io commented
on Apr 25, 2025 AuthorMore actionsOh I see this template has been removed: #818
Is there any plan to support a pure C++ module template in the future? With React Native
0.79.0there is a way to register pure C++ modules via the codegen spec, so I think this should allow for a pure C++ self contained library implementation.Is there any plan to support a pure C++ module template in the future
I haven't managed to write a C++ library that works. The official docs only cover how to write one in existing app, https://reactnative.dev/docs/the-new-architecture/pure-cxx-modules, but trying to use same approach with a library doesn't seem to work with autolinking.
If you figure out how then PR or a sample library I can turn into a template is welcome.
Reacted by JoeyZach-Dean-Attractions-io commented
on Apr 28, 2025 AuthorMore actionsI did manage to get iOS working by adding code to the consuming app's
AppDelegatefile to register the module. I think React Native 0.79.0 released something in the codegen process to declare your native modules and it would link them for you but I ran into a crash when trying this. I asked in the reactwg repo here about it: reactwg/react-native-new-architecture#286However, I stumbled across this youtube video https://www.youtube.com/watch?v=KURIqiCPbco and they used an Objective-C file in the library and registered the native module in the
+ (void) loadfunction.#import <Foundation/Foundation.h> #import "MyCpp.h" #import <ReactCommon/CxxTurboModuleUtils.h> @interface OnLoad : NSObject @end @implementation OnLoad using namespace facebook::react; + (void) load { registerCxxModuleToGlobalModuleMap( std::string(MyCpp::kModuleName), [](std::shared_ptr<CallInvoker> jsInvoker) { return std::make_shared<MyCpp>(jsInvoker); } ); } @end
This is working for me. I'm going to watch the Android version next and try implementing that. If I get both working I'll either share a repo or create a PR (if time allows).
I'll also ask in the reactwg repo to check this is best practise.
Zach-Dean-Attractions-io commented
on Apr 28, 2025 AuthorMore actionsOk I have Android working too thanks to the author's other video https://www.youtube.com/watch?v=ibgHObp8YwA&t=8s
This repo has the changes for Android & iOS react-native-pure-cpp-turbo-module-library. If I get time I could attempt a PR to add it into the
create-react-native-libraryproject, but I also might wait for a review from the RN team to check this is best practice and if there are any mistakes that I have made or other problems this solution may cause.@Zach-Dean-Attractions-io thank you! i'll check it out
@Zach-Dean-Attractions-io I was able to setup a sample with the latest template based on your example https://github.com/satya164/react-native-pure-cpp-turbo-module-library
However, before we can include it as a template, we would want to disable
includeGeneratedCode, and while it works on iOS, it doesn't seem to work on Android.Zach-Dean-Attractions-io commented
on May 6, 2025 AuthorMore actionsHi @satya164
I did see in this PR #819 it was planned to remove
includesGeneratedCode: true. I was quite confused (due to my own lack of understanding) about the documentation on that flag and managed to clear up my understanding here: reactwg/react-native-new-architecture#272 (reply in thread). I think I will includeincludesGeneratedCode: truein my project since if I don't include it and the consuming app runs codegen for me, it still might be using an incompatible version of React Native.However, that doesn't matter really as the library template should work with
includesGeneratedCode: true / falseand not just one option. I'll try take a look this week but I'm not too clued in to how everything works under the hood myself so might have to ask in the react working group.Reacted by Navipro70Zach-Dean-Attractions-io commented
on May 9, 2025 AuthorMore actionsI haven't had much time to look into it sorry.
However, from what I can see there is a file generated called
autolinking.jsonand this file includes"android": { "cmakeListsPath": "/Users/zachdean/Desktop/react-native-pure-cpp-turbo-module-library/android/build/generated/source/codegen/jni/CMakeLists.txt", }Then in the Gradle task
GenerateAutolinkingNewArchitecturesFileTask.ktthis json file is used to write a fileexample/android/app/build/generated/autolinking/src/main/jni/Android-autolinking.cmakeand this looks like:# This code was generated by [React Native](https://www.npmjs.com/package/@react-native/gradle-plugin) cmake_minimum_required(VERSION 3.13) set(CMAKE_VERBOSE_MAKEFILE on) # We set REACTNATIVE_MERGED_SO so libraries/apps can selectively decide to depend on either libreactnative.so # or link against a old prefab target (this is needed for React Native 0.76 on). set(REACTNATIVE_MERGED_SO true) add_subdirectory("/Users/zachdean/Desktop/react-native-pure-cpp-turbo-module-library/android/build/generated/source/codegen/jni/" PureCppTurboModuleLibrarySpec_autolinked_build) add_subdirectory("/Users/zachdean/Desktop/react-native-pure-cpp-turbo-module-library/android/" PureCppTurboModuleLibrarySpec_cxxmodule_autolinked_build) set(AUTOLINKED_LIBRARIES react_codegen_PureCppTurboModuleLibrarySpec react-native-pure-cpp-turbo-module-library )The first
add_subdirectoryline causes an issue because the generated code isn't shipped with the library. Looking at the code that generates theAndroid-autolinking.cmakefile, I expected that if I setcmakeListsPath: nullinreact-native.config.jsthen it might avoid thisadd_subdirectorycommand but that doesn't seem to work it is still populated with that default path.I manually set it to
nullin theautolinking.jsonfile"android": { "cmakeListsPath": null, }But then I run into another error.
CMake Error at example/node_modules/react-native/ReactAndroid/cmake-utils/ReactNative-application.cmake:103 (target_link_libraries): Cannot specify link libraries for target "react_codegen_RNPureCppTurboModuleLibrarySpec" which is not built by this project.The generated CMake file adds a library
react_codegen_PureCppTurboModuleLibrarySpec, which I assume doesn't get built if the generated code isn't shipped with the library. Although I would expect the consuming app would generated the CMake file to add this library, otherwise it wouldn't be possible to create a C++ library withoutincludesGeneratedCode: true. Maybe the app needs to also include what this generated CMake file would have done.However, some of the paths here such as
react/renderer/components/RNPureCppTurboModuleLibrarySpec/*.cppdon't seem to exist ifincludesGeneratedCode: trueisn't specified. I thought that the consuming app might generated them in a build folder but I can't see that it does.Another example is
PureCppImpl.hincludesRNPureCppTurboModuleLibrarySpecJSI.hwhich is in the generated folder but doesn't seem to be created in the example app if the generated code isn't there. Unless the error just occurs before it can generate those files.# 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. cmake_minimum_required(VERSION 3.13) set(CMAKE_VERBOSE_MAKEFILE on) file(GLOB react_codegen_SRCS CONFIGURE_DEPENDS *.cpp react/renderer/components/RNPureCppTurboModuleLibrarySpec/*.cpp) add_library( react_codegen_RNPureCppTurboModuleLibrarySpec OBJECT ${react_codegen_SRCS} ) target_include_directories(react_codegen_RNPureCppTurboModuleLibrarySpec PUBLIC . react/renderer/components/RNPureCppTurboModuleLibrarySpec) target_link_libraries( react_codegen_RNPureCppTurboModuleLibrarySpec fbjni jsi # We need to link different libraries based on whether we are building rncore or not, that's necessary # because we want to break a circular dependency between react_codegen_rncore and reactnative reactnative ) target_compile_options( react_codegen_RNPureCppTurboModuleLibrarySpec PRIVATE -DLOG_TAG=\"ReactNative\" -fexceptions -frtti -std=c++20 -Wall )I might have to ask this in the react working group because I can't quite see that it is possible but I am sure that's more my lack of understanding.
Reacted by Navipro70Zach-Dean-Attractions-io commented
on May 9, 2025 AuthorMore actionsOk I think I have found the problem. I took a look at the recent version of
create-react-native-libraryand the turbo module template which works correctly. When you build the consuming app it generates the code in theandroiddirectory that the module requires.This isn't happening in this project and so the build fails. I think this is due to the fact there is no
build.gradlein theandroiddirectory which configures the React Native plugin.If you clone this repo you should be able to remove
includesGeneratedCode: trueand build android successfully.You may not need the files within android/src/main but I think you need the
build.gradlefile.I think it is this code that lets the React Native Plugin know our library is using codegen.
react { jsRootDir = file("../src/") libraryName = "PureCppTurboModuleLibrary" codegenJavaPackageName = "com.purecppturbomodulelibrary" }Reacted by Satyajit Sahoo@Zach-Dean-Attractions-io thanks a lot for the investigation. I'll check it out. ideally it shouldn't need a
build.gradle(react-native-community/cli#2387) but i guess that's something to be fixed.Zach-Dean-Attractions-io commented
on May 9, 2025 AuthorMore actionsAh right I see! I'm not sure in that case sorry. Let me know what you find.
Reacted by Satyajit Sahoo@Zach-Dean-Attractions-io thanks a lot for the investigation. I'll check it out. ideally it shouldn't need a
build.gradle(react-native-community/cli#2387) but i guess that's something to be fixed.@satya164 I tried out your repo with the fixes but still the same error exists, am I missing any configs
https://github.com/satya164/react-native-pure-cpp-turbo-module-library
CMake Error at example/node_modules/react-native/ReactAndroid/cmake-utils/ReactNative-application.cmake:103 (target_link_libraries): Cannot specify link libraries for target "react_codegen_RNPureCppTurboModuleLibrarySpec" which is not built by this project.@Zach-Dean-Attractions-io thanks a lot for the investigation. I'll check it out. ideally it shouldn't need a
build.gradle(react-native-community/cli#2387) but i guess that's something to be fixed.@satya164 I tried out your repo with the fixes but still the same error exists, am I missing any configs
https://github.com/satya164/react-native-pure-cpp-turbo-module-library
CMake Error at example/node_modules/react-native/ReactAndroid/cmake-utils/ReactNative-application.cmake:103 (target_link_libraries): Cannot specify link libraries for target "react_codegen_RNPureCppTurboModuleLibrarySpec" which is not built by this project.You can revert the last commit to have a working implementation with
includesGeneratedCode: true. Right now it's not possible to disable it, looks like bug in autolinking.I'm confused a lot of current documentation for pure C++ module implementation by the way of separated package
I was able to add C++ module into existed react-native project by docs, so that was a challenge for a while, but I've passed it successfully. So the next step I was going to separate this module from existed project to a npm library, and at the point I'm struggling with it now :(
I've succesfully linked C++ module with IOS project, it was pretty much the same as in docs. Bring C++ code, make static library by podspec, write wrapper in Obj-C++, also an important thing is to add
modulesProviderincodegenConfiginpackage.json- all is done.But Android... I've tried a way from docs and it fails up at
CMakeLists.txtatinclude(${REACT_ANDROID_DIR}/cmake-utils/ReactNative-application.cmake)on a build phase of android from example folder. So I've tried a lot ofCMakeLists.txtconfigs,OnLoad.cppfrom docs and much more but even if app was build successfully, it cannot find my native C++ module. I cannot recognize what I'm doing wrong because I don't even know what I should to do. All previous ways that I saw don't work for me (a lot of them are above)"react-native": "0.79.2", "react-native-builder-bob": "^0.40.12", "create-react-native-library": "0.51.1"Reacted by JoeyHoly cache... Just deleted generated code from build directories in both android folders from root and example, rebuilt and all became working, for a point
./gradlew cleandidn't helpSo would like to share my milestones to make pure C++ module working on android:
- Add build.gradle CMakeLists native build to android section (path is your relative path from android folder):
externalNativeBuild { cmake { path "CMakeLists.txt" } }- Add react-native.config.js with following code, replace names with your module names:
module.exports = { dependency: { platforms: { /** * @type {import('@react-native-community/cli-types').IOSDependencyParams} */ ios: {}, /** * @type {import('@react-native-community/cli-types').AndroidDependencyParams} */ android: { cxxModuleCMakeListsModuleName: 'react-native-cryptopp', cxxModuleCMakeListsPath: 'CMakeLists.txt', cxxModuleHeaderName: 'NativeCryptopp', }, }, }, };- CMakeLists.txt for the following code, replace names with your module names:
cmake_minimum_required(VERSION 3.4.1) project(NativeCryptopp) set (CMAKE_VERBOSE_MAKEFILE ON) add_library(react-native-cryptopp STATIC ../cpp/NativeCryptopp.cpp ) target_include_directories( react-native-cryptopp PUBLIC ../cpp ) target_link_libraries(react-native-cryptopp jsi reactnative react_codegen_RNCryptoppSpec )- Delete all files in android/src/main/java except the
{YOUR_GENERATED_MODULE_NAME}Package.ktand make it empty (need for linking, but as I saw at @satya164 repo it can be deleted as well, but I didn't found a way to do it) like this:
package com.cryptopp import com.facebook.react.BaseReactPackage import com.facebook.react.bridge.NativeModule import com.facebook.react.bridge.ReactApplicationContext import com.facebook.react.module.model.ReactModuleInfo import com.facebook.react.module.model.ReactModuleInfoProvider import java.util.HashMap class CryptoppPackage : BaseReactPackage() { override fun getModule(name: String, reactContext: ReactApplicationContext): NativeModule? { return null } override fun getReactModuleInfoProvider(): ReactModuleInfoProvider { return ReactModuleInfoProvider { val moduleInfos: MutableMap<String, ReactModuleInfo> = HashMap() moduleInfos } } }Don't forget to delete all build before building a new one.
Zach-Dean-Attractions-io commented
on Jul 14, 2025 AuthorMore actionsHi @Navipro70
You should be able to use https://github.com/Zach-Dean-Attractions-io/react-native-pure-cpp-turbo-module-library for a working example of a pure C++ turbo module on both iOS and Android. Although it does use
includesGeneratedCode: truein the codegen configuration and an extra configuration inreact-native.config.jsto support that, but that may or may not be a problem for you.Reacted by Navipro70@Zach-Dean-Attractions-io
Hello!
Thank you for helping out. I figured it out without includeGeneratedCode, if anybody need one more project as an example, you're welcome 😁: https://github.com/Navipro70/react-native-crypto-cppAlso sorry for a little mess above, my issue and messages isn't fully belong to original one but I found it helpful for other because didn't found the way myself in docs and other sources. But what a point we have now? For me personally it would be nice to have:
- Updated React Native documentation for https://reactnative.dev/docs/the-new-architecture/create-module-library. Because for pure C++ it's incorrect, you don't need OnLoad.cpp, moreover, CMakeLists.txt changing a lot when you copy code and pretty much other stuff already mentioned here.
- Create C++ Turbo Modules template in create-react-native-library. Because as I remember I started my project with just pure native mobile files (Obj-C and Kotlin) and didn't have an option for pure C++ module creation.
@Zach-Dean-Attractions-io you also mentioned that you have wrote a question/issue to a react-native, may you please give us a link to it? And also what do you think about my millstones above? Thanks.
Reacted by 翎葉I want to know how to remove the codegen of .kt. I use turbomoduel in c++ on both Android and iOS, but every time I modify Nativexxx.ts, kotlin also needs to be modified, otherwise there will be a compilation error.
I want to know how to remove the codegen of .kt. I use turbomoduel in c++ on both Android and iOS, but every time I modify Nativexxx.ts, kotlin also needs to be modified, otherwise there will be a compilation error.
modify .kt files under turbomodule-library/android/src/main/java/com/ folder, don't inherit the glue code, you won't get an error.
Description
I'm not sure if I'm missing something obvious but when creating the library template for a Turbo Module using C++ for Android & iOS there is a default example implementing a
multiplyfunction. However, on Android the implementation for this function is in Kotlin and it doesn't use the shared C++ library.When the JS code calls
multiplyit comes into the code here.Is there any reason why the
OnLoad.cppfile isn't used to register the turbo module in this case as described here: pure-cxx-modules#androidPackages
Selected options
npx create-react-native-library cppLibraryTestLink to repro
N/A
Environment