Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

runtime cxx module autolinking #43054

Closed
wants to merge 1 commit into from
Closed

Conversation

philIip
Copy link
Contributor

@philIip philIip commented Feb 15, 2024

Summary:

Changelog: [iOS][Android][Added] Experimental macro to autolink C++ turbomodules

this implementation is inspired by RCT_EXPORT_MODULE, we keep a global data structure that maps module names to a lambda that returns the C++ turbomodule. this will come with a hit to startup time. the only way to avoid that is a codegen solution. this is an experimental solution because we don't have a proper autolinking solution for ios modules that doesn't require changes in the app layer.

How to use

In the .cpp file of your TurboModule, add the following line, where MyCxxNativeModule is the identifier of your module. This will automatically link the module on both iOS and Android. The class name of your TurboModule must match its JavaScript module identifier and live in the facebook::react namespace.

#include <ReactCommon/CxxTurboModuleUtils.h>

RCT_EXPORT_CXX_MODULE_EXPERIMENTAL(MyCxxNativeModule)

namespace facebook::react {
  	
MyCxxNativeModule::MyCxxNativeModule(
...

there's still a catch here, because the macro can still get compiled out if the compiler thinks the file is not being used. this is how you can work around this at the build level:

on android, in your CMakeLists.txt, pass in -Wl, --whole_archive to add_compile_options .

add_compile_options(-Wl, --whole_archive)

on iOS, in the podspec, pass "-Wl, --whole_archive" as the value to "OTHER_LDFLAGS" in the pod_target_xcconfig.

Pod::Spec.new do |s|
  ...
  s.pod_target_xcconfig = {
    "OTHER_LDFLAGS" => "-Wl, --whole_archive"
  }
  ...
end

Differential Revision: D53602544

@facebook-github-bot facebook-github-bot added the CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. label Feb 15, 2024
@facebook-github-bot
Copy link
Contributor

This pull request was exported from Phabricator. Differential Revision: D53602544

Summary:
see https://fb.workplace.com/groups/2158787827656681/posts/2296646383870824/?comment_id=2303006146568181 for context

>hi everyone, update on how this directional development is going. currently, RuntimeExecutor appears to fulfill ExpoModules needs and has been integrated successfully on iOS. however, there is still a question on how to migrate callsites that require the runtime "on demand" when they are already on the JS thread. example from reanimated here (https://github.com/.../react.../blob/main/apple/REAModule.mm).

>Samuel and Pieter helped brainstorm a couple of options (exposing the raw runtime pointer, C++ turbomodules, deobfuscating the runtime pointer in the turbomodule invocation flow), but i felt like C++ turbomodule was the least hacky and had the most long-term prospects of these options.

>since the blocker is autolinking, i prototyped a macro similar to RCT_EXPORT_MODULE for cxx modules only and i would like to get everyone's comments: D53602544. Nicola is investigating android atm.

this implementation is inspired by RCT_EXPORT_MODULE, we keep a global data structure that maps module names to a lambda that returns the C++ turbomodule. this will come with a hit to startup time. the only way to avoid that is a codegen solution.

this is a temporary solution because we don't have a proper autolinking solution for ios modules that doesn't require changes in user land.

Differential Revision: D53602544
@facebook-github-bot
Copy link
Contributor

This pull request was exported from Phabricator. Differential Revision: D53602544

@analysis-bot
Copy link

Platform Engine Arch Size (bytes) Diff
android hermes arm64-v8a 17,832,418 +4,083
android hermes armeabi-v7a n/a --
android hermes x86 n/a --
android hermes x86_64 n/a --
android jsc arm64-v8a 21,190,890 +4,094
android jsc armeabi-v7a n/a --
android jsc x86 n/a --
android jsc x86_64 n/a --

Base commit: e4135e9
Branch: main

@facebook-github-bot facebook-github-bot added the Merged This PR has been merged. label Feb 20, 2024
@facebook-github-bot
Copy link
Contributor

This pull request has been merged in 01d704d.

@philIip philIip changed the title cxx module autolinking without codegen runtime cxx module autolinking Feb 23, 2024
@jpudysz
Copy link

jpudysz commented Apr 24, 2024

Hey @philIip!

I've tried your macro on iOS and confirmed that I added the compiler flags. I'm also using the same name in JS, but my module can't be registered. What works for me is the Obj-C macro with the load method:

#define INIT_CXX_MODULE(NAME) \
    @interface CxxModule: NSObject \
    @end \
    @implementation CxxModule \
    + (void)load { \
        facebook::react::registerCxxModuleToGlobalModuleMap( \
            std::string(facebook::react::NAME::kModuleName), \
            [](std::shared_ptr<facebook::react::CallInvoker> jsInvoker){ \
                return std::make_shared<facebook::react::NAME>(jsInvoker); \
            } \
        ); \
    } \
    @end \

It seems like the C++ code is never executed and the module is not registered. Can you give me any hints on how to handle this? It would be perfect to initialize my C++ TurboModule from C++ without single Obj-C file.
By the way, I'm using Codegen too.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. fb-exported Merged This PR has been merged. p: Facebook Partner: Facebook Partner
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants