From bd7d10e5aace9eaee620409a1451356f02b837cc Mon Sep 17 00:00:00 2001 From: Andrew Jack Date: Fri, 8 Jan 2016 12:11:34 -0800 Subject: [PATCH] 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 --- .../templates/src/app/build.gradle | 10 +- .../templates/src/app/react.gradle | 140 ++++++++---------- 2 files changed, 74 insertions(+), 76 deletions(-) diff --git a/local-cli/generator-android/templates/src/app/build.gradle b/local-cli/generator-android/templates/src/app/build.gradle index b68fc50c5..68f2f417f 100644 --- a/local-cli/generator-android/templates/src/app/build.gradle +++ b/local-cli/generator-android/templates/src/app/build.gradle @@ -3,7 +3,8 @@ apply plugin: "com.android.application" 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 * 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 @@ -23,6 +24,13 @@ import com.android.build.OutputFile * // whether to bundle JS and assets in release mode * 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 * root: "../../", * diff --git a/local-cli/generator-android/templates/src/app/react.gradle b/local-cli/generator-android/templates/src/app/react.gradle index f2152d1f6..4b43bf910 100644 --- a/local-cli/generator-android/templates/src/app/react.gradle +++ b/local-cli/generator-android/templates/src/app/react.gradle @@ -11,69 +11,8 @@ def elvisFile(thing) { } 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 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) { Task dependentTask = tasks.findByPath(dependentTaskName); if (dependentTask != null) { @@ -82,25 +21,76 @@ void runBefore(String dependentTaskName, Task task) { } 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 - bundleDebugJsAndAssets.dependsOn mergeDebugAssets + productFlavors.each { productFlavorName -> + buildTypes.each { buildTypeName -> + // Create variant and source names + def sourceName = "${buildTypeName}" + def targetName = "${sourceName.capitalize()}" + if (productFlavorName) { + sourceName = "${productFlavorName}${targetName}" + } - runBefore('processArmeabi-v7aDebugResources', bundleDebugJsAndAssets) - runBefore('processX86DebugResources', bundleDebugJsAndAssets) - runBefore('processUniversalDebugResources', bundleDebugJsAndAssets) - runBefore('processDebugResources', bundleDebugJsAndAssets) + // React js bundle directories + def jsBundleDirConfigName = "jsBundleDir${targetName}" + def jsBundleDir = elvisFile(config."$jsBundleDirConfigName") ?: + 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 - bundleReleaseJsAndAssets.dependsOn mergeReleaseAssets + // Bundle task name for variant + def bundleJsAndAssetsTaskName = "bundle${targetName}JsAndAssets" - runBefore('processArmeabi-v7aReleaseResources', bundleReleaseJsAndAssets) - runBefore('processX86ReleaseResources', bundleReleaseJsAndAssets) - runBefore('processUniversalReleaseResources', bundleReleaseJsAndAssets) - runBefore('processReleaseResources', bundleReleaseJsAndAssets) + def currentBundleTask = tasks.create( + name: bundleJsAndAssetsTaskName, + type: Exec) { + 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) + } + } }