Skip to content

Commit

Permalink
Further simplify the New App Template by don't requiring the dynamic …
Browse files Browse the repository at this point in the history
…library name (facebook#34671)

Summary:
Pull Request resolved: facebook#34671

I'm simplifying the template further by:
- Do not expose a configurable dynamic library name. Let's use `appmodules`
and still allow the users to configure it, if needed.
- Move all the initialization logic inside the `JNI_OnLoad` method
- Cleanup the `DefaultReactNativeHost` to don't require a dynamic library
name but just a boolean.

Changelog:
[Android] [Changed] - Further simplify the New App Template by don't requiring the dynamic library name

Reviewed By: cipolleschi

Differential Revision: D39462948

fbshipit-source-id: 737733fc263162a0baf3b7a451e48b8616679d3b
  • Loading branch information
cortinico authored and OlimpiaZurek committed May 22, 2023
1 parent 7b6ea2e commit 52017ef
Show file tree
Hide file tree
Showing 12 changed files with 53 additions and 144 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import com.facebook.react.fabric.ComponentFactory
* implementation of its native methods.
*
* This class works together with the [DefaultNativeEntryPoint] and it's C++ implementation is
* hosted inside the React Native framwork
* hosted inside the React Native framework
*/
@DoNotStrip
class DefaultComponentsRegistry
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@

package com.facebook.react.defaults

import com.facebook.jni.HybridData
import com.facebook.proguard.annotations.DoNotStrip
import com.facebook.soloader.SoLoader

/**
Expand All @@ -18,22 +16,14 @@ import com.facebook.soloader.SoLoader
* This class needs to be invoked as `DefaultNativeEntryPoint.load("...")` by passing the name of
* the dynamic library to load.
*
* This class works together with the [DefaultNativeEntryPoint] and it's C++ implementation is
* hosted inside the React Native framework
* By default it loads a library called `appmodules`. `appmodules` is a convention used to refer to
* the application dynamic library. If changed here should be updated also inside the template.
*/
@DoNotStrip
class DefaultNativeEntryPoint @DoNotStrip private constructor() {

@DoNotStrip private val hybridData: HybridData = initHybrid()

@DoNotStrip private external fun initHybrid(): HybridData

companion object {
@JvmStatic
fun load(dynamicLibraryName: String) {
SoLoader.loadLibrary("react_newarchdefaults")
SoLoader.loadLibrary(dynamicLibraryName)
DefaultNativeEntryPoint()
}
object DefaultNativeEntryPoint {
@JvmStatic
@JvmOverloads
fun load(dynamicLibraryName: String = "appmodules") {
SoLoader.loadLibrary("react_newarchdefaults")
SoLoader.loadLibrary(dynamicLibraryName)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,29 +25,27 @@ abstract class DefaultReactNativeHost protected constructor(application: Applica

override fun getReactPackageTurboModuleManagerDelegateBuilder():
ReactPackageTurboModuleManagerDelegate.Builder? =
dynamicLibraryName?.let {
// If the user provided a dynamic library name, we assume they want to load
// the default ReactPackageTurboModuleManagerDelegate
if (isNewArchEnabled) {
DefaultTurboModuleManagerDelegate.Builder()
} else {
null
}

override fun getJSIModulePackage(): JSIModulePackage? =
dynamicLibraryName?.let {
// If the user provided a dynamic library name, we assume they want to load
// the default JSIModulePackage
if (isNewArchEnabled) {
DefaultJSIModulePackage(this)
} else {
null
}

/**
* Returns the name of the dynamic library used by app on the New Architecture. This is generally
* "<applicationname>_appmodules" or just "appmodules"
* Returns whether the user wants to use the New Architecture or not.
*
* If null, we will assume you're not using the New Architecture and will not attempt to load any
* dynamic library at runtime.
* If true, we will load the default JSI Module Package and TurboModuleManagerDelegate needed to
* enable the New Architecture
*
* If set, we'll take care of create a TurboModuleManagerDelegate that will load the library you
* specified.
* If false, the app will not attempt to load the New Architecture modules.
*/
protected open val dynamicLibraryName: String?
get() = null
protected open val isNewArchEnabled: Boolean
get() = false
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import com.facebook.react.bridge.ReactApplicationContext
* [ReactPackageTurboModuleManagerDelegate] for new apps in Open Source.
*
* This class works together with the [DefaultNativeEntryPoint] and it's C++ implementation is
* hosted inside the React Native framwork
* hosted inside the React Native framework
*/
class DefaultTurboModuleManagerDelegate
private constructor(context: ReactApplicationContext, packages: List<ReactPackage>) :
Expand Down
9 changes: 0 additions & 9 deletions packages/rn-tester/android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -123,13 +123,6 @@ def reactNativeArchitectures() {
return value ? value.split(",") : ["armeabi-v7a", "x86", "x86_64", "arm64-v8a"]
}

/**
* The name of the dynamic library for this application. This will contain all the
* compiled C++ code and will be loaded at runtime.
* For RN tester is "rntester_appmodules" so that we'll have a `librntester_appmodules.so` to load.
*/
def dynamicLibraryName = "rntester_appmodules"

android {
buildToolsVersion = "31.0.0"
compileSdkVersion 31
Expand Down Expand Up @@ -161,7 +154,6 @@ android {
versionName "1.0"
testBuildType System.getProperty('testBuildType', 'debug') // This will later be used to control the test apk build type
testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner'
buildConfigField("String", "DYNAMIC_LIBRARY_NAME", "\"$dynamicLibraryName\"")
}
signingConfigs {
release {
Expand Down Expand Up @@ -249,7 +241,6 @@ android {
"-DPROJECT_BUILD_DIR=$buildDir",
"-DREACT_ANDROID_DIR=$reactAndroidProjectDir",
"-DREACT_ANDROID_BUILD_DIR=$reactAndroidBuildDir",
"-DTARGET_NAME=$dynamicLibraryName",
"-DANDROID_STL=c++_shared"
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,8 +112,8 @@ public List<ViewManager> createViewManagers(
}

@Override
public String getDynamicLibraryName() {
return BuildConfig.DYNAMIC_LIBRARY_NAME;
protected boolean isNewArchEnabled() {
return true;
}
};

Expand All @@ -123,7 +123,7 @@ public void onCreate() {
ReactFontManager.getInstance().addCustomFont(this, "Rubik", R.font.rubik);
super.onCreate();
SoLoader.init(this, /* native exopackage */ false);
DefaultNativeEntryPoint.load(BuildConfig.DYNAMIC_LIBRARY_NAME);
DefaultNativeEntryPoint.load();
ReactNativeFlipper.initializeFlipper(this, getReactNativeHost().getReactInstanceManager());
}

Expand Down
4 changes: 2 additions & 2 deletions packages/rn-tester/android/app/src/main/jni/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@

cmake_minimum_required(VERSION 3.13)

# Define the library name here.
project(${TARGET_NAME})
# Define the application dynamic library name here.
project(appmodules)

include(${REACT_ANDROID_DIR}/cmake-utils/ReactNative-application.cmake)

Expand Down
50 changes: 12 additions & 38 deletions packages/rn-tester/android/app/src/main/jni/OnLoad.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,18 +14,16 @@
#include <react/renderer/components/AppSpecs/ComponentDescriptors.h>
#include <rncore.h>

namespace facebook {
namespace react {

void registerComponents(
std::shared_ptr<ComponentDescriptorProviderRegistry const> registry) {
registry->add(concreteComponentDescriptorProvider<
RNTMyNativeViewComponentDescriptor>());
std::shared_ptr<facebook::react::ComponentDescriptorProviderRegistry const>
registry) {
registry->add(facebook::react::concreteComponentDescriptorProvider<
facebook::react::RNTMyNativeViewComponentDescriptor>());
}

std::shared_ptr<TurboModule> provideModules(
std::shared_ptr<facebook::react::TurboModule> provideModules(
const std::string &name,
const JavaTurboModule::InitParams &params) {
const facebook::react::JavaTurboModule::InitParams &params) {
auto module = AppSpecs_ModuleProvider(name, params);
if (module != nullptr) {
return module;
Expand All @@ -37,35 +35,11 @@ std::shared_ptr<TurboModule> provideModules(
return rncore_ModuleProvider(name, params);
}

class RNTesterNativeEntryPoint
: public facebook::jni::HybridClass<RNTesterNativeEntryPoint> {
public:
constexpr static auto kJavaDescriptor =
"Lcom/facebook/react/defaults/DefaultNativeEntryPoint;";

static jni::local_ref<jhybriddata> initHybrid(jni::alias_ref<jhybridobject>) {
DefaultTurboModuleManagerDelegate::moduleProvidersFromEntryPoint =
&provideModules;
DefaultComponentsRegistry::registerComponentDescriptorsFromEntryPoint =
&registerComponents;
return makeCxxInstance();
}

static void registerNatives() {
registerHybrid({
makeNativeMethod("initHybrid", RNTesterNativeEntryPoint::initHybrid),
});
}

private:
friend HybridBase;
using HybridBase::HybridBase;
};

} // namespace react
} // namespace facebook

JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *) {
return facebook::jni::initialize(
vm, [] { facebook::react::RNTesterNativeEntryPoint::registerNatives(); });
return facebook::jni::initialize(vm, [] {
facebook::react::DefaultTurboModuleManagerDelegate::
moduleProvidersFromEntryPoint = &provideModules;
facebook::react::DefaultComponentsRegistry::
registerComponentDescriptorsFromEntryPoint = &registerComponents;
});
}
9 changes: 0 additions & 9 deletions template/android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -129,13 +129,6 @@ def reactNativeArchitectures() {
return value ? value.split(",") : ["armeabi-v7a", "x86", "x86_64", "arm64-v8a"]
}

/**
* The name of the dynamic library for this application. This will contain all the
* compiled C++ code and will be loaded at runtime.
* The default is "appmodules" so that we'll have a `libappmodules.so` to load.
*/
def dynamicLibraryName = "appmodules"

android {
ndkVersion rootProject.ext.ndkVersion

Expand All @@ -148,7 +141,6 @@ android {
versionCode 1
versionName "1.0"
buildConfigField "boolean", "IS_NEW_ARCHITECTURE_ENABLED", isNewArchitectureEnabled().toString()
buildConfigField "String", "DYNAMIC_LIBRARY_NAME", "\"$dynamicLibraryName\""

if (isNewArchitectureEnabled()) {
// We configure the CMake build only if you decide to opt-in for the New Architecture.
Expand All @@ -157,7 +149,6 @@ android {
arguments "-DPROJECT_BUILD_DIR=$buildDir",
"-DREACT_ANDROID_DIR=$rootDir/../node_modules/react-native/ReactAndroid",
"-DREACT_ANDROID_BUILD_DIR=$rootDir/../node_modules/react-native/ReactAndroid/build",
"-DTARGET_NAME=$dynamicLibraryName",
"-DANDROID_STL=c++_shared"
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,15 +35,8 @@ protected String getJSMainModuleName() {
}

@Override
public String getDynamicLibraryName() {
// If you enabled the New Architecture, you need to return the name of the
// dynamic library to load (usually 'appmodule'). This is configured
// in your build.gradle file.
if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) {
return BuildConfig.DYNAMIC_LIBRARY_NAME;
} else {
return null;
}
protected boolean isNewArchEnabled() {
return BuildConfig.IS_NEW_ARCHITECTURE_ENABLED;
}
};

Expand All @@ -60,7 +53,7 @@ public void onCreate() {
// If you opted-in for the New Architecture, we enable the TurboModule system
// and load the native entry point for this app.
ReactFeatureFlags.useTurboModules = true;
DefaultNativeEntryPoint.load(BuildConfig.DYNAMIC_LIBRARY_NAME);
DefaultNativeEntryPoint.load();
}
ReactNativeFlipper.initializeFlipper(this, getReactNativeHost().getReactInstanceManager());
}
Expand Down
2 changes: 1 addition & 1 deletion template/android/app/src/main/jni/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
cmake_minimum_required(VERSION 3.13)

# Define the library name here.
project(${TARGET_NAME})
project(appmodules)

# This file includes all the necessary to let you build your application with the New Architecture.
include(${REACT_ANDROID_DIR}/cmake-utils/ReactNative-application.cmake)
48 changes: 10 additions & 38 deletions template/android/app/src/main/jni/OnLoad.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,24 +4,22 @@
#include <react/renderer/componentregistry/ComponentDescriptorProviderRegistry.h>
#include <rncli.h>

namespace facebook {
namespace react {

void registerComponents(
std::shared_ptr<ComponentDescriptorProviderRegistry const> registry) {
std::shared_ptr<facebook::react::ComponentDescriptorProviderRegistry const>
registry) {
// Custom Fabric Components go here. You can register custom
// components coming from your App or from 3rd party libraries here.
//
// providerRegistry->add(concreteComponentDescriptorProvider<
// AocViewerComponentDescriptor>());

// By default we just use the components autolinked by RN CLI
rncli_registerProviders(registry);
facebook::react::rncli_registerProviders(registry);
}

std::shared_ptr<TurboModule> provideModules(
std::shared_ptr<facebook::react::TurboModule> provideModules(
const std::string &name,
const JavaTurboModule::InitParams &params) {
const facebook::react::JavaTurboModule::InitParams &params) {
// Here you can provide your own module provider for TurboModules coming from
// either your application or from external libraries. The approach to follow
// is similar to the following (for a library called `samplelibrary`):
Expand All @@ -33,40 +31,14 @@ std::shared_ptr<TurboModule> provideModules(
// return rncore_ModuleProvider(moduleName, params);

// By default we just use the module providers autolinked by RN CLI
return rncli_ModuleProvider(name, params);
return facebook::react::rncli_ModuleProvider(name, params);
}

class MainApplicationNativeEntryPoint
: public facebook::jni::HybridClass<MainApplicationNativeEntryPoint> {
public:
constexpr static auto kJavaDescriptor =
"Lcom/facebook/react/defaults/DefaultNativeEntryPoint;";

static jni::local_ref<jhybriddata> initHybrid(jni::alias_ref<jhybridobject>) {
DefaultTurboModuleManagerDelegate::moduleProvidersFromEntryPoint =
&provideModules;
DefaultComponentsRegistry::registerComponentDescriptorsFromEntryPoint =
&registerComponents;
return makeCxxInstance();
}

static void registerNatives() {
registerHybrid({
makeNativeMethod(
"initHybrid", MainApplicationNativeEntryPoint::initHybrid),
});
}

private:
friend HybridBase;
using HybridBase::HybridBase;
};

} // namespace react
} // namespace facebook

JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *) {
return facebook::jni::initialize(vm, [] {
facebook::react::MainApplicationNativeEntryPoint::registerNatives();
facebook::react::DefaultTurboModuleManagerDelegate::
moduleProvidersFromEntryPoint = &provideModules;
facebook::react::DefaultComponentsRegistry::
registerComponentDescriptorsFromEntryPoint = &registerComponents;
});
}

0 comments on commit 52017ef

Please sign in to comment.