fix: Support RN 0.69 and use Hermes from source! 🎉 (#1186)
* wip * wip * Update CMakeLists.txt * Update CMakeLists.txt * Update android/build.gradle Co-authored-by: Tomek Zawadzki <tomekzawadzki98@gmail.com> Co-authored-by: Tomek Zawadzki <tomekzawadzki98@gmail.com>
This commit is contained in:
parent
312b82b9f6
commit
205e542cb6
@ -76,27 +76,47 @@ target_include_directories(
|
||||
file (GLOB LIBRN_DIR "${BUILD_DIR}/react-native-0*/jni/${ANDROID_ABI}")
|
||||
|
||||
if(${FOR_HERMES})
|
||||
file (GLOB LIBHERMES_DIR "${BUILD_DIR}/third-party-ndk/hermes/jni/${ANDROID_ABI}")
|
||||
# Use Hermes
|
||||
find_library(
|
||||
JS_ENGINE_LIB
|
||||
hermes
|
||||
PATHS ${LIBHERMES_DIR}
|
||||
NO_CMAKE_FIND_ROOT_PATH
|
||||
)
|
||||
# Use Reanimated Hermes
|
||||
file (GLOB LIBREANIMATED_DIR "${BUILD_DIR}/react-native-reanimated-*-hermes.aar/jni/${ANDROID_ABI}")
|
||||
string(APPEND CMAKE_CXX_FLAGS " -DJS_RUNTIME_HERMES=1")
|
||||
|
||||
if(${REACT_NATIVE_VERSION} LESS 69)
|
||||
# From `hermes-engine` npm package
|
||||
target_include_directories(
|
||||
${PACKAGE_NAME}
|
||||
PRIVATE
|
||||
"${JS_RUNTIME_DIR}/android/include"
|
||||
)
|
||||
else()
|
||||
# Bundled Hermes from module `com.facebook.react:hermes-engine` or project `:ReactAndroid:hermes-engine`
|
||||
target_include_directories(
|
||||
${PACKAGE_NAME}
|
||||
PRIVATE
|
||||
"${JS_RUNTIME_DIR}/API"
|
||||
"${JS_RUNTIME_DIR}/public"
|
||||
)
|
||||
endif()
|
||||
|
||||
target_link_libraries(
|
||||
${PACKAGE_NAME}
|
||||
"${BUILD_DIR}/third-party-ndk/hermes/jni/${ANDROID_ABI}/libhermes.so"
|
||||
)
|
||||
file (GLOB LIBREANIMATED_DIR "${BUILD_DIR}/react-native-reanimated-*-hermes.aar/jni/${ANDROID_ABI}")
|
||||
else()
|
||||
file (GLOB LIBJSC_DIR "${BUILD_DIR}/android-jsc*.aar/jni/${ANDROID_ABI}")
|
||||
# Use JSC
|
||||
find_library(
|
||||
JS_ENGINE_LIB
|
||||
jscexecutor
|
||||
PATHS ${LIBRN_DIR}
|
||||
NO_CMAKE_FIND_ROOT_PATH
|
||||
)
|
||||
# Use Reanimated JSC
|
||||
file (GLOB LIBREANIMATED_DIR "${BUILD_DIR}/react-native-reanimated-*-jsc.aar/jni/${ANDROID_ABI}")
|
||||
file (GLOB LIBJSC_DIR "${BUILD_DIR}/android-jsc*.aar/jni/${ANDROID_ABI}")
|
||||
|
||||
# Use JSC
|
||||
find_library(
|
||||
JS_ENGINE_LIB
|
||||
jscexecutor
|
||||
PATHS ${LIBRN_DIR}
|
||||
NO_CMAKE_FIND_ROOT_PATH
|
||||
)
|
||||
target_link_libraries(
|
||||
${PACKAGE_NAME}
|
||||
${JS_ENGINE_LIB}
|
||||
)
|
||||
|
||||
# Use Reanimated JSC
|
||||
file (GLOB LIBREANIMATED_DIR "${BUILD_DIR}/react-native-reanimated-*-jsc.aar/jni/${ANDROID_ABI}")
|
||||
endif()
|
||||
|
||||
find_library(
|
||||
@ -105,12 +125,22 @@ find_library(
|
||||
PATHS ${LIBRN_DIR}
|
||||
NO_CMAKE_FIND_ROOT_PATH
|
||||
)
|
||||
find_library(
|
||||
FOLLY_JSON_LIB
|
||||
folly_json
|
||||
PATHS ${LIBRN_DIR}
|
||||
NO_CMAKE_FIND_ROOT_PATH
|
||||
)
|
||||
|
||||
if(${REACT_NATIVE_VERSION} LESS 69)
|
||||
find_library(
|
||||
FOLLY_LIB
|
||||
folly_json
|
||||
PATHS ${LIBRN_DIR}
|
||||
NO_CMAKE_FIND_ROOT_PATH
|
||||
)
|
||||
else()
|
||||
find_library(
|
||||
FOLLY_LIB
|
||||
folly_runtime
|
||||
PATHS ${LIBRN_DIR}
|
||||
NO_CMAKE_FIND_ROOT_PATH
|
||||
)
|
||||
endif()
|
||||
|
||||
find_library(
|
||||
REACT_NATIVE_JNI_LIB
|
||||
@ -118,6 +148,7 @@ find_library(
|
||||
PATHS ${LIBRN_DIR}
|
||||
NO_CMAKE_FIND_ROOT_PATH
|
||||
)
|
||||
|
||||
if(${REACT_NATIVE_VERSION} LESS 66)
|
||||
# JSI lib didn't exist on RN 0.65 and before. Simply omit it.
|
||||
set (JSI_LIB "")
|
||||
@ -144,16 +175,14 @@ find_library(
|
||||
)
|
||||
|
||||
# linking
|
||||
|
||||
message(WARNING "VisionCamera linking: FOR_HERMES=${FOR_HERMES}")
|
||||
target_link_libraries(
|
||||
${PACKAGE_NAME}
|
||||
${LOG_LIB}
|
||||
${JSI_LIB}
|
||||
${JS_ENGINE_LIB} # <-- Hermes or JSC
|
||||
${REANIMATED_LIB}
|
||||
${REACT_NATIVE_JNI_LIB}
|
||||
${FBJNI_LIB}
|
||||
${FOLLY_JSON_LIB}
|
||||
${FOLLY_LIB}
|
||||
android
|
||||
)
|
||||
|
@ -16,13 +16,35 @@ static def findNodeModules(baseDir) {
|
||||
}
|
||||
throw new GradleException("VisionCamera: Failed to find node_modules/ path!")
|
||||
}
|
||||
static def findNodeModulePath(baseDir, packageName) {
|
||||
def basePath = baseDir.toPath().normalize()
|
||||
// Node's module resolution algorithm searches up to the root directory,
|
||||
// after which the base path will be null
|
||||
while (basePath) {
|
||||
def candidatePath = Paths.get(basePath.toString(), "node_modules", packageName)
|
||||
if (candidatePath.toFile().exists()) {
|
||||
return candidatePath.toString()
|
||||
}
|
||||
basePath = basePath.getParent()
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
def isNewArchitectureEnabled() {
|
||||
// To opt-in for the New Architecture, you can either:
|
||||
// - Set `newArchEnabled` to true inside the `gradle.properties` file
|
||||
// - Invoke gradle with `-newArchEnabled=true`
|
||||
// - Set an environment variable `ORG_GRADLE_PROJECT_newArchEnabled=true`
|
||||
return project.hasProperty("newArchEnabled") && project.newArchEnabled == "true"
|
||||
}
|
||||
|
||||
def nodeModules = findNodeModules(projectDir)
|
||||
logger.warn("VisionCamera: node_modules/ found at: ${nodeModules}")
|
||||
def reactNative = new File("$nodeModules/react-native")
|
||||
|
||||
def CMAKE_NODE_MODULES_DIR = project.getProjectDir().getParentFile().getParent()
|
||||
def reactProperties = new Properties()
|
||||
file("$nodeModules/react-native/ReactAndroid/gradle.properties").withInputStream { reactProperties.load(it) }
|
||||
def REACT_NATIVE_FULL_VERSION = reactProperties.getProperty("VERSION_NAME")
|
||||
def REACT_NATIVE_VERSION = reactProperties.getProperty("VERSION_NAME").split("\\.")[1].toInteger()
|
||||
|
||||
def FOR_HERMES = System.getenv("FOR_HERMES") == "True"
|
||||
@ -31,6 +53,17 @@ rootProject.getSubprojects().forEach({project ->
|
||||
FOR_HERMES = project.ext.react.enableHermes
|
||||
}
|
||||
})
|
||||
def jsRuntimeDir = {
|
||||
if (FOR_HERMES) {
|
||||
if (REACT_NATIVE_VERSION >= 69) {
|
||||
return Paths.get(CMAKE_NODE_MODULES_DIR, "react-native", "sdks", "hermes")
|
||||
} else {
|
||||
return Paths.get(CMAKE_NODE_MODULES_DIR, "hermes-engine")
|
||||
}
|
||||
} else {
|
||||
return Paths.get(CMAKE_NODE_MODULES_DIR, "react-native", "ReactCommon", "jsi")
|
||||
}
|
||||
}.call()
|
||||
logger.warn("VisionCamera: Building with ${FOR_HERMES ? "Hermes" : "JSC"}...")
|
||||
|
||||
buildscript {
|
||||
@ -67,6 +100,16 @@ def getExtOrIntegerDefault(name) {
|
||||
return rootProject.ext.has(name) ? rootProject.ext.get(name) : (project.properties['VisionCamera_' + name]).toInteger()
|
||||
}
|
||||
|
||||
def resolveBuildType() {
|
||||
def buildType = "debug"
|
||||
tasks.all({ task ->
|
||||
if (task.name == "buildCMakeRelease") {
|
||||
buildType = "release"
|
||||
}
|
||||
})
|
||||
return buildType
|
||||
}
|
||||
|
||||
// plugin.js file only exists since REA v2.
|
||||
def hasReanimated2 = file("${nodeModules}/react-native-reanimated/plugin.js").exists()
|
||||
def disableFrameProcessors = rootProject.ext.has("disableFrameProcessors") ? rootProject.ext.get("disableFrameProcessors").asBoolean() : false
|
||||
@ -99,7 +142,8 @@ android {
|
||||
arguments '-DANDROID_STL=c++_shared',
|
||||
"-DREACT_NATIVE_VERSION=${REACT_NATIVE_VERSION}",
|
||||
"-DNODE_MODULES_DIR=${nodeModules}",
|
||||
"-DFOR_HERMES=${FOR_HERMES}"
|
||||
"-DFOR_HERMES=${FOR_HERMES}",
|
||||
"-DJS_RUNTIME_DIR=${jsRuntimeDir}"
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -228,17 +272,14 @@ dependencies {
|
||||
//noinspection GradleDynamicVersion
|
||||
extractJNI("com.facebook.fbjni:fbjni:+")
|
||||
|
||||
def rnAAR = fileTree("${nodeModules}/react-native/android").matching({ it.include "**/**/*.aar" }).singleFile
|
||||
def rnAarMatcher = "**/react-native/**/*${resolveBuildType()}.aar"
|
||||
if (REACT_NATIVE_VERSION < 69) {
|
||||
rnAarMatcher = "**/**/*.aar"
|
||||
}
|
||||
def rnAAR = fileTree("$reactNative/android").matching({ it.include rnAarMatcher }).singleFile
|
||||
def jscAAR = fileTree("${nodeModules}/jsc-android/dist/org/webkit/android-jsc").matching({ it.include "**/**/*.aar" }).singleFile
|
||||
|
||||
def inputFile = file("${nodeModules}/react-native/package.json")
|
||||
def json = new JsonSlurper().parseText(inputFile.text)
|
||||
def reactNativeVersion = json.version as String
|
||||
def (major, minor, patch) = reactNativeVersion.tokenize('.')
|
||||
|
||||
def jsEngine = FOR_HERMES ? "hermes" : "jsc"
|
||||
def reaAAR = "${nodeModules}/react-native-reanimated/android/react-native-reanimated-${minor}-${jsEngine}.aar"
|
||||
|
||||
def reaAAR = "${nodeModules}/react-native-reanimated/android/react-native-reanimated-${REACT_NATIVE_VERSION}-${jsEngine}.aar"
|
||||
extractJNI(files(rnAAR, jscAAR, reaAAR))
|
||||
}
|
||||
|
||||
@ -285,7 +326,12 @@ if (ENABLE_FRAME_PROCESSORS) {
|
||||
}
|
||||
|
||||
task downloadBoost(dependsOn: createNativeDepsDirectories, type: Download) {
|
||||
src("https://github.com/react-native-community/boost-for-react-native/releases/download/v${BOOST_VERSION.replace("_", ".")}-0/boost_${BOOST_VERSION}.tar.gz")
|
||||
def transformedVersion = BOOST_VERSION.replace("_", ".")
|
||||
def srcUrl = "https://boostorg.jfrog.io/artifactory/main/release/${transformedVersion}/source/boost_${BOOST_VERSION}.tar.gz"
|
||||
if (REACT_NATIVE_VERSION < 69) {
|
||||
srcUrl = "https://github.com/react-native-community/boost-for-react-native/releases/download/v${transformedVersion}-0/boost_${BOOST_VERSION}.tar.gz"
|
||||
}
|
||||
src(srcUrl)
|
||||
onlyIfNewer(true)
|
||||
overwrite(false)
|
||||
dest(boost_file)
|
||||
@ -394,26 +440,95 @@ if (ENABLE_FRAME_PROCESSORS) {
|
||||
|
||||
prepareThirdPartyNdkHeaders.mustRunAfter createNativeDepsDirectories
|
||||
|
||||
/*
|
||||
COPY-PASTE from react-native-reanimated.
|
||||
Vision Camera includes "hermes/hermes.h" header file in `NativeProxy.cpp`.
|
||||
Previously, we used header files from `hermes-engine` package in `node_modules`.
|
||||
Starting from React Native 0.69, Hermes is no longer distributed as package on NPM.
|
||||
On the new architecture, Hermes is downloaded from GitHub and then compiled from sources.
|
||||
However, on the old architecture, we need to download Hermes header files on our own
|
||||
as well as unzip Hermes AAR in order to obtain `libhermes.so` shared library.
|
||||
For more details, see https://reactnative.dev/architecture/bundled-hermes
|
||||
or https://github.com/reactwg/react-native-new-architecture/discussions/4
|
||||
*/
|
||||
if (REACT_NATIVE_VERSION >= 69 && !isNewArchitectureEnabled()) {
|
||||
// copied from `react-native/ReactAndroid/hermes-engine/build.gradle`
|
||||
|
||||
def customDownloadDir = System.getenv("REACT_NATIVE_DOWNLOADS_DIR")
|
||||
def downloadDir = customDownloadDir ? new File(customDownloadDir) : new File(reactNative, "sdks/download")
|
||||
|
||||
// By default we are going to download and unzip hermes inside the /sdks/hermes folder
|
||||
// but you can provide an override for where the hermes source code is located.
|
||||
def hermesDir = System.getenv("REACT_NATIVE_OVERRIDE_HERMES_DIR") ?: new File(reactNative, "sdks/hermes")
|
||||
|
||||
def hermesVersion = "main"
|
||||
def hermesVersionFile = new File(reactNative, "sdks/.hermesversion")
|
||||
if (hermesVersionFile.exists()) {
|
||||
hermesVersion = hermesVersionFile.text
|
||||
}
|
||||
|
||||
task downloadHermes(type: Download) {
|
||||
src("https://github.com/facebook/hermes/tarball/${hermesVersion}")
|
||||
onlyIfNewer(true)
|
||||
overwrite(false)
|
||||
dest(new File(downloadDir, "hermes.tar.gz"))
|
||||
}
|
||||
|
||||
task unzipHermes(dependsOn: downloadHermes, type: Copy) {
|
||||
from(tarTree(downloadHermes.dest)) {
|
||||
eachFile { file ->
|
||||
// We flatten the unzip as the tarball contains a `facebook-hermes-<SHA>`
|
||||
// folder at the top level.
|
||||
if (file.relativePath.segments.size() > 1) {
|
||||
file.relativePath = new org.gradle.api.file.RelativePath(!file.isDirectory(), file.relativePath.segments.drop(1))
|
||||
}
|
||||
}
|
||||
}
|
||||
into(hermesDir)
|
||||
}
|
||||
}
|
||||
|
||||
task prepareHermes() {
|
||||
doLast {
|
||||
def hermesPackagePath = file("${nodeModules}/hermes-engine")
|
||||
if (!hermesPackagePath.exists()) {
|
||||
throw new GradleScriptException("Could not find the hermes-engine npm package", null)
|
||||
}
|
||||
if (REACT_NATIVE_VERSION >= 69) {
|
||||
if (!isNewArchitectureEnabled()) {
|
||||
dependsOn(unzipHermes)
|
||||
}
|
||||
|
||||
def hermesAAR = file("$hermesPackagePath/android/hermes-debug.aar")
|
||||
if (!hermesAAR.exists()) {
|
||||
throw new GradleScriptException("The hermes-engine npm package is missing \"android/hermes-debug.aar\"", null)
|
||||
}
|
||||
doLast {
|
||||
def hermesAAR = file("$reactNative/android/com/facebook/react/hermes-engine/$REACT_NATIVE_FULL_VERSION/hermes-engine-$REACT_NATIVE_FULL_VERSION-${resolveBuildType()}.aar") // e.g. hermes-engine-0.70.0-rc.1-debug.aar
|
||||
if (!hermesAAR.exists()) {
|
||||
throw new GradleScriptException("Could not find hermes-engine AAR", null)
|
||||
}
|
||||
|
||||
def soFiles = zipTree(hermesAAR).matching({ it.include "**/*.so" })
|
||||
def soFiles = zipTree(hermesAAR).matching({ it.include "**/*.so" })
|
||||
|
||||
copy {
|
||||
from soFiles
|
||||
from "$reactNative/ReactAndroid/src/main/jni/first-party/hermes/Android.mk"
|
||||
into "$thirdPartyNdkDir/hermes"
|
||||
copy {
|
||||
from soFiles
|
||||
from "$reactNative/ReactAndroid/src/main/jni/first-party/hermes/Android.mk"
|
||||
into "$thirdPartyNdkDir/hermes"
|
||||
}
|
||||
}
|
||||
} else {
|
||||
doLast {
|
||||
def hermesPackagePath = findNodeModulePath(projectDir, "hermes-engine")
|
||||
if (!hermesPackagePath) {
|
||||
throw new GradleScriptException("Could not find the hermes-engine npm package", null)
|
||||
}
|
||||
|
||||
def hermesAAR = file("$hermesPackagePath/android/hermes-debug.aar")
|
||||
if (!hermesAAR.exists()) {
|
||||
throw new GradleScriptException("The hermes-engine npm package is missing \"android/hermes-debug.aar\"", null)
|
||||
}
|
||||
|
||||
def soFiles = zipTree(hermesAAR).matching({ it.include "**/*.so" })
|
||||
|
||||
copy {
|
||||
from soFiles
|
||||
from "$reactNative/ReactAndroid/src/main/jni/first-party/hermes/Android.mk"
|
||||
into "$thirdPartyNdkDir/hermes"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
prepareHermes.mustRunAfter prepareThirdPartyNdkHeaders
|
||||
|
Loading…
Reference in New Issue
Block a user