Files
react-native/ReactAndroid/build.gradle
T
Pascal Hartig 35fc0add2d Remove vendored proguard annotation (#26069)
Summary:
There have been multiple complaints about combining RN with various
other FB libraries, including Litho and Flipper, because of bundled dependencies
that can't be deduplicated by Gradle.

This is one of three current conflicts:

1) Proguard annotations (this PR)
2) Yoga
3) fbjni

While the Yoga group name doesn't make a massive amount of sense
it was the easiest existing package to use and since we don't
have a better namespace for this, we might as well use this.

A similar change to Litho is landing right now.

## Changelog

[Android] [Changed] - Use centralized package for DoNotStrip annotation
Pull Request resolved: https://github.com/facebook/react-native/pull/26069

Test Plan:
```
yarn
./gradlew :RNTester:android:app:assembleDebug
```

Reviewed By: cpojer

Differential Revision: D16827430

Pulled By: passy

fbshipit-source-id: 87542b5422fee598d8e635651441f0ecd42eb9d7
2019-08-15 06:04:16 -07:00

392 lines
16 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 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")
if (!hermesAAR.exists()) {
// At Facebook, this file is in a different folder
hermesAAR = file("$projectDir/../../node_modules/hermes-engine/android/hermes-debug.aar")
}
}
def soFiles = zipTree(hermesAAR).matching({ it.include "**/*.so" })
copy {
from soFiles
from "src/main/jni/first-party/hermes/Android.mk"
into "$thirdPartyNdkDir/hermes"
}
}
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, prepareHermes, 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")
exclude("**/libhermes.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("com.facebook.yoga:proguard-annotations:1.14.1")
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}")
debugImplementation("com.facebook.flipper:flipper:${FLIPPER_VERSION}") {
exclude group:'com.facebook.yoga'
exclude group:'com.facebook.flipper', module: 'fbjni'
exclude group:'com.facebook.litho', module: 'litho-annotations'
}
}
apply(from: "release.gradle")