Skip to content

Commit

Permalink
CMake setup for ReactAndroid (#33472)
Browse files Browse the repository at this point in the history
Summary:
Pull Request resolved: #33472

Changes native build of ReactAndroid to CMake instead of ndk-build. Removes a few workarounds around AGP issues with ndk-build which seems to be working with CMake by default.

Changelog: [Changed][Android] - Use CMake to build ReactAndroid module

Reviewed By: cortinico

Differential Revision: D35018803

fbshipit-source-id: af477937ed70a5ddfafef4e6260a397ee9911580
  • Loading branch information
Andrei Shikov authored and facebook-github-bot committed Mar 23, 2022
1 parent 1907bd3 commit e3830dd
Show file tree
Hide file tree
Showing 5 changed files with 174 additions and 42 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ project.xcworkspace
/ReactAndroid/gradlew
/ReactAndroid/gradlew.bat
/ReactAndroid/hermes-engine/build/
/ReactAndroid/hermes-engine/.cxx/
/template/android/app/build/
/template/android/build/

Expand Down
74 changes: 34 additions & 40 deletions ReactAndroid/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -215,10 +215,6 @@ def reactNativeArchitectures() {
return value ? value.split(",") : ["armeabi-v7a", "x86", "x86_64", "arm64-v8a"]
}

def ndkBuildJobs() {
return project.findProperty("jobs") ?: Runtime.runtime.availableProcessors()
}

tasks.register("packageReactNdkLibsForBuck") {
dependsOn("packageReactNdkDebugLibsForBuck")
}
Expand Down Expand Up @@ -286,29 +282,48 @@ android {
testInstrumentationRunner("androidx.test.runner.AndroidJUnitRunner")

externalNativeBuild {
ndkBuild {
arguments "NDK_APPLICATION_MK=$projectDir/src/main/jni/Application.mk",
"THIRD_PARTY_NDK_DIR=$thirdPartyNdkDir",
"REACT_COMMON_DIR=$projectDir/../ReactCommon",
"REACT_GENERATED_SRC_DIR=$buildDir/generated/source",
"REACT_SRC_DIR=$projectDir/src/main/java/com/facebook/react",
"APP_STL=c++_shared",
"-j${ndkBuildJobs()}"

if (Os.isFamily(Os.FAMILY_MAC)) {
// This flag will suppress "fcntl(): Bad file descriptor" warnings on local builds.
arguments "--output-sync=none"
}
cmake {
arguments "-DREACT_COMMON_DIR=${rootProject.projectDir}/ReactCommon",
"-DREACT_ANDROID_DIR=$projectDir",
"-DANDROID_STL=c++_shared",
"-DANDROID_TOOLCHAIN=clang",
"-DANDROID_PLATFORM=android-21"

targets "reactnativejni",
"jscexecutor",
"jsijniprofiler",
"reactnativeblob",
"reactperfloggerjni",
"turbomodulejsijni",
"fabricjni"
}
}
ndk {
abiFilters (*reactNativeArchitectures())
}
}

buildTypes {
debug {
externalNativeBuild {
cmake {
targets "hermes-executor-debug"
}
}
}

release {
externalNativeBuild {
cmake {
targets "hermes-executor-release"
}
}
}
}

externalNativeBuild {
ndkBuild {
path "src/main/jni/react/jni/Android.mk"
cmake {
path "src/main/jni/CMakeLists.txt"
}
}

Expand Down Expand Up @@ -407,27 +422,6 @@ afterEvaluate {

// Needed as some of the native sources needs to be downloaded
// before configureNdkBuildDebug could be executed.
reactNativeArchitectures().each { architecture ->
tasks.findByName("configureNdkBuildDebug[${architecture}]")?.configure { dependsOn(preBuild) }
tasks.findByName("configureNdkBuildRelease[${architecture}]")?.configure { dependsOn(preBuild) }
}
configureNdkBuildDebug.dependsOn(preBuild)
configureNdkBuildRelease.dependsOn(preBuild)

// As we're consuming Hermes via Prefab, we're using the AGP C++ reference feature
// which is supposed to work for CMake only, we need to introduce an explicit dependency
// on publishing libraries prefab tasks.
// See https://developer.android.com/studio/releases/gradle-plugin?buildsystem=ndk-build#cpp-references.
// If we don't do this, the `configureNdkBuild*` is flaky and fails if the `prefabDebugPackage`
// is not yet executed.
// This can be safely removed once we move to CMake or once AGP supports C++ references on ndk-build.
configureNdkBuildDebug.dependsOn(":ReactAndroid:hermes-engine:prefabDebugPackage")
configureNdkBuildRelease.dependsOn(":ReactAndroid:hermes-engine:prefabReleasePackage")
reactNativeArchitectures().each { architecture ->
tasks.findByName("configureNdkBuildDebug[${architecture}]")?.configure { dependsOn(":ReactAndroid:hermes-engine:prefabDebugPackage") }
tasks.findByName("configureNdkBuildRelease[${architecture}]")?.configure { dependsOn(":ReactAndroid:hermes-engine:prefabReleasePackage") }
}

publishing {
publications {
release(MavenPublication) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# 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_RECURSE jsijniprofiler_SRC CONFIGURE_DEPENDS *.cpp)

add_library(
jsijniprofiler
SHARED
${jsijniprofiler_SRC}
)
target_compile_options(
jsijniprofiler
PRIVATE
-fexceptions
)
target_include_directories(jsijniprofiler PRIVATE .)
target_link_libraries(
jsijniprofiler
fb
fbjni
jsireact
folly_runtime
hermes-engine::libhermes
jsi
reactnativejni
)
102 changes: 102 additions & 0 deletions ReactAndroid/src/main/jni/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
# 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)

project(ReactAndroid)

# Make sure every shared lib includes a .note.gnu.build-id header
add_link_options(-Wl,--build-id)
add_compile_options(-Wall -Werror -std=c++1y)

function(add_react_android_subdir relative_path)
add_subdirectory(${REACT_ANDROID_DIR}/${relative_path} ReactAndroid/${relative_path})
endfunction()

function(add_react_third_party_ndk_subdir relative_path)
add_react_android_subdir(build/third-party-ndk/${relative_path})
endfunction()

function(add_react_common_subdir relative_path)
add_subdirectory(${REACT_COMMON_DIR}/${relative_path} ReactCommon/${relative_path})
endfunction()

# Third-party prefabs
find_package(hermes-engine REQUIRED CONFIG)

# Third-party downloaded targets
add_react_third_party_ndk_subdir(glog)
add_react_third_party_ndk_subdir(boost)
add_react_third_party_ndk_subdir(double-conversion)
add_react_third_party_ndk_subdir(fmt)
add_react_third_party_ndk_subdir(libevent)
add_react_third_party_ndk_subdir(folly)
add_react_third_party_ndk_subdir(jsc)

# Common targets
add_react_common_subdir(yoga)
add_react_common_subdir(runtimeexecutor)
add_react_common_subdir(reactperflogger)
add_react_common_subdir(logger)
add_react_common_subdir(jsiexecutor)
add_react_common_subdir(cxxreact)
add_react_common_subdir(jsi)
add_react_common_subdir(butter)
add_react_common_subdir(callinvoker)
add_react_common_subdir(jsinspector)
add_react_common_subdir(hermes/executor)
add_react_common_subdir(hermes/inspector)
add_react_common_subdir(react/renderer/runtimescheduler)
add_react_common_subdir(react/debug)
add_react_common_subdir(react/config)
add_react_common_subdir(react/renderer/animations)
add_react_common_subdir(react/renderer/attributedstring)
add_react_common_subdir(react/renderer/componentregistry)
add_react_common_subdir(react/renderer/mounting)
add_react_common_subdir(react/renderer/scheduler)
add_react_common_subdir(react/renderer/telemetry)
add_react_common_subdir(react/renderer/templateprocessor)
add_react_common_subdir(react/renderer/uimanager)
add_react_common_subdir(react/renderer/core)
add_react_common_subdir(react/renderer/graphics)
add_react_common_subdir(react/renderer/debug)
add_react_common_subdir(react/renderer/imagemanager)
add_react_common_subdir(react/renderer/components/view)
add_react_common_subdir(react/renderer/components/switch)
add_react_common_subdir(react/renderer/components/textinput)
add_react_common_subdir(react/renderer/components/progressbar)
add_react_common_subdir(react/renderer/components/slider)
add_react_common_subdir(react/renderer/components/root)
add_react_common_subdir(react/renderer/components/image)
add_react_common_subdir(react/renderer/componentregistry/native)
add_react_common_subdir(react/renderer/components/text)
add_react_common_subdir(react/renderer/components/unimplementedview)
add_react_common_subdir(react/renderer/components/modal)
add_react_common_subdir(react/renderer/components/scrollview)
add_react_common_subdir(react/renderer/leakchecker)
add_react_common_subdir(react/renderer/textlayoutmanager)
add_react_common_subdir(react/utils)
add_react_common_subdir(react/bridging)
add_react_common_subdir(react/renderer/mapbuffer)
add_react_common_subdir(react/nativemodule/core)

# ReactAndroid JNI targets
add_react_android_subdir(build/generated/source/codegen/jni)
add_react_android_subdir(src/main/java/com/facebook/hermes/reactexecutor)
add_react_android_subdir(src/main/jni/first-party/fbjni)
add_react_android_subdir(src/main/jni/first-party/fb)
add_react_android_subdir(src/main/jni/first-party/fbgloginit)
add_react_android_subdir(src/main/jni/first-party/yogajni)
add_react_android_subdir(src/main/jni/react/jni)
add_react_android_subdir(src/main/java/com/facebook/react/reactperflogger/jni)
add_react_android_subdir(src/main/java/com/facebook/react/jscexecutor)
add_react_android_subdir(src/main/java/com/facebook/react/turbomodule/core/jni)
add_react_android_subdir(src/main/java/com/facebook/react/uimanager/jni)
add_react_android_subdir(src/main/java/com/facebook/react/common/mapbuffer/jni)
add_react_android_subdir(src/main/java/com/facebook/react/fabric/jni)
add_react_android_subdir(src/main/java/com/facebook/react/modules/blob/jni)
add_react_android_subdir(src/main/java/com/facebook/hermes/instrumentation/)

8 changes: 6 additions & 2 deletions ReactCommon/runtimeexecutor/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ set(CMAKE_VERBOSE_MAKEFILE on)

add_compile_options(-fexceptions -frtti -std=c++17 -Wall)

add_library(runtimeexecutor INTERFACE)
file(GLOB_RECURSE runtimeexecutor_SRC CONFIGURE_DEPENDS *.cpp *.h)

target_include_directories(runtimeexecutor INTERFACE .)
add_library(runtimeexecutor SHARED ${runtimeexecutor_SRC})

target_include_directories(runtimeexecutor PUBLIC .)

target_link_libraries(runtimeexecutor jsi)

0 comments on commit e3830dd

Please sign in to comment.