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

Binary packages : AAR, pod, nuget #1446

Open
CedricGuillemet opened this issue Nov 20, 2024 · 8 comments
Open

Binary packages : AAR, pod, nuget #1446

CedricGuillemet opened this issue Nov 20, 2024 · 8 comments
Assignees
Milestone

Comments

@CedricGuillemet
Copy link
Contributor

CedricGuillemet commented Nov 20, 2024

Following this PR that adds .aar android package build:
#1440

Next steps to improve integration ease into user land projects:

Unkowns

Technical questions/small tasks:

  • test back compatibility with BRN build (does new android project aar breaks existing BRN build?)
  • Is it possible to build a maven package that contains different JNI folders depending on JSEngine variable?
  • Is it possible to do a dry run of the publish process?
  • BN build produces an .aar, is it possible to open it and use it in a small project: like Installation test. A step after playground build that tests the local .aar
  • see linked PR for potential factorized code between gradle scripts (package and use import : extractNativeLibraries https://github.com/BabylonJS/BabylonNative/pull/1440/files/f50ade5e205029a159ca17f690704b095851b8de#diff-8bbc0df4aecf373eeaede4c5aac76fa992054286de68dd0c91d2210971edc3d3 )
  • Measure build time between maven aar and full build: the idea here is to know how much time is shaved with using Maven AAR and decide if it's worth doing. Is debugging as easy as before? if build is a few seconds faster, is it worth having a more complex build vs building everything?

iOS

  • same questions as android: ability to trace/debug, ability to test the pod locally
  • any limitation when using pods with prebuild binaries?
  • test project with produced cocoapod
  • test with BRN build: as a 1st step, ensure BRN build is not broken. Use produced cocoapodslater
  • Any limitation for MacOS/VisionOS? I believe this pods solution should be extended to these 2 platforms as well

Windows/Nuget

  • add more steps when more experienced with Android/iOS

BRN

  • add more steps when more experienced with Android/iOS

Next steps:

  • test BRN Android build (nothing is broken)
  • multiple JNI folders in single .aar tech test (or multiple .aar will be published)
  • iOS playground to produce a cocoapods that is then used. Check debugging still works
  • ...
@okwasniewski
Copy link
Contributor

Hey @CedricGuillemet,

I'm experimenting with the AAR and wanted to create a prebuilt for React Native.

As I understand the flow would be to:

  1. Prebuild .AAR file with NAPI_JAVASCRIPT_ENGINE set as JSI
  2. Integrate .aar file with React Native
  3. Use the Wrapper and Engine View making the integration significantly easier.

I'm hitting issues on the first step, when I set the variable I'm getting this error:

CMake Error at /Users/okwasniewski/workspace/Babylon/BabylonNative/Build/Android/Debug/1s1i656w/x86/_deps/jsruntimehost-src/Core/Node-API-JSI/CMakeLists.txt:55 (message):
  jsi target is required : com.android.ide.common.process.ProcessException: -- Android: Targeting API '24' with architecture 'x86', ABI 'x86', and processor 'i686'

I guess I need to have JSI linked, which means that prebuilding won't be possible for React Native? Or do you have some idea how to make this work?

I've tried to reference JSI in the CMake file of Babylon Native (just for testing) but it didn't work:

add_subdirectory(/Users/okwasniewski/workspace/react-native/packages/react-native/ReactCommon/jsi/jsi
 ${CMAKE_CURRENT_BINARY_DIR}/jsi)
target_include_directories(jsi INTERFACE /Users/okwasniewski/workspace/react-native/packages/react-native/ReactCommon/jsi)

Can you point me in the right direction on how to get the AAR prebuild working?

@okwasniewski
Copy link
Contributor

As an additional context I was able to take the build the AAR file, reference it in a React Native project:

implementation files('libs/BabylonNative-release.aar')

Render the Engine View that Babylon Native provides and load scripts using the view.loadScript method:

engineView.loadScript("app:///Scripts/experience.js")

And it worked! Making the integration way simpler (Great work on that btw!)

image

Now its the matter of having JSI in the middle 😅

@CedricGuillemet
Copy link
Contributor Author

And it worked! Making the integration way simpler (Great work on that btw!)

That's excellent news! Yes, integration should be a lot easier and it should be possible to do the same for other platforms as well.
Correct me if I'm wrong @bghgary but JSI with napi is waiting for some tasks to be done in the RN team. I don't think it's possible to precompile for JSI at the moment. This said, is it possible to test android + jsi with
BabylonNative CI ?

@okwasniewski
Copy link
Contributor

@CedricGuillemet @bghgary any chance you can share what are the prerequisites for getting this prebuilt JSI to work? I think this is crucial for the new architecture to work properly, moving most of the integration layer back to Babylon Native would make it a lot easier.

For now I'm struggling with getting new architecture to work properly due to some internal stack corruption errors..

I wanted to explore whether using your work on AAR this might make the new architecture migration easier.

I've been trying out different ways of getting the prebuild of JSI to work, I think I'm getting there, this is a hacky way of getting this working there but we can polish the build system once it works.

I've been modifying this file:

https://github.com/BabylonJS/BabylonNative/blob/master/Apps/Playground/Android/BabylonNative/CMakeLists.txt

set(REACT_NATIVE_PATH "~/workspace/react-native/packages/react-native" CACHE PATH "Path to React Native source")

# Add all JSI dependencies

add_subdirectory("${REACT_NATIVE_PATH}/ReactAndroid/src/main/jni/third-party/folly" 
                 "${CMAKE_CURRENT_BINARY_DIR}/folly")

add_subdirectory("${REACT_NATIVE_PATH}/ReactAndroid/src/main/jni/third-party/boost" 
                 "${CMAKE_CURRENT_BINARY_DIR}/boost")

add_subdirectory("${REACT_NATIVE_PATH}/ReactAndroid/src/main/jni/third-party/fmt" 
                 "${CMAKE_CURRENT_BINARY_DIR}/fmt")

add_subdirectory("${REACT_NATIVE_PATH}/ReactAndroid/src/main/jni/third-party/double-conversion" 
                 "${CMAKE_CURRENT_BINARY_DIR}/double-conversion")

add_subdirectory("${REACT_NATIVE_PATH}/ReactAndroid/src/main/jni/third-party/glog" 
                 "${CMAKE_CURRENT_BINARY_DIR}/glog")

add_subdirectory("${REACT_NATIVE_PATH}/ReactCommon/jsi" 
                 "${CMAKE_CURRENT_BINARY_DIR}/jsi")

target_include_directories(BabylonNativeJNI
    PRIVATE "${REACT_NATIVE_PATH}/ReactCommon"
    PRIVATE "${REACT_NATIVE_PATH}/ReactCommon/jsi")

target_link_libraries(BabylonNativeJNI
    GLESv3
    android
    EGL
    log
    jsi # Add jsi here
    -lz
    AndroidExtensions
    AppRuntime
    Canvas
    Console
    GraphicsDevice
    NativeCamera
    NativeEngine
    NativeInput
    NativeOptimizations
    NativeXr
    ScriptLoader
    XMLHttpRequest
    Window)

It looks like this is almost working, Im still struggling with the error that V8JsiRuntime.h is missing. Do you have an idea why that might be missing? It looks like it comes from the configuration of Babylon Native.

/Users/okwasniewski/workspace/Babylon/BabylonNative/Build/Android/RelWithDebInfo/3q27672l/arm64-v8a/_deps/jsruntimehost-src/Core/AppRuntime/Source/AppRuntime_JSI.cpp:5:10: fatal error: 'V8JsiRuntime.h' file not found
#include <V8JsiRuntime.h>
         ^~~~~~~~~~~~~~~~

Also I noticed that the new Babylon Native wrapper doesn't have methods to interface with JSI, should we create new ones? Where we will probably pass some JSI instance etc.? Just how the old Babylon React Native integration worked?

@ryantrem
Copy link
Member

ryantrem commented Dec 2, 2024

Render the Engine View that Babylon Native provides

In a final implementation of all this, we would need to reconcile the differences between the BN Playground engine view and the BRN engine view. The BRN one may have more generic functionality since it was intended to be part of the BRN lib and not just used in the Playground test app.

Regarding JSI and NAPI and Babylon Native - JSI and NAPI are basically both abstractions over JS engines. We have NAPI implementations for V8, JavaScriptCore, and Chakra, but also a NAPI implementation for JSI. This is basically two layers of abstraction, which is not ideal but works. There are some other efforts under way to try to get NAPI directly into RN side by side with JSI, which would simplify the BRN integration, but the timeline on that is unknown. One of the problems we have with the NAPI implementation for JSI is that JSI is not ABI stable, which means any of the code using JSI needs to be in sync with the JSI used in the RN app, which is why BRN has different versions of the binary packages (e.g. @babylonjs/react-native-iosandroid-0-70). Every time there is an ABI breaking change, we have to release a new BRN binary package variant. If BN itself is pre-compiled, that problem moves to the BN repo instead of the BRN repo. @bghgary and I have talked some about the idea of creating an ABI stable wrapper over JSI to side step this problem, and we think it should be possible, but we haven't planned out the work in detail yet.

@okwasniewski
Copy link
Contributor

Thanks @ryantrem,

Looks like merging this PR: facebook/hermes#1377 is going to solve a lot of those issues allowing BN to be precompiled by directly using NodeAPI from Hermes instead of relying on JSI

@ryantrem
Copy link
Member

Well, sort of. That change is for Hermes only. If BRN relied on this, it would only be compatible with Hermes. If a React Native project was using JavaScriptCore for example, they would not be able to use BRN unless they migrated to Hermes. We could consider having this constraint, but in the past we avoided solutions that required a specific JS engine.

@matthargett
Copy link

I totally agree that VM diversity and preserving optionally is critical. While Hermes performs well in many benchmarks, and had a lot of great ideas, it currently performs very poorly in threeJS and Apollo GraphQL hot paths. I'm confident those gaps will close over time, but JSC (and v8) get significantly better performance per watt in their interpreter (no JIT) modes.

Additionally, we have had great competition in JS runtime ecosystem for 16+ years that has resulted in it being the dominant way to make cross-platform apps. Every time an innovation causes one VM to leap ahead, competitors try (and often succeed) to leapfrog it. This will keep happening, and optionality and user freedom is important to preserve.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants