Add support for Build Variants to react.gradle

Summary:
This PR adds support for Android Gradle [Build Variants](https://sites.google.com/a/android.com/tools/tech-docs/new-build-system/user-guide#TOC-Build-Variants) when generating the JS bundle.

**Before**: only supported "bundleDebugJsAndAssets" and "bundleReleaseJsAndAssets"

**Now**: all variants are supported
Examples: "bundleDevDebugJsAndAssets", "bundleStageAlphaJsAndAssets", or "bundleBetaJsAndAssets"

The Gradle script will automatically create bundle tasks for each build variant found in a project.
Closes https://github.com/facebook/react-native/pull/4686

Reviewed By: svcscm

Differential Revision: D2815856

Pulled By: foghina

fb-gh-sync-id: 4518de70d178205bc3e5044d2446b56c40298da2
This commit is contained in:
Andrew Jack 2016-01-08 12:11:34 -08:00 committed by facebook-github-bot-3
parent de392b5351
commit bd7d10e5aa
2 changed files with 74 additions and 76 deletions

View File

@ -3,7 +3,8 @@ apply plugin: "com.android.application"
import com.android.build.OutputFile import com.android.build.OutputFile
/** /**
* The react.gradle file registers two tasks: bundleDebugJsAndAssets and bundleReleaseJsAndAssets. * The react.gradle file registers a task for each build variant (e.g. bundleDebugJsAndAssets
* and bundleReleaseJsAndAssets).
* These basically call `react-native bundle` with the correct arguments during the Android build * These basically call `react-native bundle` with the correct arguments during the Android build
* cycle. By default, bundleDebugJsAndAssets is skipped, as in debug/dev mode we prefer to load the * cycle. By default, bundleDebugJsAndAssets is skipped, as in debug/dev mode we prefer to load the
* bundle directly from the development server. Below you can see all the possible configurations * bundle directly from the development server. Below you can see all the possible configurations
@ -23,6 +24,13 @@ import com.android.build.OutputFile
* // whether to bundle JS and assets in release mode * // whether to bundle JS and assets in release mode
* bundleInRelease: true, * bundleInRelease: true,
* *
* // whether to bundle JS and assets in another build variant (if configured).
* // See http://tools.android.com/tech-docs/new-build-system/user-guide#TOC-Build-Variants
* // The configuration property is in the format 'bundleIn${productFlavor}${buildType}'
* // bundleInFreeDebug: true,
* // bundleInPaidRelease: true,
* // bundleInBeta: true,
*
* // the root of your project, i.e. where "package.json" lives * // the root of your project, i.e. where "package.json" lives
* root: "../../", * root: "../../",
* *

View File

@ -11,69 +11,8 @@ def elvisFile(thing) {
} }
def reactRoot = elvisFile(config.root) ?: file("../../") def reactRoot = elvisFile(config.root) ?: file("../../")
def jsBundleDirDebug = elvisFile(config.jsBundleDirDebug) ?:
file("$buildDir/intermediates/assets/debug")
def jsBundleDirRelease = elvisFile(config.jsBundleDirRelease) ?:
file("$buildDir/intermediates/assets/release")
def resourcesDirDebug = elvisFile(config.resourcesDirDebug) ?:
file("$buildDir/intermediates/res/merged/debug")
def resourcesDirRelease = elvisFile(config.resourcesDirRelease) ?:
file("$buildDir/intermediates/res/merged/release")
def inputExcludes = config.inputExcludes ?: ["android/**", "ios/**"] def inputExcludes = config.inputExcludes ?: ["android/**", "ios/**"]
def jsBundleFileDebug = file("$jsBundleDirDebug/$bundleAssetName")
def jsBundleFileRelease = file("$jsBundleDirRelease/$bundleAssetName")
task bundleDebugJsAndAssets(type: Exec) {
// create dirs if they are not there (e.g. the "clean" task just ran)
doFirst {
jsBundleDirDebug.mkdirs()
resourcesDirDebug.mkdirs()
}
// set up inputs and outputs so gradle can cache the result
inputs.files fileTree(dir: reactRoot, excludes: inputExcludes)
outputs.dir jsBundleDirDebug
outputs.dir resourcesDirDebug
// set up the call to the react-native cli
workingDir reactRoot
if (Os.isFamily(Os.FAMILY_WINDOWS)) {
commandLine "cmd", "/c", "react-native", "bundle", "--platform", "android", "--dev", "true", "--entry-file",
entryFile, "--bundle-output", jsBundleFileDebug, "--assets-dest", resourcesDirDebug
} else {
commandLine "react-native", "bundle", "--platform", "android", "--dev", "true", "--entry-file",
entryFile, "--bundle-output", jsBundleFileDebug, "--assets-dest", resourcesDirDebug
}
enabled config.bundleInDebug ?: false
}
task bundleReleaseJsAndAssets(type: Exec) {
// create dirs if they are not there (e.g. the "clean" task just ran)
doFirst {
jsBundleDirRelease.mkdirs()
resourcesDirRelease.mkdirs()
}
// set up inputs and outputs so gradle can cache the result
inputs.files fileTree(dir: reactRoot, excludes: inputExcludes)
outputs.dir jsBundleDirRelease
outputs.dir resourcesDirRelease
// set up the call to the react-native cli
workingDir reactRoot
if (Os.isFamily(Os.FAMILY_WINDOWS)) {
commandLine "cmd","/c", "react-native", "bundle", "--platform", "android", "--dev", "false", "--entry-file",
entryFile, "--bundle-output", jsBundleFileRelease, "--assets-dest", resourcesDirRelease
} else {
commandLine "react-native", "bundle", "--platform", "android", "--dev", "false", "--entry-file",
entryFile, "--bundle-output", jsBundleFileRelease, "--assets-dest", resourcesDirRelease
}
enabled config.bundleInRelease ?: true
}
void runBefore(String dependentTaskName, Task task) { void runBefore(String dependentTaskName, Task task) {
Task dependentTask = tasks.findByPath(dependentTaskName); Task dependentTask = tasks.findByPath(dependentTaskName);
if (dependentTask != null) { if (dependentTask != null) {
@ -82,25 +21,76 @@ void runBefore(String dependentTaskName, Task task) {
} }
gradle.projectsEvaluated { gradle.projectsEvaluated {
// Grab all build types and product flavors
def buildTypes = android.buildTypes.collect { type -> type.name }
def productFlavors = android.productFlavors.collect { flavor -> flavor.name }
// hook bundleDebugJsAndAssets into the android build process // When no product flavors defined, use empty
if (!productFlavors) productFlavors.add('')
bundleDebugJsAndAssets.dependsOn mergeDebugResources productFlavors.each { productFlavorName ->
bundleDebugJsAndAssets.dependsOn mergeDebugAssets buildTypes.each { buildTypeName ->
// Create variant and source names
def sourceName = "${buildTypeName}"
def targetName = "${sourceName.capitalize()}"
if (productFlavorName) {
sourceName = "${productFlavorName}${targetName}"
}
runBefore('processArmeabi-v7aDebugResources', bundleDebugJsAndAssets) // React js bundle directories
runBefore('processX86DebugResources', bundleDebugJsAndAssets) def jsBundleDirConfigName = "jsBundleDir${targetName}"
runBefore('processUniversalDebugResources', bundleDebugJsAndAssets) def jsBundleDir = elvisFile(config."$jsBundleDirConfigName") ?:
runBefore('processDebugResources', bundleDebugJsAndAssets) file("$buildDir/intermediates/assets/${sourceName}")
// hook bundleReleaseJsAndAssets into the android build process def resourcesDirConfigName = "jsBundleDir${targetName}"
def resourcesDir = elvisFile(config."${resourcesDirConfigName}") ?:
file("$buildDir/intermediates/res/merged/${sourceName}")
def jsBundleFile = file("$jsBundleDir/$bundleAssetName")
bundleReleaseJsAndAssets.dependsOn mergeReleaseResources // Bundle task name for variant
bundleReleaseJsAndAssets.dependsOn mergeReleaseAssets def bundleJsAndAssetsTaskName = "bundle${targetName}JsAndAssets"
runBefore('processArmeabi-v7aReleaseResources', bundleReleaseJsAndAssets) def currentBundleTask = tasks.create(
runBefore('processX86ReleaseResources', bundleReleaseJsAndAssets) name: bundleJsAndAssetsTaskName,
runBefore('processUniversalReleaseResources', bundleReleaseJsAndAssets) type: Exec) {
runBefore('processReleaseResources', bundleReleaseJsAndAssets) group = "react"
description = "bundle JS and assets for ${targetName}."
// Create dirs if they are not there (e.g. the "clean" task just ran)
doFirst {
jsBundleDir.mkdirs()
resourcesDir.mkdirs()
}
// Set up inputs and outputs so gradle can cache the result
inputs.files fileTree(dir: reactRoot, excludes: inputExcludes)
outputs.dir jsBundleDir
outputs.dir resourcesDir
// Set up the call to the react-native cli
workingDir reactRoot
// Set up dev mode
def devEnabled = !targetName.toLowerCase().contains("release")
if (Os.isFamily(Os.FAMILY_WINDOWS)) {
commandLine "cmd", "/c", "react-native", "bundle", "--platform", "android", "--dev", "${devEnabled}",
"--entry-file", entryFile, "--bundle-output", jsBundleFile, "--assets-dest", resourcesDir
} else {
commandLine "react-native", "bundle", "--platform", "android", "--dev", "${devEnabled}",
"--entry-file", entryFile, "--bundle-output", jsBundleFile, "--assets-dest", resourcesDir
}
enabled config."bundleIn${targetName}" ?: targetName.toLowerCase().contains("release")
}
// Hook bundle${productFlavor}${buildType}JsAndAssets into the android build process
currentBundleTask.dependsOn("merge${targetName}Resources")
currentBundleTask.dependsOn("merge${targetName}Assets")
runBefore("processArmeabi-v7a${targetName}Resources", currentBundleTask)
runBefore("processX86${targetName}Resources", currentBundleTask)
runBefore("processUniversal${targetName}Resources", currentBundleTask)
runBefore("process${targetName}Resources", currentBundleTask)
}
}
} }