From e3830ddffd9260fe071e0c9f9df40b379d54cf26 Mon Sep 17 00:00:00 2001 From: Andrei Shikov Date: Wed, 23 Mar 2022 11:18:54 -0700 Subject: [PATCH] CMake setup for ReactAndroid (#33472) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/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 --- .gitignore | 1 + ReactAndroid/build.gradle | 72 ++++++------- .../hermes/instrumentation/CMakeLists.txt | 31 ++++++ ReactAndroid/src/main/jni/CMakeLists.txt | 102 ++++++++++++++++++ ReactCommon/runtimeexecutor/CMakeLists.txt | 8 +- 5 files changed, 173 insertions(+), 41 deletions(-) create mode 100644 ReactAndroid/src/main/java/com/facebook/hermes/instrumentation/CMakeLists.txt create mode 100644 ReactAndroid/src/main/jni/CMakeLists.txt diff --git a/.gitignore b/.gitignore index 0ad070d45ae..35da812e054 100644 --- a/.gitignore +++ b/.gitignore @@ -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/ diff --git a/ReactAndroid/build.gradle b/ReactAndroid/build.gradle index 1e531e54f78..576b931f699 100644 --- a/ReactAndroid/build.gradle +++ b/ReactAndroid/build.gradle @@ -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") } @@ -286,19 +282,20 @@ 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()}" + cmake { + arguments "-DREACT_COMMON_DIR=${rootProject.projectDir}/ReactCommon", + "-DREACT_ANDROID_DIR=$projectDir", + "-DANDROID_STL=c++_shared", + "-DANDROID_TOOLCHAIN=clang", + "-DANDROID_PLATFORM=android-21" - if (Os.isFamily(Os.FAMILY_MAC)) { - // This flag will suppress "fcntl(): Bad file descriptor" warnings on local builds. - arguments "--output-sync=none" - } + targets "reactnativejni", + "jscexecutor", + "jsijniprofiler", + "reactnativeblob", + "reactperfloggerjni", + "turbomodulejsijni", + "fabricjni" } } ndk { @@ -306,9 +303,27 @@ android { } } + 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" } } @@ -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) { diff --git a/ReactAndroid/src/main/java/com/facebook/hermes/instrumentation/CMakeLists.txt b/ReactAndroid/src/main/java/com/facebook/hermes/instrumentation/CMakeLists.txt new file mode 100644 index 00000000000..525d86ad721 --- /dev/null +++ b/ReactAndroid/src/main/java/com/facebook/hermes/instrumentation/CMakeLists.txt @@ -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 +) diff --git a/ReactAndroid/src/main/jni/CMakeLists.txt b/ReactAndroid/src/main/jni/CMakeLists.txt new file mode 100644 index 00000000000..9629ebf5408 --- /dev/null +++ b/ReactAndroid/src/main/jni/CMakeLists.txt @@ -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/) + diff --git a/ReactCommon/runtimeexecutor/CMakeLists.txt b/ReactCommon/runtimeexecutor/CMakeLists.txt index 037d7ec3b7e..b07e6b63625 100644 --- a/ReactCommon/runtimeexecutor/CMakeLists.txt +++ b/ReactCommon/runtimeexecutor/CMakeLists.txt @@ -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)