471 lines
18 KiB
Groovy
471 lines
18 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 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
|
||
|
|
||
|
// 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 hermesPackagePath = findNodeModulePath(projectDir, "hermes-engine")
|
||
|
if (!hermesPackagePath) {
|
||
|
throw new GradleScriptException("Could not find the hermes-engine npm package")
|
||
|
}
|
||
|
|
||
|
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 {
|
||
|
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 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(jscDist).matching({ it.include "**/android-jsc/**/*.aar" }).singleFile
|
||
|
def soFiles = zipTree(jscAAR).matching({ it.include "**/*.so" })
|
||
|
|
||
|
def headerFiles = fileTree(jscDist).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)
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* 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) {
|
||
|
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"
|
||
|
} 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.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
|
||
|
}
|
||
|
|
||
|
def buildReactNdkLib = tasks.register("buildReactNdkLib", Exec) {
|
||
|
dependsOn(prepareJSC, prepareHermes, prepareBoost, prepareDoubleConversion, prepareFolly, prepareGlog, extractAARHeaders, extractJNIFiles)
|
||
|
|
||
|
inputs.dir("$projectDir/../ReactCommon")
|
||
|
inputs.dir("src/main/jni")
|
||
|
inputs.dir("src/main/java/com/facebook/react/modules/blob")
|
||
|
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()
|
||
|
)
|
||
|
}
|
||
|
|
||
|
def cleanReactNdkLib = tasks.register("cleanReactNdkLib", 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)}")
|
||
|
}
|
||
|
}
|
||
|
|
||
|
def packageReactNdkLibs = tasks.register("packageReactNdkLibs", Copy) {
|
||
|
dependsOn(buildReactNdkLib)
|
||
|
from("$buildDir/react-ndk/all")
|
||
|
into("$buildDir/react-ndk/exported")
|
||
|
exclude("**/libjsc.so")
|
||
|
exclude("**/libhermes.so")
|
||
|
}
|
||
|
|
||
|
def packageReactNdkLibsForBuck = tasks.register("packageReactNdkLibsForBuck", Copy) {
|
||
|
dependsOn(packageReactNdkLibs)
|
||
|
from("$buildDir/react-ndk/exported")
|
||
|
into("src/main/jni/prebuilt/lib")
|
||
|
}
|
||
|
|
||
|
task extractAARHeaders {
|
||
|
doLast {
|
||
|
configurations.extractHeaders.files.each {
|
||
|
def file = it.absoluteFile
|
||
|
def packageName = file.name.tokenize('-')[0]
|
||
|
copy {
|
||
|
from zipTree(file)
|
||
|
into "$projectDir/src/main/jni/first-party/$packageName/headers"
|
||
|
include "**/*.h"
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
task extractJNIFiles {
|
||
|
doLast {
|
||
|
configurations.extractJNI.files.each {
|
||
|
def file = it.absoluteFile
|
||
|
def packageName = file.name.tokenize('-')[0]
|
||
|
copy {
|
||
|
from zipTree(file)
|
||
|
into "$projectDir/src/main/jni/first-party/$packageName/"
|
||
|
include "jni/**/*"
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
android {
|
||
|
compileSdkVersion 29
|
||
|
|
||
|
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")
|
||
|
}
|
||
|
|
||
|
configurations {
|
||
|
extractHeaders
|
||
|
extractJNI
|
||
|
}
|
||
|
}
|
||
|
|
||
|
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("androidx.swiperefreshlayout:swiperefreshlayout:1.0.0")
|
||
|
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")
|
||
|
api("com.facebook.fbjni:fbjni-java-only:0.0.3")
|
||
|
extractHeaders("com.facebook.fbjni:fbjni:0.0.2:headers")
|
||
|
extractJNI("com.facebook.fbjni:fbjni:0.0.2")
|
||
|
|
||
|
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("androidx.test:runner:${ANDROIDX_TEST_VERSION}")
|
||
|
androidTestImplementation("androidx.test:rules:${ANDROIDX_TEST_VERSION}")
|
||
|
androidTestImplementation("org.mockito:mockito-core:${MOCKITO_CORE_VERSION}")
|
||
|
}
|
||
|
|
||
|
apply(from: "release.gradle")
|