Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[android][gradle] Use Node's module resolution algo to find JSC & Hermes #26773

Closed
wants to merge 2 commits into from
Closed
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
72 changes: 56 additions & 16 deletions ReactAndroid/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ plugins {
id("de.undercouch.download")
}

import java.nio.file.Paths

import de.undercouch.gradle.tasks.download.Download
import org.apache.tools.ant.taskdefs.condition.Os
import org.apache.tools.ant.filters.ReplaceTokens
Expand Down Expand Up @@ -92,17 +94,16 @@ task prepareFolly(dependsOn: dependenciesPath ? [] : [downloadFolly], type: Copy
}

task prepareHermes() {
def hermesAAR = file("$projectDir/../node_modules/hermes-engine/android/hermes-debug.aar")
if (!hermesAAR.exists()) {
// For an app to build from RN source, hermes-engine is located at /path/to/app/node_modules
// and $projectDir is located at /path/to/app/node_modules/react-native/ReactAndroid
hermesAAR = file("$projectDir/../../hermes-engine/android/hermes-debug.aar")
def hermesPackagePath = findNodeModulePath(projectDir, "hermes-engine")
if (!hermesPackagePath) {
throw new GradleScriptException("Could not find the hermes-engine npm package")
}

if (!hermesAAR.exists()) {
// At Facebook, this file is in a different folder
hermesAAR = file("$projectDir/../../node_modules/hermes-engine/android/hermes-debug.aar")
}
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\"")
}

def soFiles = zipTree(hermesAAR).matching({ it.include "**/*.so" })

copy {
Expand Down Expand Up @@ -160,16 +161,20 @@ task prepareGlog(dependsOn: dependenciesPath ? [] : [downloadGlog], type: Copy)
// Create Android.mk library module based on jsc from npm
task prepareJSC {
doLast {
def jscPackageRoot = file("$projectDir/../node_modules/jsc-android/dist")
if (!jscPackageRoot.exists()) {
// For an app to build from RN source, the jsc-android is located at /path/to/app/node_modules
// and $projectDir may located at /path/to/app/node_modules/react-native/ReactAndroid
jscPackageRoot = file("$projectDir/../../jsc-android/dist")
def jscPackagePath = findNodeModulePath(projectDir, "jsc-android")
if (!jscPackagePath) {
throw new GradleScriptException("Could not find the jsc-android npm package")
}

def jscDist = file("$jscPackagePath/dist")
if (!jscDist.exists()) {
throw new GradleScriptException("The jsc-android npm package is missing its \"dist\" directory")
}
def jscAAR = fileTree(jscPackageRoot).matching({ it.include "**/android-jsc/**/*.aar" }).singleFile

def jscAAR = fileTree(jscDist).matching({ it.include "**/android-jsc/**/*.aar" }).singleFile
def soFiles = zipTree(jscAAR).matching({ it.include "**/*.so" })

def headerFiles = fileTree(jscPackageRoot).matching({ it.include "**/include/*.h" })
def headerFiles = fileTree(jscDist).matching({ it.include "**/include/*.h" })

copy {
from(soFiles)
Expand All @@ -192,6 +197,41 @@ task downloadNdkBuildDependencies {
dependsOn(downloadGlog)
}

/**
* Finds the path of the installed npm package with the given name using Node's
* module resolution algorithm, which searches "node_modules" directories up to
* the file system root. This handles various cases, including:
*
* - Working in the open-source RN repo:
* Gradle: /path/to/react-native/ReactAndroid
* Node module: /path/to/react-native/node_modules/[package]
*
* - Installing RN as a dependency of an app and searching for hoisted
* dependencies:
* Gradle: /path/to/app/node_modules/react-native/ReactAndroid
* Node module: /path/to/app/node_modules/[package]
*
* - Working in a larger repo (e.g., Facebook) that contains RN:
* Gradle: /path/to/repo/path/to/react-native/ReactAndroid
* Node module: /path/to/repo/node_modules/[package]
*
* The search begins at the given base directory (a File object). The returned
* path is a string.
*/
def findNodeModulePath(baseDir, packageName) {
ide marked this conversation as resolved.
Show resolved Hide resolved
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 getNdkBuildName() {
if (Os.isFamily(Os.FAMILY_WINDOWS)) {
return "ndk-build.cmd"
Expand Down