react-native/ReactAndroid/build.gradle

323 lines
13 KiB
Groovy
Raw Normal View History

// 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.
2015-09-16 17:38:42 +00:00
plugins {
id("com.android.library")
id("maven")
id("de.undercouch.download")
}
2015-09-16 17:38:42 +00:00
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.
2015-09-16 17:38:42 +00:00
def customDownloadsDir = System.getenv("REACT_NATIVE_DOWNLOADS_DIR")
def downloadsDir = customDownloadsDir ? new File(customDownloadsDir) : new File("$buildDir/downloads")
2015-09-16 17:38:42 +00:00
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
// - jsc-headers
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")
2015-09-16 17:38:42 +00:00
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"
2015-09-16 17:38:42 +00:00
onlyIfNewer true
overwrite false
dest new File(downloadsDir, "boost_${BOOST_VERSION}.tar.gz")
2015-09-16 17:38:42 +00:00
}
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}")
}
2015-09-16 17:38:42 +00:00
}
task downloadDoubleConversion(dependsOn: createNativeDepsDirectories, type: Download) {
src "https://github.com/google/double-conversion/archive/v${DOUBLE_CONVERSION_VERSION}.tar.gz"
2015-09-16 17:38:42 +00:00
onlyIfNewer true
overwrite false
dest new File(downloadsDir, "double-conversion-${DOUBLE_CONVERSION_VERSION}.tar.gz")
2015-09-16 17:38:42 +00:00
}
task prepareDoubleConversion(dependsOn: dependenciesPath ? [] : [downloadDoubleConversion], type: Copy) {
from dependenciesPath ?: tarTree(downloadDoubleConversion.dest)
2015-09-16 17:38:42 +00:00
from 'src/main/jni/third-party/double-conversion/Android.mk'
include "double-conversion-${DOUBLE_CONVERSION_VERSION}/src/**/*", 'Android.mk'
2015-09-16 17:38:42 +00:00
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"
2015-09-16 17:38:42 +00:00
onlyIfNewer true
overwrite false
dest new File(downloadsDir, "folly-${FOLLY_VERSION}.tar.gz");
2015-09-16 17:38:42 +00:00
}
task prepareFolly(dependsOn: dependenciesPath ? [] : [downloadFolly], type: Copy) {
from dependenciesPath ?: tarTree(downloadFolly.dest)
2015-09-16 17:38:42 +00:00
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}/")}
2015-09-16 17:38:42 +00:00
includeEmptyDirs = false
into "$thirdPartyNdkDir/folly"
}
task downloadGlog(dependsOn: createNativeDepsDirectories, type: Download) {
src "https://github.com/google/glog/archive/v${GLOG_VERSION}.tar.gz"
2015-09-16 17:38:42 +00:00
onlyIfNewer true
overwrite false
dest new File(downloadsDir, "glog-${GLOG_VERSION}.tar.gz")
2015-09-16 17:38:42 +00:00
}
// Prepare glog sources to be compiled, this task will perform steps that normally should've been
2015-09-16 17:38:42 +00:00
// executed by automake. This way we can avoid dependencies on make/automake
task prepareGlog(dependsOn: dependenciesPath ? [] : [downloadGlog], type: Copy) {
from dependenciesPath ?: tarTree(downloadGlog.dest)
2015-09-16 17:38:42 +00:00
from 'src/main/jni/third-party/glog/'
include "glog-${GLOG_VERSION}/src/**/*", 'Android.mk', 'config.h'
2015-09-16 17:38:42 +00:00
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"
}
task downloadJSCHeaders(type: Download) {
// in sync with webkit SVN revision 174650
def jscAPIBaseURL = 'https://raw.githubusercontent.com/WebKit/webkit/38b15a3ba3c1b0798f2036f7cea36ffdc096202e/Source/JavaScriptCore/API/'
def jscHeaderFiles = ['JavaScript.h', 'JSBase.h', 'JSContextRef.h', 'JSObjectRef.h', 'JSRetainPtr.h', 'JSStringRef.h', 'JSValueRef.h', 'WebKitAvailability.h']
2015-09-16 17:38:42 +00:00
def output = new File(downloadsDir, 'jsc')
output.mkdirs()
src(jscHeaderFiles.collect { headerName -> "$jscAPIBaseURL$headerName" })
onlyIfNewer true
overwrite false
dest output
}
// Create Android.mk library module based on so files from mvn + include headers fetched from webkit.org
task prepareJSC(dependsOn: dependenciesPath ? [] : [downloadJSCHeaders]) << {
2015-09-16 17:38:42 +00:00
copy {
from zipTree(configurations.compile.fileCollection { dep -> dep.name == 'android-jsc' }.singleFile)
from dependenciesPath ? "$dependenciesPath/jsc-headers" : {downloadJSCHeaders.dest}
2015-09-16 17:38:42 +00:00
from 'src/main/jni/third-party/jsc/Android.mk'
include 'jni/**/*.so', '*.h', 'Android.mk'
filesMatching('*.h', { fname -> fname.path = "JavaScriptCore/${fname.path}"})
into "$thirdPartyNdkDir/jsc";
}
}
task downloadNdkBuildDependencies {
if (!boostPath) {
dependsOn downloadBoost
}
dependsOn downloadDoubleConversion
dependsOn downloadFolly
dependsOn downloadGlog
dependsOn downloadJSCHeaders
}
2015-09-16 17:38:42 +00:00
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.absolutePath
2015-09-16 17:38:42 +00:00
if (ndkDir) {
return new File(ndkDir, getNdkBuildName()).getAbsolutePath()
}
return null
}
def getNdkBuildFullPath() {
def ndkBuildFullPath = findNdkBuildFullPath()
if (ndkBuildFullPath == null) {
2015-09-16 17:38:42 +00:00
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)
}
2015-09-16 17:38:42 +00:00
return ndkBuildFullPath
}
task buildReactNdkLib(dependsOn: [prepareJSC, prepareBoost, prepareDoubleConversion, prepareFolly, prepareGlog], type: Exec) {
inputs.file('src/main/jni/react')
2015-09-16 17:38:42 +00:00
outputs.dir("$buildDir/react-ndk/all")
commandLine getNdkBuildFullPath(),
'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",
'-C', file('src/main/jni/react/jni').absolutePath,
'--jobs', project.hasProperty("jobs") ? project.property("jobs") : Runtime.runtime.availableProcessors()
2015-09-16 17:38:42 +00:00
}
task cleanReactNdkLib(type: Exec) {
commandLine getNdkBuildFullPath(),
"NDK_APPLICATION_MK=$projectDir/src/main/jni/Application.mk",
"THIRD_PARTY_NDK_DIR=$buildDir/third-party-ndk",
"REACT_COMMON_DIR=$projectDir/../ReactCommon",
2015-09-16 17:38:42 +00:00
'-C', file('src/main/jni/react/jni').absolutePath,
'clean'
}
task packageReactNdkLibs(dependsOn: buildReactNdkLib, type: Copy) {
from "$buildDir/react-ndk/all"
exclude '**/libjsc.so'
into "$buildDir/react-ndk/exported"
}
task packageReactNdkLibsForBuck(dependsOn: packageReactNdkLibs, type: Copy) {
from "$buildDir/react-ndk/exported"
into "src/main/jni/prebuilt/lib"
}
2015-09-16 17:38:42 +00:00
android {
compileSdkVersion 26
buildToolsVersion "27.0.3"
2015-09-16 17:38:42 +00:00
defaultConfig {
minSdkVersion 16
targetSdkVersion 26
2015-09-16 17:38:42 +00:00
versionCode 1
versionName "1.0"
Inline and fix proguard rules Summary: The original proguard rules are put in the template, which is not very convenient and easy to get wrong. Because new rules get put, people also has two copy paste the rule. And there are also existing project import react native as a dependency. So the best way to keep a android library project proguard rule is to manage the rule itself, using `consumerProguardFiles` like [dagger](https://github.com/JakeWharton/butterknife/blob/46baef6d96e93a1872efa17fdfc1d2af59b36f0c/butterknife/build.gradle#L9) and other android library project. <!-- Required: Write your motivation here. If this PR fixes an issue, type "Fixes #issueNumber" to automatically close the issue when the PR is merged. --> Use RNTester to build the release flavor (now it has bugs https://github.com/facebook/react-native/issues/18460, I keep my change in local for now), after build success, run to check if crash. In the process, I also fix https://github.com/facebook/react-native/issues/12994 and https://github.com/facebook/react-native/issues/6624 by adding the following to proguard rules ```proguard -keep,includedescriptorclasses class com.facebook.react.bridge.** { *; } ``` <!-- Does this PR require a documentation change? Create a PR at https://github.com/facebook/react-native-website and add a link to it here. --> [ANDROID] [ENHANCEMENT and BUGFIX] [Proguard rules] - inline and fix proguard rules . <!-- **INTERNAL and MINOR tagged notes will not be included in the next version's final release notes.** CATEGORY [----------] TYPE [ CLI ] [-------------] LOCATION [ DOCS ] [ BREAKING ] [-------------] [ GENERAL ] [ BUGFIX ] [ {Component} ] [ INTERNAL ] [ ENHANCEMENT ] [ {Filename} ] [ IOS ] [ FEATURE ] [ {Directory} ] |-----------| [ ANDROID ] [ MINOR ] [ {Framework} ] - | {Message} | [----------] [-------------] [-------------] |-----------| EXAMPLES: [IOS] [BREAKING] [FlatList] - Change a thing that breaks other things [ANDROID] [BUGFIX] [TextInput] - Did a thing to TextInput [CLI] [FEATURE] [local-cli/info/info.js] - CLI easier to do things with [DOCS] [BUGFIX] [GettingStarted.md] - Accidentally a thing/word [GENERAL] [ENHANCEMENT] [Yoga] - Added new yoga thing/position [INTERNAL] [FEATURE] [./scripts] - Added thing to script that nobody will see --> Closes https://github.com/facebook/react-native/pull/18461 Differential Revision: D7527533 Pulled By: hramos fbshipit-source-id: 447dbc16983bcfb597187b40c1be3987a8c5a832
2018-04-06 00:26:39 +00:00
consumerProguardFiles 'proguard-rules.pro'
2015-09-16 17:38:42 +00:00
ndk {
moduleName "reactnativejni"
}
buildConfigField 'boolean', 'IS_INTERNAL_BUILD', 'false'
buildConfigField 'int', 'EXOPACKAGE_FLAGS', '0'
testApplicationId "com.facebook.react.tests.gradle"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
2015-09-16 17:38:42 +00:00
}
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'
}
2015-09-16 17:38:42 +00:00
}
tasks.withType(JavaCompile) {
compileTask -> compileTask.dependsOn packageReactNdkLibs
}
clean.dependsOn cleanReactNdkLib
lintOptions {
abortOnError false
}
packagingOptions {
exclude 'META-INF/NOTICE'
exclude 'META-INF/LICENSE'
}
2015-09-16 17:38:42 +00:00
}
dependencies {
api 'com.facebook.infer.annotation:infer-annotation:0.11.2'
api 'javax.inject:javax.inject:1'
api 'com.android.support:appcompat-v7:27.1.1'
api "com.facebook.fresco:fresco:${FRESCO_VERSION}"
api "com.facebook.fresco:imagepipeline-okhttp3:${FRESCO_VERSION}"
api 'com.facebook.soloader:soloader:0.5.1'
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.14.0'
2015-09-16 17:38:42 +00:00
compile 'org.webkit:android-jsc:r174650'
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'])
androidTestImplementation 'com.android.support.test:runner:0.3'
androidTestImplementation "org.mockito:mockito-core:${MOCKITO_CORE_VERSION}"
2015-09-16 17:38:42 +00:00
}
apply from: 'release.gradle'