mirror of
https://github.com/status-im/react-native.git
synced 2025-02-03 21:24:31 +00:00
Better Android Gradle Plugin 3.x integration
Summary: Better integration with the Android Gradle-based build process, especially the changes introduced by the [Android Gradle Plugin 3.x and AAPT2](https://developer.android.com/studio/build/gradle-plugin-3-0-0-migration.html). Fixes #16906, the `android.enableAapt2=false` workaround is no longer required. Bases the task generation process on the actual application variants present in the project. The current manual process of iterating build types and product flavors could break down when more than one dimension type is present (see https://developer.android.com/studio/build/build-variants.html#flavor-dimensions). This also exposes a very basic set of properties in the build tasks, so that other tasks can more reliably access them: ```groovy android.applicationVariants.all { variant -> // This is the generated task itself: def reactBundleTask = variant.bundleJsAndAssets // These are the outputs by type: def resFileCollection = reactBundleTask.generatedResFolders def assetsFileCollection = reactBundleTask.generatedAssetsFolders } ``` I've tested various combinations of product flavors and build types ([Build Variants](https://developer.android.com/studio/build/build-variants.html)) to make sure this is consistent. This is a port of what we're currently deploying to our CI process. [ ANDROID ] [ BUGFIX ] [ react.gradle ] - Support Android Gradle Plugin 3.x and AAPT2 [ ANDROID ] [ FEATURE ] [ react.gradle ] - Expose the bundling task and its outputs via ext properties Closes https://github.com/facebook/react-native/pull/17967 Differential Revision: D7017148 Pulled By: hramos fbshipit-source-id: e52b3365e5807430b9caced51349abf72332a587
This commit is contained in:
parent
5447ca6707
commit
d16ff3bd8b
99
react.gradle
99
react.gradle
@ -6,67 +6,38 @@ def cliPath = config.cliPath ?: "node_modules/react-native/local-cli/cli.js"
|
|||||||
def bundleAssetName = config.bundleAssetName ?: "index.android.bundle"
|
def bundleAssetName = config.bundleAssetName ?: "index.android.bundle"
|
||||||
def entryFile = config.entryFile ?: "index.android.js"
|
def entryFile = config.entryFile ?: "index.android.js"
|
||||||
def bundleCommand = config.bundleCommand ?: "bundle"
|
def bundleCommand = config.bundleCommand ?: "bundle"
|
||||||
|
def reactRoot = file(config.root ?: "../../")
|
||||||
// because elvis operator
|
|
||||||
def elvisFile(thing) {
|
|
||||||
return thing ? file(thing) : null;
|
|
||||||
}
|
|
||||||
|
|
||||||
def reactRoot = elvisFile(config.root) ?: file("../../")
|
|
||||||
def inputExcludes = config.inputExcludes ?: ["android/**", "ios/**"]
|
def inputExcludes = config.inputExcludes ?: ["android/**", "ios/**"]
|
||||||
def bundleConfig = config.bundleConfig ? "${reactRoot}/${config.bundleConfig}" : null ;
|
def bundleConfig = config.bundleConfig ? "${reactRoot}/${config.bundleConfig}" : null ;
|
||||||
|
|
||||||
void runBefore(String dependentTaskName, Task task) {
|
|
||||||
Task dependentTask = tasks.findByPath(dependentTaskName);
|
|
||||||
if (dependentTask != null) {
|
|
||||||
dependentTask.dependsOn task
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
gradle.projectsEvaluated {
|
gradle.projectsEvaluated {
|
||||||
// Grab all build types and product flavors
|
android.applicationVariants.all { def variant ->
|
||||||
def buildTypes = android.buildTypes.collect { type -> type.name }
|
|
||||||
def productFlavors = android.productFlavors.collect { flavor -> flavor.name }
|
|
||||||
|
|
||||||
// When no product flavors defined, use empty
|
|
||||||
if (!productFlavors) productFlavors.add('')
|
|
||||||
|
|
||||||
productFlavors.each { productFlavorName ->
|
|
||||||
buildTypes.each { buildTypeName ->
|
|
||||||
// Create variant and target names
|
// Create variant and target names
|
||||||
def flavorNameCapitalized = "${productFlavorName.capitalize()}"
|
def targetName = variant.name.capitalize()
|
||||||
def buildNameCapitalized = "${buildTypeName.capitalize()}"
|
def targetPath = variant.dirName
|
||||||
def targetName = "${flavorNameCapitalized}${buildNameCapitalized}"
|
|
||||||
def targetPath = productFlavorName ?
|
|
||||||
"${productFlavorName}/${buildTypeName}" :
|
|
||||||
"${buildTypeName}"
|
|
||||||
|
|
||||||
// React js bundle directories
|
// React js bundle directories
|
||||||
def jsBundleDirConfigName = "jsBundleDir${targetName}"
|
def jsBundleDir = file("$buildDir/generated/assets/react/${targetPath}")
|
||||||
def jsBundleDir = elvisFile(config."$jsBundleDirConfigName") ?:
|
def resourcesDir = file("$buildDir/generated/res/react/${targetPath}")
|
||||||
file("$buildDir/intermediates/assets/${targetPath}")
|
|
||||||
|
|
||||||
def resourcesDirConfigName = "resourcesDir${targetName}"
|
|
||||||
def resourcesDir = elvisFile(config."${resourcesDirConfigName}") ?:
|
|
||||||
file("$buildDir/intermediates/res/merged/${targetPath}")
|
|
||||||
def jsBundleFile = file("$jsBundleDir/$bundleAssetName")
|
def jsBundleFile = file("$jsBundleDir/$bundleAssetName")
|
||||||
|
|
||||||
// Bundle task name for variant
|
|
||||||
def bundleJsAndAssetsTaskName = "bundle${targetName}JsAndAssets"
|
|
||||||
|
|
||||||
// Additional node and packager commandline arguments
|
// Additional node and packager commandline arguments
|
||||||
def nodeExecutableAndArgs = config.nodeExecutableAndArgs ?: ["node"]
|
def nodeExecutableAndArgs = config.nodeExecutableAndArgs ?: ["node"]
|
||||||
def extraPackagerArgs = config.extraPackagerArgs ?: []
|
def extraPackagerArgs = config.extraPackagerArgs ?: []
|
||||||
|
|
||||||
def currentBundleTask = tasks.create(
|
def currentBundleTask = tasks.create(
|
||||||
name: bundleJsAndAssetsTaskName,
|
name: "bundle${targetName}JsAndAssets",
|
||||||
type: Exec) {
|
type: Exec) {
|
||||||
group = "react"
|
group = "react"
|
||||||
description = "bundle JS and assets for ${targetName}."
|
description = "bundle JS and assets for ${targetName}."
|
||||||
|
|
||||||
// Create dirs if they are not there (e.g. the "clean" task just ran)
|
// Create dirs if they are not there (e.g. the "clean" task just ran)
|
||||||
doFirst {
|
doFirst {
|
||||||
|
jsBundleDir.deleteDir()
|
||||||
jsBundleDir.mkdirs()
|
jsBundleDir.mkdirs()
|
||||||
|
resourcesDir.deleteDir()
|
||||||
resourcesDir.mkdirs()
|
resourcesDir.mkdirs()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -99,19 +70,53 @@ gradle.projectsEvaluated {
|
|||||||
}
|
}
|
||||||
|
|
||||||
enabled config."bundleIn${targetName}" ||
|
enabled config."bundleIn${targetName}" ||
|
||||||
config."bundleIn${buildTypeName.capitalize()}" ?:
|
config."bundleIn${variant.buildType.name.capitalize()}" ?:
|
||||||
targetName.toLowerCase().contains("release")
|
targetName.toLowerCase().contains("release")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hook bundle${productFlavor}${buildType}JsAndAssets into the android build process
|
// Expose a minimal interface on the application variant and the task itself:
|
||||||
currentBundleTask.dependsOn("merge${targetName}Resources")
|
variant.ext.bundleJsAndAssets = currentBundleTask
|
||||||
currentBundleTask.dependsOn("merge${targetName}Assets")
|
currentBundleTask.ext.generatedResFolders = files(resourcesDir).builtBy(currentBundleTask)
|
||||||
|
currentBundleTask.ext.generatedAssetsFolders = files(jsBundleDir).builtBy(currentBundleTask)
|
||||||
|
|
||||||
runBefore("process${flavorNameCapitalized}Armeabi-v7a${buildNameCapitalized}Resources", currentBundleTask)
|
variant.registerGeneratedResFolders(currentBundleTask.generatedResFolders)
|
||||||
runBefore("process${flavorNameCapitalized}X86${buildNameCapitalized}Resources", currentBundleTask)
|
variant.mergeResources.dependsOn(currentBundleTask)
|
||||||
runBefore("processUniversal${targetName}Resources", currentBundleTask)
|
|
||||||
runBefore("process${targetName}Resources", currentBundleTask)
|
def resourcesDirConfigValue = config."resourcesDir${targetName}"
|
||||||
runBefore("dataBindingProcessLayouts${targetName}", currentBundleTask)
|
if (resourcesDirConfigValue) {
|
||||||
|
def currentCopyResTask = tasks.create(
|
||||||
|
name: "copy${targetName}BundledResources",
|
||||||
|
type: Copy) {
|
||||||
|
group = "react"
|
||||||
|
description = "copy bundled resources into custom location for ${targetName}."
|
||||||
|
|
||||||
|
from resourcesDir
|
||||||
|
into file(resourcesDirConfigValue)
|
||||||
|
|
||||||
|
dependsOn(currentBundleTask)
|
||||||
|
|
||||||
|
enabled currentBundleTask.enabled
|
||||||
}
|
}
|
||||||
|
|
||||||
|
variant.packageApplication.dependsOn(currentCopyResTask)
|
||||||
|
}
|
||||||
|
|
||||||
|
def currentAssetsCopyTask = tasks.create(
|
||||||
|
name: "copy${targetName}BundledJs",
|
||||||
|
type: Copy) {
|
||||||
|
group = "react"
|
||||||
|
description = "copy bundled JS into ${targetName}."
|
||||||
|
|
||||||
|
from jsBundleDir
|
||||||
|
into file(config."jsBundleDir${targetName}" ?:
|
||||||
|
"$buildDir/intermediates/assets/${targetPath}")
|
||||||
|
|
||||||
|
// mergeAssets must run first, as it clears the intermediates directory
|
||||||
|
dependsOn(variant.mergeAssets)
|
||||||
|
|
||||||
|
enabled currentBundleTask.enabled
|
||||||
|
}
|
||||||
|
|
||||||
|
variant.packageApplication.dependsOn(currentAssetsCopyTask)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user