2021-06-27 04:37:54 -06:00
import groovy.json.JsonSlurper
import org.apache.tools.ant.filters.ReplaceTokens
import java.nio.file.Paths
2022-01-03 04:23:19 -07:00
static def findNodeModules ( baseDir ) {
2021-06-27 04:37:54 -06:00
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 ) {
2022-01-03 05:18:38 -07:00
def nodeModulesPath = Paths . get ( basePath . toString ( ) , "node_modules" )
def reactNativePath = Paths . get ( nodeModulesPath . toString ( ) , "react-native" )
if ( nodeModulesPath . toFile ( ) . exists ( ) & & reactNativePath . toFile ( ) . exists ( ) ) {
return nodeModulesPath . toString ( )
2021-06-27 04:37:54 -06:00
}
basePath = basePath . getParent ( )
}
2022-01-03 04:23:19 -07:00
throw new GradleException ( "VisionCamera: Failed to find node_modules/ path!" )
2021-06-27 04:37:54 -06:00
}
2022-08-09 10:20:42 -06:00
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"
}
2021-06-27 04:37:54 -06:00
2022-01-03 04:23:19 -07:00
def nodeModules = findNodeModules ( projectDir )
logger . warn ( "VisionCamera: node_modules/ found at: ${nodeModules}" )
def reactNative = new File ( "$nodeModules/react-native" )
2022-08-09 10:20:42 -06:00
def CMAKE_NODE_MODULES_DIR = project . getProjectDir ( ) . getParentFile ( ) . getParent ( )
2022-01-03 04:23:19 -07:00
def reactProperties = new Properties ( )
file ( "$nodeModules/react-native/ReactAndroid/gradle.properties" ) . withInputStream { reactProperties . load ( it ) }
2022-08-09 10:20:42 -06:00
def REACT_NATIVE_FULL_VERSION = reactProperties . getProperty ( "VERSION_NAME" )
2022-01-03 04:23:19 -07:00
def REACT_NATIVE_VERSION = reactProperties . getProperty ( "VERSION_NAME" ) . split ( "\\." ) [ 1 ] . toInteger ( )
def FOR_HERMES = System . getenv ( "FOR_HERMES" ) = = "True"
rootProject . getSubprojects ( ) . forEach ( { project - >
if ( project . plugins . hasPlugin ( "com.android.application" ) ) {
2023-01-30 11:38:52 -07:00
FOR_HERMES = REACT_NATIVE_VERSION > = 71 & & project . hermesEnabled | | project . ext . react . enableHermes
2022-01-03 04:23:19 -07:00
}
} )
2022-08-09 10:20:42 -06:00
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 ( )
2022-01-03 05:06:18 -07:00
logger . warn ( "VisionCamera: Building with ${FOR_HERMES ? " Hermes " : " JSC "}..." )
2022-01-03 04:23:19 -07:00
2021-02-19 08:07:53 -07:00
buildscript {
// Buildscript is evaluated before everything else so we can't use getExtOrDefault
def kotlin_version = rootProject . ext . has ( 'kotlinVersion' ) ? rootProject . ext . get ( 'kotlinVersion' ) : project . properties [ 'VisionCamera_kotlinVersion' ]
repositories {
google ( )
2021-08-20 03:53:40 -06:00
mavenCentral ( )
2021-02-19 12:36:49 -07:00
maven {
url "https://plugins.gradle.org/m2/"
}
2021-02-19 08:07:53 -07:00
}
dependencies {
2021-08-20 03:53:40 -06:00
classpath 'com.android.tools.build:gradle:4.2.2'
2021-07-08 02:50:38 -06:00
classpath 'de.undercouch:gradle-download-task:4.1.2'
2021-02-19 08:07:53 -07:00
// noinspection DifferentKotlinGradleVersion
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
2021-02-19 12:36:49 -07:00
classpath "org.jetbrains.kotlin:kotlin-android-extensions:$kotlin_version"
2021-02-19 08:07:53 -07:00
}
}
apply plugin: 'com.android.library'
2021-06-27 04:37:54 -06:00
apply plugin: 'de.undercouch.download'
2021-02-19 08:07:53 -07:00
apply plugin: 'kotlin-android'
2021-02-19 12:36:49 -07:00
apply plugin: 'kotlin-android-extensions'
2021-02-19 08:07:53 -07:00
def getExtOrDefault ( name ) {
return rootProject . ext . has ( name ) ? rootProject . ext . get ( name ) : project . properties [ 'VisionCamera_' + name ]
}
def getExtOrIntegerDefault ( name ) {
return rootProject . ext . has ( name ) ? rootProject . ext . get ( name ) : ( project . properties [ 'VisionCamera_' + name ] ) . toInteger ( )
}
2022-08-09 10:20:42 -06:00
def resolveBuildType ( ) {
def buildType = "debug"
tasks . all ( { task - >
if ( task . name = = "buildCMakeRelease" ) {
buildType = "release"
}
} )
return buildType
}
2022-01-04 00:49:46 -07:00
// plugin.js file only exists since REA v2.
2022-01-03 04:23:19 -07:00
def hasReanimated2 = file ( "${nodeModules}/react-native-reanimated/plugin.js" ) . exists ( )
2022-01-03 03:54:32 -07:00
def disableFrameProcessors = rootProject . ext . has ( "disableFrameProcessors" ) ? rootProject . ext . get ( "disableFrameProcessors" ) . asBoolean ( ) : false
def ENABLE_FRAME_PROCESSORS = hasReanimated2 & & ! disableFrameProcessors
if ( ENABLE_FRAME_PROCESSORS ) {
logger . warn ( "VisionCamera: Frame Processors are enabled! Building C++ part..." )
} else {
if ( disableFrameProcessors ) {
logger . warn ( "VisionCamera: Frame Processors are disabled because the user explicitly disabled it ('disableFrameProcessors=${disableFrameProcessors}'). C++ part will not be built." )
} else if ( ! hasReanimated2 ) {
logger . warn ( "VisionCamera: Frame Processors are disabled because REA v2 does not exist. C++ part will not be built." )
}
}
2022-01-02 09:35:26 -07:00
2021-02-19 08:07:53 -07:00
android {
compileSdkVersion getExtOrIntegerDefault ( 'compileSdkVersion' )
buildToolsVersion getExtOrDefault ( 'buildToolsVersion' )
2021-06-27 04:37:54 -06:00
ndkVersion getExtOrDefault ( 'ndkVersion' )
2023-01-30 11:38:52 -07:00
if ( REACT_NATIVE_VERSION > = 71 ) {
buildFeatures {
prefab true
}
}
2021-02-19 08:07:53 -07:00
defaultConfig {
2021-02-19 12:54:55 -07:00
minSdkVersion 21
2021-02-19 08:07:53 -07:00
targetSdkVersion getExtOrIntegerDefault ( 'targetSdkVersion' )
2021-06-27 04:37:54 -06:00
2022-01-02 09:35:26 -07:00
if ( ENABLE_FRAME_PROCESSORS ) {
externalNativeBuild {
cmake {
cppFlags "-fexceptions" , "-frtti" , "-std=c++1y" , "-DONANDROID"
abiFilters 'x86' , 'x86_64' , 'armeabi-v7a' , 'arm64-v8a'
arguments '-DANDROID_STL=c++_shared' ,
"-DREACT_NATIVE_VERSION=${REACT_NATIVE_VERSION}" ,
2022-01-03 04:23:19 -07:00
"-DNODE_MODULES_DIR=${nodeModules}" ,
2022-08-09 10:20:42 -06:00
"-DFOR_HERMES=${FOR_HERMES}" ,
"-DJS_RUNTIME_DIR=${jsRuntimeDir}"
2022-01-02 09:35:26 -07:00
}
2021-06-27 04:37:54 -06:00
}
}
}
dexOptions {
javaMaxHeapSize "4g"
}
2022-01-02 09:35:26 -07:00
if ( ENABLE_FRAME_PROCESSORS ) {
externalNativeBuild {
cmake {
path "CMakeLists.txt"
}
2021-06-27 04:37:54 -06:00
}
}
packagingOptions {
2022-01-02 08:25:43 -07:00
// Exclude all Libraries that are already present in the user's app (through React Native or by him installing REA)
2023-01-30 11:38:52 -07:00
excludes = [ "**/libc++_shared.so" ,
"**/libfbjni.so" ,
"**/libjsi.so" ,
"**/libreactnativejni.so" ,
"**/libfolly_json.so" ,
"**/libreanimated.so" ,
"**/libjscexecutor.so" ,
"**/libhermes.so" ,
"**/libfolly_runtime.so" ,
"**/libglog.so" ,
]
2022-01-02 08:25:43 -07:00
// META-INF is duplicate by CameraX.
exclude "META-INF/**"
2021-02-19 08:07:53 -07:00
}
2021-02-19 12:36:49 -07:00
2021-02-19 08:07:53 -07:00
buildTypes {
release {
minifyEnabled false
}
}
2021-06-27 04:37:54 -06:00
2021-02-19 08:07:53 -07:00
lintOptions {
disable 'GradleCompatible'
}
compileOptions {
sourceCompatibility JavaVersion . VERSION_1_8
targetCompatibility JavaVersion . VERSION_1_8
}
2021-06-27 04:37:54 -06:00
configurations {
extractHeaders
extractJNI
}
2021-02-19 08:07:53 -07:00
}
repositories {
mavenCentral ( )
google ( )
def found = false
def defaultDir = null
def androidSourcesName = 'React Native sources'
if ( rootProject . ext . has ( 'reactNativeAndroidRoot' ) ) {
defaultDir = rootProject . ext . get ( 'reactNativeAndroidRoot' )
} else {
defaultDir = new File (
projectDir ,
'/../../../node_modules/react-native/android'
)
}
if ( defaultDir . exists ( ) ) {
maven {
url defaultDir . toString ( )
name androidSourcesName
}
logger . info ( ":${project.name}:reactNativeAndroidRoot ${defaultDir.canonicalPath}" )
found = true
} else {
def parentDir = rootProject . projectDir
1 . upto ( 5 , {
if ( found ) return true
parentDir = parentDir . parentFile
def androidSourcesDir = new File (
parentDir ,
'node_modules/react-native'
)
def androidPrebuiltBinaryDir = new File (
parentDir ,
'node_modules/react-native/android'
)
if ( androidPrebuiltBinaryDir . exists ( ) ) {
maven {
url androidPrebuiltBinaryDir . toString ( )
name androidSourcesName
}
logger . info ( ":${project.name}:reactNativeAndroidRoot ${androidPrebuiltBinaryDir.canonicalPath}" )
found = true
} else if ( androidSourcesDir . exists ( ) ) {
maven {
url androidSourcesDir . toString ( )
name androidSourcesName
}
logger . info ( ":${project.name}:reactNativeAndroidRoot ${androidSourcesDir.canonicalPath}" )
found = true
}
} )
}
if ( ! found ) {
throw new GradleException (
"${project.name}: unable to locate React Native android sources. " +
"Ensure you have you installed React Native as a dependency in your project and try again."
)
}
}
def kotlin_version = getExtOrDefault ( 'kotlinVersion' )
dependencies {
2023-01-30 11:38:52 -07:00
if ( REACT_NATIVE_VERSION > = 71 ) {
implementation "com.facebook.react:react-android:"
implementation "com.facebook.react:hermes-android:"
} else {
// noinspection GradleDynamicVersion
implementation 'com.facebook.react:react-native:+'
}
2021-06-27 04:37:54 -06:00
2022-01-02 09:35:26 -07:00
if ( ENABLE_FRAME_PROCESSORS ) {
implementation project ( ':react-native-reanimated' )
2021-06-27 04:37:54 -06:00
2023-01-30 11:38:52 -07:00
if ( REACT_NATIVE_VERSION < 71 ) {
//noinspection GradleDynamicVersion
2023-02-01 08:37:18 -07:00
extractHeaders ( "com.facebook.fbjni:fbjni:+:headers" )
2023-01-30 11:38:52 -07:00
//noinspection GradleDynamicVersion
extractJNI ( "com.facebook.fbjni:fbjni:+" )
2021-06-27 04:37:54 -06:00
2023-01-30 11:38:52 -07:00
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
extractJNI ( files ( rnAAR , jscAAR ) )
2022-08-09 10:20:42 -06:00
}
2023-01-30 11:38:52 -07:00
2022-01-02 09:35:26 -07:00
def jsEngine = FOR_HERMES ? "hermes" : "jsc"
2022-08-09 10:20:42 -06:00
def reaAAR = "${nodeModules}/react-native-reanimated/android/react-native-reanimated-${REACT_NATIVE_VERSION}-${jsEngine}.aar"
2023-01-30 11:38:52 -07:00
extractJNI ( files ( reaAAR ) )
2022-01-02 09:35:26 -07:00
}
2021-02-19 12:36:49 -07:00
2021-02-19 08:07:53 -07:00
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
2021-09-23 06:22:11 -06:00
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-guava:1.5.2"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.5.2"
2021-02-19 12:36:49 -07:00
2022-02-28 03:51:50 -07:00
implementation "androidx.camera:camera-core:1.1.0-beta02"
implementation "androidx.camera:camera-camera2:1.1.0-beta02"
implementation "androidx.camera:camera-lifecycle:1.1.0-beta02"
implementation "androidx.camera:camera-video:1.1.0-beta02"
2021-12-30 03:39:17 -07:00
2022-02-28 03:51:50 -07:00
implementation "androidx.camera:camera-view:1.1.0-beta02"
implementation "androidx.camera:camera-extensions:1.1.0-beta02"
2021-12-30 03:39:17 -07:00
2021-08-06 02:44:57 -06:00
implementation "androidx.exifinterface:exifinterface:1.3.3"
2021-02-19 08:07:53 -07:00
}
2021-06-27 04:37:54 -06:00
2022-01-02 09:35:26 -07:00
if ( ENABLE_FRAME_PROCESSORS ) {
// third-party-ndk deps headers
// mostly a copy of https://github.com/software-mansion/react-native-reanimated/blob/master/android/build.gradle#L115
2022-10-28 04:18:06 -06:00
def customDownloadsDir = System . getenv ( "REACT_NATIVE_DOWNLOADS_DIR" )
def downloadsDir = customDownloadsDir ? new File ( customDownloadsDir ) : new File ( "$buildDir/downloads" )
2022-01-02 09:35:26 -07:00
def thirdPartyNdkDir = new File ( "$buildDir/third-party-ndk" )
2022-01-03 04:23:19 -07:00
def thirdPartyVersionsFile = new File ( "${nodeModules}/react-native/ReactAndroid/gradle.properties" )
2022-01-02 09:35:26 -07:00
def thirdPartyVersions = new Properties ( )
thirdPartyVersions . load ( new FileInputStream ( thirdPartyVersionsFile ) )
def BOOST_VERSION = thirdPartyVersions [ "BOOST_VERSION" ]
def boost_file = new File ( downloadsDir , "boost_${BOOST_VERSION}.tar.gz" )
def DOUBLE_CONVERSION_VERSION = thirdPartyVersions [ "DOUBLE_CONVERSION_VERSION" ]
def double_conversion_file = new File ( downloadsDir , "double-conversion-${DOUBLE_CONVERSION_VERSION}.tar.gz" )
def FOLLY_VERSION = thirdPartyVersions [ "FOLLY_VERSION" ]
def folly_file = new File ( downloadsDir , "folly-${FOLLY_VERSION}.tar.gz" )
def GLOG_VERSION = thirdPartyVersions [ "GLOG_VERSION" ]
def glog_file = new File ( downloadsDir , "glog-${GLOG_VERSION}.tar.gz" )
task createNativeDepsDirectories {
doLast {
downloadsDir . mkdirs ( )
thirdPartyNdkDir . mkdirs ( )
}
}
2021-06-27 04:37:54 -06:00
2022-01-02 09:35:26 -07:00
task downloadBoost ( dependsOn: createNativeDepsDirectories , type: Download ) {
2022-08-09 10:20:42 -06:00
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 )
2022-01-02 09:35:26 -07:00
onlyIfNewer ( true )
overwrite ( false )
dest ( boost_file )
2021-06-27 04:37:54 -06:00
}
2022-01-02 09:35:26 -07:00
task prepareBoost ( dependsOn: downloadBoost , type: Copy ) {
from ( tarTree ( resources . gzip ( downloadBoost . dest ) ) )
from ( "src/main/jni/third-party/boost/Android.mk" )
include ( "Android.mk" , "boost_${BOOST_VERSION}/boost/**/*.hpp" , "boost/boost/**/*.hpp" )
includeEmptyDirs = false
into ( "$thirdPartyNdkDir" ) // /boost_X_XX_X
doLast {
file ( "$thirdPartyNdkDir/boost_${BOOST_VERSION}" ) . renameTo ( "$thirdPartyNdkDir/boost" )
}
}
2021-06-27 04:37:54 -06:00
2022-01-02 09:35:26 -07:00
task downloadDoubleConversion ( dependsOn: createNativeDepsDirectories , type: Download ) {
src ( "https://github.com/google/double-conversion/archive/v${DOUBLE_CONVERSION_VERSION}.tar.gz" )
onlyIfNewer ( true )
overwrite ( false )
dest ( double_conversion_file )
}
2021-06-27 04:37:54 -06:00
2022-01-02 09:35:26 -07:00
task prepareDoubleConversion ( dependsOn: downloadDoubleConversion , type: Copy ) {
from ( tarTree ( downloadDoubleConversion . dest ) )
from ( "src/main/jni/third-party/double-conversion/Android.mk" )
include ( "double-conversion-${DOUBLE_CONVERSION_VERSION}/src/**/*" , "Android.mk" )
filesMatching ( "*/src/**/*" , { fname - > fname . path = "double-conversion/${fname.name}" } )
includeEmptyDirs = false
into ( "$thirdPartyNdkDir/double-conversion" )
}
2021-06-27 04:37:54 -06:00
2022-01-02 09:35:26 -07:00
task downloadFolly ( dependsOn: createNativeDepsDirectories , type: Download ) {
src ( "https://github.com/facebook/folly/archive/v${FOLLY_VERSION}.tar.gz" )
onlyIfNewer ( true )
overwrite ( false )
dest ( folly_file )
}
2021-06-27 04:37:54 -06:00
2022-01-02 09:35:26 -07:00
task prepareFolly ( dependsOn: downloadFolly , type: Copy ) {
from ( tarTree ( downloadFolly . dest ) )
from ( "src/main/jni/third-party/folly/Android.mk" )
include ( "folly-${FOLLY_VERSION}/folly/**/*" , "Android.mk" )
eachFile { fname - > fname . path = ( fname . path - "folly-${FOLLY_VERSION}/" ) }
includeEmptyDirs = false
into ( "$thirdPartyNdkDir/folly" )
}
2021-06-27 04:37:54 -06:00
2022-01-02 09:35:26 -07:00
task downloadGlog ( dependsOn: createNativeDepsDirectories , type: Download ) {
src ( "https://github.com/google/glog/archive/v${GLOG_VERSION}.tar.gz" )
onlyIfNewer ( true )
overwrite ( false )
dest ( glog_file )
2021-06-27 04:37:54 -06:00
}
2022-01-02 09:35:26 -07:00
task prepareGlog ( dependsOn: downloadGlog , type: Copy ) {
from ( tarTree ( downloadGlog . dest ) )
from ( "src/main/jni/third-party/glog/" )
include ( "glog-${GLOG_VERSION}/src/**/*" , "Android.mk" , "config.h" )
includeEmptyDirs = false
filesMatching ( "**/*.h.in" ) {
filter ( ReplaceTokens , tokens: [
ac_cv_have_unistd_h : "1" ,
ac_cv_have_stdint_h : "1" ,
ac_cv_have_systypes_h : "1" ,
ac_cv_have_inttypes_h : "1" ,
ac_cv_have_libgflags : "0" ,
ac_google_start_namespace : "namespace google {" ,
ac_cv_have_uint16_t : "1" ,
ac_cv_have_u_int16_t : "1" ,
ac_cv_have___uint16 : "0" ,
ac_google_end_namespace : "}" ,
ac_cv_have___builtin_expect : "1" ,
ac_google_namespace : "google" ,
ac_cv___attribute___noinline : "__attribute__ ((noinline))" ,
ac_cv___attribute___noreturn : "__attribute__ ((noreturn))" ,
ac_cv___attribute___printf_4_5: "__attribute__((__format__ (__printf__, 4, 5)))"
] )
it . path = ( it . name - ".in" )
2021-06-27 04:37:54 -06:00
}
2022-01-02 09:35:26 -07:00
into ( "$thirdPartyNdkDir/glog" )
2021-06-27 04:37:54 -06:00
2022-01-02 09:35:26 -07:00
doLast {
copy {
from ( fileTree ( dir: "$thirdPartyNdkDir/glog" , includes: [ "stl_logging.h" , "logging.h" , "raw_logging.h" , "vlog_is_on.h" , "**/src/glog/log_severity.h" ] ) . files )
includeEmptyDirs = false
into ( "$thirdPartyNdkDir/glog/exported/glog" )
}
}
2021-09-06 02:32:06 -06:00
}
2022-01-02 09:35:26 -07:00
task prepareThirdPartyNdkHeaders {
if ( ! boost_file . exists ( ) ) {
dependsOn ( prepareBoost )
}
if ( ! double_conversion_file . exists ( ) ) {
dependsOn ( prepareDoubleConversion )
}
if ( ! folly_file . exists ( ) ) {
dependsOn ( prepareFolly )
}
if ( ! glog_file . exists ( ) ) {
dependsOn ( prepareGlog )
}
2021-09-06 02:32:06 -06:00
}
2022-01-02 09:35:26 -07:00
prepareThirdPartyNdkHeaders . mustRunAfter createNativeDepsDirectories
2021-09-06 02:32:06 -06:00
2022-08-09 10:20:42 -06:00
/ *
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
2022-01-02 09:35:26 -07:00
}
2021-09-06 02:32:06 -06:00
2022-08-09 10:20:42 -06:00
task downloadHermes ( type: Download ) {
src ( "https://github.com/facebook/hermes/tarball/${hermesVersion}" )
onlyIfNewer ( true )
overwrite ( false )
dest ( new File ( downloadDir , "hermes.tar.gz" ) )
2022-01-02 09:35:26 -07:00
}
2021-06-27 04:37:54 -06:00
2022-08-09 10:20:42 -06:00
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 )
}
}
2021-06-27 04:37:54 -06:00
2022-08-09 10:20:42 -06:00
task prepareHermes ( ) {
if ( REACT_NATIVE_VERSION > = 69 ) {
if ( ! isNewArchitectureEnabled ( ) ) {
dependsOn ( unzipHermes )
}
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" } )
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"
}
}
2022-01-02 09:35:26 -07:00
}
2021-06-27 04:37:54 -06:00
}
2022-01-02 09:35:26 -07:00
prepareHermes . mustRunAfter prepareThirdPartyNdkHeaders
2021-09-06 02:32:06 -06:00
2022-01-02 09:35:26 -07:00
task prepareJSC {
doLast {
2022-01-03 04:23:19 -07:00
def jscPackagePath = file ( "${nodeModules}/jsc-android" )
if ( ! jscPackagePath . exists ( ) ) {
2022-01-02 09:35:26 -07:00
throw new GradleScriptException ( "Could not find the jsc-android npm package" , null )
}
2021-06-27 04:37:54 -06:00
2022-01-02 09:35:26 -07:00
def jscDist = file ( "$jscPackagePath/dist" )
if ( ! jscDist . exists ( ) ) {
throw new GradleScriptException ( "The jsc-android npm package is missing its \"dist\" directory" , null )
}
2021-06-27 04:37:54 -06:00
2022-01-02 09:35:26 -07:00
def jscAAR = fileTree ( jscDist ) . matching ( { it . include "**/android-jsc/**/*.aar" } ) . singleFile
def soFiles = zipTree ( jscAAR ) . matching ( { it . include "**/*.so" } )
2021-06-27 04:37:54 -06:00
2022-01-02 09:35:26 -07:00
def headerFiles = fileTree ( jscDist ) . matching ( { it . include "**/include/*.h" } )
2021-06-27 04:37:54 -06:00
2022-01-02 09:35:26 -07:00
copy {
from ( soFiles )
from ( headerFiles )
from ( "$reactNative/ReactAndroid/src/main/jni/third-party/jsc/Android.mk" )
2021-06-27 04:37:54 -06:00
2022-01-02 09:35:26 -07:00
filesMatching ( "**/*.h" , { it . path = "JavaScriptCore/${it.name}" } )
2021-06-27 04:37:54 -06:00
2022-01-02 09:35:26 -07:00
includeEmptyDirs ( false )
into ( "$thirdPartyNdkDir/jsc" )
}
2021-06-27 04:37:54 -06:00
}
}
2022-01-02 09:35:26 -07:00
prepareJSC . mustRunAfter prepareHermes
2021-09-06 02:32:06 -06:00
2022-01-02 09:35:26 -07:00
task extractAARHeaders {
doLast {
configurations . extractHeaders . files . each {
def file = it . absoluteFile
copy {
from zipTree ( file )
into "$buildDir/$file.name"
include "**/*.h"
}
2021-09-06 02:32:06 -06:00
}
}
2021-06-27 04:37:54 -06:00
}
2021-09-06 02:32:06 -06:00
2022-01-02 09:35:26 -07:00
extractAARHeaders . mustRunAfter prepareJSC
2021-09-06 02:32:06 -06:00
2022-01-02 09:35:26 -07:00
task extractJNIFiles {
doLast {
configurations . extractJNI . files . each {
def file = it . absoluteFile
2021-09-06 02:32:06 -06:00
2022-01-02 09:35:26 -07:00
copy {
from zipTree ( file )
into "$buildDir/$file.name"
include "jni/**/*"
}
2021-09-06 02:32:06 -06:00
}
}
2021-06-27 04:37:54 -06:00
}
2022-01-02 09:35:26 -07:00
extractJNIFiles . mustRunAfter extractAARHeaders
2021-09-06 02:32:06 -06:00
2022-01-02 09:35:26 -07:00
// pre-native build pipeline
2021-06-27 04:37:54 -06:00
2022-01-02 09:35:26 -07:00
tasks . whenTaskAdded { task - >
if ( ! task . name . contains ( 'Clean' ) & & ( task . name . contains ( 'externalNative' ) | | task . name . contains ( 'CMake' ) ) ) {
task . dependsOn ( extractJNIFiles )
2023-01-30 11:38:52 -07:00
if ( REACT_NATIVE_VERSION < 71 ) {
task . dependsOn ( extractAARHeaders )
task . dependsOn ( prepareThirdPartyNdkHeaders )
task . dependsOn ( prepareJSC )
task . dependsOn ( prepareHermes )
}
2022-01-02 09:35:26 -07:00
}
2021-06-27 04:37:54 -06:00
}
}