Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -53,4 +53,4 @@ DEPENDENCIES
xcodeproj!

BUNDLED WITH
2.2.22
2.3.11
128 changes: 114 additions & 14 deletions android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,17 @@ buildscript {

plugins {
id("com.android.application")
id("kotlin-android")
id("kotlin-kapt")
id("org.jetbrains.kotlin.android") version "${kotlinVersion}"
id("org.jetbrains.kotlin.kapt") version "${kotlinVersion}"
}

// `react-native run-android` is hard-coded to look for the output APK at a very
// specific location. See
// https://github.com/react-native-community/cli/blob/6cf12b00c02aca6d4bc843446394331d71a9749e/packages/platform-android/src/commands/runAndroid/index.ts#L180
buildDir = "${rootDir}/${name}/build"

def reactNativeDir = findNodeModulesPath(rootDir, "react-native")
def reactNativeVersion = getReactNativeVersionNumber(rootDir)
def reactNativeDir = findNodeModulesPath("react-native", rootDir)
def reactNativeVersion = getPackageVersionNumber("react-native", rootDir)

repositories {
maven {
Expand Down Expand Up @@ -51,21 +51,23 @@ apply(from: "${projectDir}/../../test-app.gradle")
applyTestAppModule(project)

project.ext.react = [
appName : getAppName(),
applicationId: getApplicationId(),
enableFabric : isFabricEnabled(rootDir),
enableFlipper: getFlipperVersion(rootDir),
enableHermes : true,
abiSplit : false,
appName : getAppName(),
applicationId : getApplicationId(),
architectures : ["arm64-v8a", "armeabi-v7a", "x86", "x86_64"],
enableFabric : isFabricEnabled(project),
enableFlipper : getFlipperVersion(rootDir),
enableHermes : true,
enableNewArchitecture: isNewArchitectureEnabled(project),
]

project.ext.signingConfigs = getSigningConfigs()

android {
compileSdkVersion project.ext.compileSdkVersion

// We need only set `ndkVersion` when building react-native from source.
if (hasProperty("ANDROID_NDK_VERSION")) {
ndkVersion ANDROID_NDK_VERSION
if (project.hasProperty("ndkVersion")) {
ndkVersion project.ext.ndkVersion
}

// TODO: Remove this block when minSdkVersion >= 24. See
Expand Down Expand Up @@ -106,6 +108,69 @@ android {
resValue "string", "app_name", project.ext.react.appName

testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"

if (project.ext.react.enableNewArchitecture) {
externalNativeBuild {
ndkBuild {
arguments "APP_PLATFORM=android-${project.ext.minSdkVersion}",
"APP_STL=c++_shared",
"NDK_TOOLCHAIN_VERSION=clang",
"GENERATED_SRC_DIR=${buildDir}/generated/source",
"NODE_MODULES_DIR=${reactNativeDir}/..",
"PROJECT_BUILD_DIR=${buildDir}",
"REACT_ANDROID_DIR=${reactNativeDir}/ReactAndroid",
"REACT_ANDROID_BUILD_DIR=${reactNativeDir}/ReactAndroid/build"
cFlags "-Wall", "-Werror", "-frtti", "-fexceptions", "-DWITH_INSPECTOR=1"
cppFlags "-std=c++17"
targets "reacttestapp_appmodules"
}
}
if (!project.ext.react.abiSplit) {
ndk {
abiFilters(*project.ext.react.architectures)
}
}
}
}

if (project.ext.react.enableNewArchitecture) {
externalNativeBuild {
ndkBuild {
path "${projectDir}/src/main/jni/Android.mk"
}
}

def reactAndroidProjectDir = project(":ReactAndroid").projectDir
def packageReactNdkDebugLibs = tasks.register("packageReactNdkDebugLibs", Copy) {
dependsOn(":ReactAndroid:packageReactNdkDebugLibsForBuck")
from("${reactAndroidProjectDir}/src/main/jni/prebuilt/lib")
into("${buildDir}/react-ndk/exported")
}
def packageReactNdkReleaseLibs = tasks.register("packageReactNdkReleaseLibs", Copy) {
dependsOn(":ReactAndroid:packageReactNdkReleaseLibsForBuck")
from("${reactAndroidProjectDir}/src/main/jni/prebuilt/lib")
into("${buildDir}/react-ndk/exported")
}

afterEvaluate {
preDebugBuild.dependsOn(packageReactNdkDebugLibs)
preReleaseBuild.dependsOn(packageReactNdkReleaseLibs)

// Due to a bug in AGP, we have to explicitly set a dependency
// between configureNdkBuild* tasks and the preBuild tasks. This can
// be removed once this issue is resolved:
// https://issuetracker.google.com/issues/207403732
configureNdkBuildRelease.dependsOn(preReleaseBuild)
configureNdkBuildDebug.dependsOn(preDebugBuild)
project.ext.react.architectures.each { architecture ->
tasks.findByName("configureNdkBuildDebug[${architecture}]")?.configure {
dependsOn("preDebugBuild")
}
tasks.findByName("configureNdkBuildRelease[${architecture}]")?.configure {
dependsOn("preReleaseBuild")
}
}
}
}

lintOptions {
Expand Down Expand Up @@ -154,6 +219,13 @@ android {
main.java.srcDirs += "src/no-fabric/java"
}

// TODO: Remove this block when we drop support for 0.65.
if (project.ext.react.enableNewArchitecture) {
main.java.srcDirs += "src/turbomodule/java"
} else {
main.java.srcDirs += "src/no-turbomodule/java"
}

// TODO: Remove this block when we drop support for 0.67.
// https://github.com/facebook/react-native/commit/ce74aa4ed335d4c36ce722d47937b582045e05c4
if (reactNativeVersion < 6800) {
Expand All @@ -162,6 +234,15 @@ android {
main.java.srcDirs += "src/reactinstanceeventlistener-0.68/java"
}
}

splits {
abi {
reset()
enable(project.ext.react.abiSplit)
universalApk(false)
include(*project.ext.react.architectures)
}
}
}

dependencies {
Expand All @@ -171,8 +252,8 @@ dependencies {
// TODO: Remove this block when we drop support for 0.68.
if (reactNativeVersion < 6900) {
def hermesEngineDir =
findNodeModulesPath(file(reactNativeDir), "hermes-engine")
?: findNodeModulesPath(file(reactNativeDir), "hermesvm")
findNodeModulesPath("hermes-engine", file(reactNativeDir))
?: findNodeModulesPath("hermesvm", file(reactNativeDir))
if (hermesEngineDir == null) {
throw new GradleException("Could not find 'hermes-engine'. Please make sure you've added it to 'package.json'.")
}
Expand Down Expand Up @@ -225,3 +306,22 @@ dependencies {
}
}
}

if (project.ext.react.enableNewArchitecture) {
configurations.all {
resolutionStrategy.dependencySubstitution {
substitute(module("com.facebook.react:react-native"))
.using(project(":ReactAndroid"))
.because("On New Architecture, we are building React Native from source")
substitute(module("com.facebook.react:hermes-engine"))
.using(project(":ReactAndroid:hermes-engine"))
.because("On New Architecture, we are building Hermes from source")
}
}
}

// `@react-native-community/cli` currently requires this function to be defined.
// See https://github.com/react-native-community/cli/blob/a87fb9014635fe84ab19a1a88d6ecbbc530eb4e2/packages/platform-android/native_modules.gradle#L497
def isNewArchitectureEnabled() {
return isFabricEnabled(project)
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ class FabricJSIModulePackage(reactNativeHost: ReactNativeHost) : JSIModulePackag
val componentFactory = ComponentFactory()
CoreComponentsRegistry.register(componentFactory)

ComponentsRegistry.register(componentFactory)

return FabricJSIModuleProvider(
reactApplicationContext,
componentFactory,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@ import android.content.Context
import android.util.Log
import com.facebook.react.PackageList
import com.facebook.react.ReactInstanceManager
import com.facebook.react.ReactNativeHost
import com.facebook.react.ReactPackage
import com.facebook.react.bridge.JSIModulePackage
import com.facebook.react.bridge.ReactContext
import com.facebook.react.bridge.ReactMarker
Expand All @@ -22,6 +20,7 @@ import com.facebook.soloader.SoLoader
import com.microsoft.reacttestapp.BuildConfig
import com.microsoft.reacttestapp.R
import com.microsoft.reacttestapp.compat.ReactInstanceEventListener
import com.microsoft.reacttestapp.compat.ReactNativeHostCompat
import com.microsoft.reacttestapp.fabric.FabricJSIModulePackage
import java.util.concurrent.CountDownLatch

Expand Down Expand Up @@ -49,7 +48,7 @@ sealed class BundleSource {
class TestAppReactNativeHost(
application: Application,
private val reactBundleNameProvider: ReactBundleNameProvider
) : ReactNativeHost(application) {
) : ReactNativeHostCompat(application) {
var source: BundleSource =
if (reactBundleNameProvider.bundleName == null || isPackagerRunning(application)) {
BundleSource.Server
Expand Down Expand Up @@ -166,7 +165,7 @@ class TestAppReactNativeHost(

override fun getUseDeveloperSupport() = source == BundleSource.Server

override fun getPackages(): List<ReactPackage> = PackageList(application).packages
override fun getPackages() = PackageList(application).packages

private fun addCustomDevOptions(devSupportManager: DevSupportManager) {
val bundleOption = application.resources.getString(
Expand Down
58 changes: 58 additions & 0 deletions android/app/src/main/jni/Android.mk
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
THIS_DIR := $(call my-dir)

include $(REACT_ANDROID_DIR)/Android-prebuilt.mk

# If you wish to add a custom TurboModule or Fabric component in your app you
# will have to include the following autogenerated makefile.
# include $(GENERATED_SRC_DIR)/codegen/jni/Android.mk

# Makefile for autolinked libraries
include $(PROJECT_BUILD_DIR)/generated/rncli/src/main/jni/Android-rncli.mk

include $(CLEAR_VARS)

LOCAL_PATH := $(THIS_DIR)

# You can customize the name of your application .so file here.
LOCAL_MODULE := reacttestapp_appmodules

LOCAL_C_INCLUDES := $(LOCAL_PATH)
LOCAL_SRC_FILES := $(wildcard $(LOCAL_PATH)/*.cpp)
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)

# If you wish to add a custom TurboModule or Fabric component in your app you
# will have to uncomment those lines to include the generated source
# files from the codegen (placed in $(GENERATED_SRC_DIR)/codegen/jni)
#
# LOCAL_C_INCLUDES += $(GENERATED_SRC_DIR)/codegen/jni
# LOCAL_SRC_FILES += $(wildcard $(GENERATED_SRC_DIR)/codegen/jni/*.cpp)
# LOCAL_EXPORT_C_INCLUDES += $(GENERATED_SRC_DIR)/codegen/jni

# Autolinked TurboModules and Fabric components
LOCAL_C_INCLUDES += $(PROJECT_BUILD_DIR)/generated/rncli/src/main/jni
LOCAL_SRC_FILES += $(wildcard $(PROJECT_BUILD_DIR)/generated/rncli/src/main/jni/*.cpp)
LOCAL_EXPORT_C_INCLUDES += $(PROJECT_BUILD_DIR)/generated/rncli/src/main/jni

# Here you should add any native library you wish to depend on.
LOCAL_SHARED_LIBRARIES := \
libfabricjni \
libfbjni \
libfolly_runtime \
libglog \
libjsi \
libreact_codegen_rncore \
libreact_debug \
libreact_nativemodule_core \
libreact_render_componentregistry \
libreact_render_core \
libreact_render_debug \
libreact_render_graphics \
librrc_view \
libruntimeexecutor \
libturbomodulejsijni \
libyoga \
$(call import-codegen-modules)

LOCAL_CFLAGS := -std=c++17 -Wall -frtti -fexceptions -DLOG_TAG=\"ReactNative\"

include $(BUILD_SHARED_LIBRARY)
55 changes: 55 additions & 0 deletions android/app/src/main/jni/ComponentsRegistry.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
#include "ComponentsRegistry.h"

#include <CoreComponentsRegistry.h>
#include <rncli.h>

#include <fbjni/fbjni.h>

#include <react/renderer/componentregistry/ComponentDescriptorProviderRegistry.h>
#include <react/renderer/componentregistry/ComponentDescriptorRegistry.h>
#include <react/renderer/components/rncore/ComponentDescriptors.h>

using facebook::react::ComponentDescriptorParameters;
using facebook::react::ComponentDescriptorProviderRegistry;
using facebook::react::ComponentDescriptorRegistry;
using facebook::react::ComponentFactory;
using facebook::react::ContextContainer;
using facebook::react::CoreComponentsRegistry;
using facebook::react::EventDispatcher;
using facebook::react::UnimplementedNativeViewComponentDescriptor;
using ReactTestApp::ComponentsRegistry;

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

ComponentsRegistry::ComponentsRegistry(ComponentFactory *)
{
}

facebook::jni::local_ref<ComponentsRegistry::jhybriddata>
ComponentsRegistry::initHybrid(facebook::jni::alias_ref<jclass>, ComponentFactory *delegate)
{
delegate->buildRegistryFunction = [](EventDispatcher::Weak const &eventDispatcher,
ContextContainer::Shared const &contextContainer)
-> ComponentDescriptorRegistry::Shared {
auto providerRegistry = CoreComponentsRegistry::sharedProviderRegistry();

// Register providers generated by `@react-native-community/cli`
rncli_registerProviders(providerRegistry);

auto registry = providerRegistry->createComponentDescriptorRegistry(
{eventDispatcher, contextContainer});

auto mutableRegistry = std::const_pointer_cast<ComponentDescriptorRegistry>(registry);

mutableRegistry->setFallbackComponentDescriptor(
std::make_shared<UnimplementedNativeViewComponentDescriptor>(
ComponentDescriptorParameters{eventDispatcher, contextContainer, nullptr}));

return registry;
};

return makeCxxInstance(delegate);
}
26 changes: 26 additions & 0 deletions android/app/src/main/jni/ComponentsRegistry.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#ifndef REACTTESTAPP_JNI_COMPONENTSREGISTRY_H_
#define REACTTESTAPP_JNI_COMPONENTSREGISTRY_H_

#include <ComponentFactory.h>

#include <fbjni/fbjni.h>

namespace ReactTestApp
{
class ComponentsRegistry : public facebook::jni::HybridClass<ComponentsRegistry>
{
public:
constexpr static auto kJavaDescriptor =
"Lcom/microsoft/reacttestapp/fabric/ComponentsRegistry;";

static void registerNatives();

ComponentsRegistry(facebook::react::ComponentFactory *delegate);

private:
static facebook::jni::local_ref<ComponentsRegistry::jhybriddata>
initHybrid(facebook::jni::alias_ref<jclass>, facebook::react::ComponentFactory *delegate);
};
} // namespace ReactTestApp

#endif // REACTTESTAPP_JNI_COMPONENTSREGISTRY_H_
15 changes: 15 additions & 0 deletions android/app/src/main/jni/OnLoad.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#include <fbjni/fbjni.h>

#include "ComponentsRegistry.h"
#include "TurboModuleManagerDelegate.h"

using ReactTestApp::ComponentsRegistry;
using ReactTestApp::TurboModuleManagerDelegate;

JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *)
{
return facebook::jni::initialize(vm, [] {
TurboModuleManagerDelegate::registerNatives();
ComponentsRegistry::registerNatives();
});
}
Loading