mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
995b4d3049
Summary: ### Problem According to https://github.com/facebook/react-native/issues/9145, the `--port` setting is not respected when executing `react-native run-android`. The templates that report things like what port the dev server runs on are hard coded as well. ### Solution This commit replaces the hardcoded instances of port 8081 on Android with a build configuration property. This allows setting of the port React Native Android connects to for the local build server. For this change to work, there must also be an update to the react native CLI to pass along this setting: https://github.com/react-native-community/react-native-cli/compare/master...nhunzaker:9145-android-no-port-hardcode-cli To avoid some noise on their end, I figured I wouldn't submit a PR until it's this approach is deemed workable. ## Changelog [Android][fixed] - `react-native run-android --port <x>` correctly connects to dev server and related error messages display the correct port Pull Request resolved: https://github.com/facebook/react-native/pull/23616 Differential Revision: D15645200 Pulled By: cpojer fbshipit-source-id: 3bdfd458b8ac3ec78290736c9ed0db2e5776ed46
363 lines
14 KiB
Groovy
363 lines
14 KiB
Groovy
// Copyright (c) Facebook, Inc. and its affiliates.
|
|
|
|
// This source code is licensed under the MIT license found in the
|
|
// LICENSE file in the root directory of this source tree.
|
|
|
|
plugins {
|
|
id("com.android.library")
|
|
id("maven")
|
|
id("de.undercouch.download")
|
|
}
|
|
|
|
import de.undercouch.gradle.tasks.download.Download
|
|
import org.apache.tools.ant.taskdefs.condition.Os
|
|
import org.apache.tools.ant.filters.ReplaceTokens
|
|
|
|
// We download various C++ open-source dependencies into downloads.
|
|
// We then copy both the downloaded code and our custom makefiles and headers into third-party-ndk.
|
|
// After that we build native code from src/main/jni with module path pointing at third-party-ndk.
|
|
|
|
def customDownloadsDir = System.getenv("REACT_NATIVE_DOWNLOADS_DIR")
|
|
def downloadsDir = customDownloadsDir ? new File(customDownloadsDir) : new File("$buildDir/downloads")
|
|
def thirdPartyNdkDir = new File("$buildDir/third-party-ndk")
|
|
|
|
// You need to have following folders in this directory:
|
|
// - boost_1_63_0
|
|
// - double-conversion-1.1.6
|
|
// - folly-deprecate-dynamic-initializer
|
|
// - glog-0.3.5
|
|
def dependenciesPath = System.getenv("REACT_NATIVE_DEPENDENCIES")
|
|
|
|
// The Boost library is a very large download (>100MB).
|
|
// If Boost is already present on your system, define the REACT_NATIVE_BOOST_PATH env variable
|
|
// and the build will use that.
|
|
def boostPath = dependenciesPath ?: System.getenv("REACT_NATIVE_BOOST_PATH")
|
|
|
|
// Setup build type for NDK, supported values: {debug, release}
|
|
def nativeBuildType = System.getenv("NATIVE_BUILD_TYPE") ?: "release"
|
|
|
|
task createNativeDepsDirectories {
|
|
downloadsDir.mkdirs()
|
|
thirdPartyNdkDir.mkdirs()
|
|
}
|
|
|
|
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")
|
|
onlyIfNewer(true)
|
|
overwrite(false)
|
|
dest(new File(downloadsDir, "boost_${BOOST_VERSION}.tar.gz"))
|
|
}
|
|
|
|
task prepareBoost(dependsOn: boostPath ? [] : [downloadBoost], type: Copy) {
|
|
from(boostPath ?: 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")
|
|
doLast {
|
|
file("$thirdPartyNdkDir/boost/boost").renameTo("$thirdPartyNdkDir/boost/boost_${BOOST_VERSION}")
|
|
}
|
|
}
|
|
|
|
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(new File(downloadsDir, "double-conversion-${DOUBLE_CONVERSION_VERSION}.tar.gz"))
|
|
}
|
|
|
|
task prepareDoubleConversion(dependsOn: dependenciesPath ? [] : [downloadDoubleConversion], type: Copy) {
|
|
from(dependenciesPath ?: 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")
|
|
}
|
|
|
|
task downloadFolly(dependsOn: createNativeDepsDirectories, type: Download) {
|
|
src("https://github.com/facebook/folly/archive/v${FOLLY_VERSION}.tar.gz")
|
|
onlyIfNewer(true)
|
|
overwrite(false)
|
|
dest(new File(downloadsDir, "folly-${FOLLY_VERSION}.tar.gz"))
|
|
}
|
|
|
|
task prepareFolly(dependsOn: dependenciesPath ? [] : [downloadFolly], type: Copy) {
|
|
from(dependenciesPath ?: 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")
|
|
}
|
|
|
|
task downloadGlog(dependsOn: createNativeDepsDirectories, type: Download) {
|
|
src("https://github.com/google/glog/archive/v${GLOG_VERSION}.tar.gz")
|
|
onlyIfNewer(true)
|
|
overwrite(false)
|
|
dest(new File(downloadsDir, "glog-${GLOG_VERSION}.tar.gz"))
|
|
}
|
|
|
|
// Prepare glog sources to be compiled, this task will perform steps that normally should've been
|
|
// executed by automake. This way we can avoid dependencies on make/automake
|
|
task prepareGlog(dependsOn: dependenciesPath ? [] : [downloadGlog], type: Copy) {
|
|
from(dependenciesPath ?: 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")
|
|
}
|
|
into("$thirdPartyNdkDir/glog")
|
|
|
|
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")
|
|
}
|
|
}
|
|
}
|
|
|
|
// 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 jscAAR = fileTree(jscPackageRoot).matching({ it.include "**/android-jsc/**/*.aar" }).singleFile
|
|
def soFiles = zipTree(jscAAR).matching({ it.include "**/*.so" })
|
|
|
|
def headerFiles = fileTree(jscPackageRoot).matching({ it.include "**/include/*.h" })
|
|
|
|
copy {
|
|
from(soFiles)
|
|
from(headerFiles)
|
|
from("src/main/jni/third-party/jsc/Android.mk")
|
|
|
|
filesMatching("**/*.h", { it.path = "JavaScriptCore/${it.name}" })
|
|
|
|
includeEmptyDirs(false)
|
|
into("$thirdPartyNdkDir/jsc")
|
|
}
|
|
}
|
|
}
|
|
task downloadNdkBuildDependencies {
|
|
if (!boostPath) {
|
|
dependsOn(downloadBoost)
|
|
}
|
|
dependsOn(downloadDoubleConversion)
|
|
dependsOn(downloadFolly)
|
|
dependsOn(downloadGlog)
|
|
}
|
|
|
|
def getNdkBuildName() {
|
|
if (Os.isFamily(Os.FAMILY_WINDOWS)) {
|
|
return "ndk-build.cmd"
|
|
} else {
|
|
return "ndk-build"
|
|
}
|
|
}
|
|
|
|
def findNdkBuildFullPath() {
|
|
// we allow to provide full path to ndk-build tool
|
|
if (hasProperty("ndk.command")) {
|
|
return property("ndk.command")
|
|
}
|
|
// or just a path to the containing directory
|
|
if (hasProperty("ndk.path")) {
|
|
def ndkDir = property("ndk.path")
|
|
return new File(ndkDir, getNdkBuildName()).getAbsolutePath()
|
|
}
|
|
if (System.getenv("ANDROID_NDK") != null) {
|
|
def ndkDir = System.getenv("ANDROID_NDK")
|
|
return new File(ndkDir, getNdkBuildName()).getAbsolutePath()
|
|
}
|
|
def ndkDir = android.hasProperty("plugin") ? android.plugin.ndkFolder :
|
|
plugins.getPlugin("com.android.library").hasProperty("sdkHandler") ?
|
|
plugins.getPlugin("com.android.library").sdkHandler.getNdkFolder() :
|
|
android.ndkDirectory ? android.ndkDirectory.absolutePath : null
|
|
if (ndkDir) {
|
|
return new File(ndkDir, getNdkBuildName()).getAbsolutePath()
|
|
}
|
|
return null
|
|
}
|
|
|
|
def reactNativeDevServerPort() {
|
|
def value = project.getProperties().get("reactNativeDevServerPort")
|
|
return value != null ? value : "8081"
|
|
}
|
|
|
|
def reactNativeInspectorProxyPort() {
|
|
def value = project.getProperties().get("reactNativeInspectorProxyPort")
|
|
return value != null ? value : reactNativeDevServerPort()
|
|
}
|
|
|
|
def getNdkBuildFullPath() {
|
|
def ndkBuildFullPath = findNdkBuildFullPath()
|
|
if (ndkBuildFullPath == null) {
|
|
throw new GradleScriptException(
|
|
"ndk-build binary cannot be found, check if you've set " +
|
|
"\$ANDROID_NDK environment variable correctly or if ndk.dir is " +
|
|
"setup in local.properties",
|
|
null)
|
|
}
|
|
if (!new File(ndkBuildFullPath).canExecute()) {
|
|
throw new GradleScriptException(
|
|
"ndk-build binary " + ndkBuildFullPath + " doesn't exist or isn't executable.\n" +
|
|
"Check that the \$ANDROID_NDK environment variable, or ndk.dir in local.properties, is set correctly.\n" +
|
|
"(On Windows, make sure you escape backslashes in local.properties or use forward slashes, e.g. C:\\\\ndk or C:/ndk rather than C:\\ndk)",
|
|
null)
|
|
}
|
|
return ndkBuildFullPath
|
|
}
|
|
|
|
task buildReactNdkLib(dependsOn: [prepareJSC, prepareBoost, prepareDoubleConversion, prepareFolly, prepareGlog], type: Exec) {
|
|
inputs.dir("$projectDir/../ReactCommon")
|
|
inputs.dir("src/main/jni")
|
|
outputs.dir("$buildDir/react-ndk/all")
|
|
commandLine(getNdkBuildFullPath(),
|
|
"NDK_DEBUG=" + (nativeBuildType.equalsIgnoreCase("debug") ? "1" : "0"),
|
|
"NDK_PROJECT_PATH=null",
|
|
"NDK_APPLICATION_MK=$projectDir/src/main/jni/Application.mk",
|
|
"NDK_OUT=" + temporaryDir,
|
|
"NDK_LIBS_OUT=$buildDir/react-ndk/all",
|
|
"THIRD_PARTY_NDK_DIR=$buildDir/third-party-ndk",
|
|
"REACT_COMMON_DIR=$projectDir/../ReactCommon",
|
|
"REACT_SRC_DIR=$projectDir/src/main/java/com/facebook/react",
|
|
"-C", file("src/main/jni/react/jni").absolutePath,
|
|
"--jobs", project.findProperty("jobs") ?: Runtime.runtime.availableProcessors()
|
|
)
|
|
}
|
|
|
|
task cleanReactNdkLib(type: Exec) {
|
|
ignoreExitValue(true)
|
|
errorOutput(new ByteArrayOutputStream())
|
|
commandLine(getNdkBuildFullPath(),
|
|
"NDK_APPLICATION_MK=$projectDir/src/main/jni/Application.mk",
|
|
"THIRD_PARTY_NDK_DIR=$buildDir/third-party-ndk",
|
|
"REACT_COMMON_DIR=$projectDir/../ReactCommon",
|
|
"-C", file("src/main/jni/react/jni").absolutePath,
|
|
"clean")
|
|
doLast {
|
|
file(AAR_OUTPUT_URL).delete()
|
|
println("Deleted aar output dir at ${file(AAR_OUTPUT_URL)}")
|
|
}
|
|
}
|
|
|
|
task packageReactNdkLibs(dependsOn: buildReactNdkLib, type: Copy) {
|
|
from("$buildDir/react-ndk/all")
|
|
into("$buildDir/react-ndk/exported")
|
|
exclude("**/libjsc.so")
|
|
}
|
|
|
|
task packageReactNdkLibsForBuck(dependsOn: packageReactNdkLibs, type: Copy) {
|
|
from("$buildDir/react-ndk/exported")
|
|
into("src/main/jni/prebuilt/lib")
|
|
}
|
|
|
|
android {
|
|
compileSdkVersion 28
|
|
|
|
compileOptions {
|
|
sourceCompatibility(JavaVersion.VERSION_1_8)
|
|
targetCompatibility(JavaVersion.VERSION_1_8)
|
|
}
|
|
|
|
defaultConfig {
|
|
minSdkVersion(16)
|
|
targetSdkVersion(28)
|
|
versionCode(1)
|
|
versionName("1.0")
|
|
|
|
consumerProguardFiles("proguard-rules.pro")
|
|
|
|
ndk {
|
|
moduleName("reactnativejni")
|
|
}
|
|
|
|
buildConfigField("boolean", "IS_INTERNAL_BUILD", "false")
|
|
buildConfigField("int", "EXOPACKAGE_FLAGS", "0")
|
|
|
|
resValue "integer", "react_native_dev_server_port", reactNativeDevServerPort()
|
|
resValue "integer", "react_native_inspector_proxy_port", reactNativeInspectorProxyPort()
|
|
|
|
testApplicationId("com.facebook.react.tests.gradle")
|
|
testInstrumentationRunner("androidx.test.runner.AndroidJUnitRunner")
|
|
}
|
|
|
|
sourceSets.main {
|
|
jni.srcDirs = []
|
|
jniLibs.srcDir("$buildDir/react-ndk/exported")
|
|
res.srcDirs = ["src/main/res/devsupport", "src/main/res/shell", "src/main/res/views/modal", "src/main/res/views/uimanager"]
|
|
java {
|
|
srcDirs = ["src/main/java", "src/main/libraries/soloader/java", "src/main/jni/first-party/fb/jni/java"]
|
|
exclude("com/facebook/react/processing")
|
|
exclude("com/facebook/react/module/processing")
|
|
}
|
|
}
|
|
|
|
tasks.withType(JavaCompile) {
|
|
compileTask -> compileTask.dependsOn(packageReactNdkLibs)
|
|
}
|
|
|
|
clean.dependsOn(cleanReactNdkLib)
|
|
|
|
lintOptions {
|
|
abortOnError(false)
|
|
}
|
|
packagingOptions {
|
|
exclude("META-INF/NOTICE")
|
|
exclude("META-INF/LICENSE")
|
|
}
|
|
}
|
|
|
|
dependencies {
|
|
api("com.facebook.infer.annotation:infer-annotation:0.11.2")
|
|
api("javax.inject:javax.inject:1")
|
|
api("androidx.appcompat:appcompat:1.0.2")
|
|
api("com.facebook.fresco:fresco:${FRESCO_VERSION}")
|
|
api("com.facebook.fresco:imagepipeline-okhttp3:${FRESCO_VERSION}")
|
|
api("com.facebook.soloader:soloader:${SO_LOADER_VERSION}")
|
|
api("com.google.code.findbugs:jsr305:3.0.2")
|
|
api("com.squareup.okhttp3:okhttp:${OKHTTP_VERSION}")
|
|
api("com.squareup.okhttp3:okhttp-urlconnection:${OKHTTP_VERSION}")
|
|
api("com.squareup.okio:okio:1.15.0")
|
|
|
|
testImplementation("junit:junit:${JUNIT_VERSION}")
|
|
testImplementation("org.powermock:powermock-api-mockito:${POWERMOCK_VERSION}")
|
|
testImplementation("org.powermock:powermock-module-junit4-rule:${POWERMOCK_VERSION}")
|
|
testImplementation("org.powermock:powermock-classloading-xstream:${POWERMOCK_VERSION}")
|
|
testImplementation("org.mockito:mockito-core:${MOCKITO_CORE_VERSION}")
|
|
testImplementation("org.easytesting:fest-assert-core:${FEST_ASSERT_CORE_VERSION}")
|
|
testImplementation("org.robolectric:robolectric:${ROBOLECTRIC_VERSION}")
|
|
|
|
androidTestImplementation(fileTree(dir: "src/main/third-party/java/buck-android-support/", include: ["*.jar"]))
|
|
//TODO: Refactor to extract versions of androidx dependencies
|
|
androidTestImplementation("androidx.test:runner:1.1.0")
|
|
androidTestImplementation("androidx.test:rules:1.1.0")
|
|
androidTestImplementation("org.mockito:mockito-core:${MOCKITO_CORE_VERSION}")
|
|
}
|
|
|
|
apply(from: "release.gradle")
|