From 78577ccbd719d360572cc1a809fb345f76c594de Mon Sep 17 00:00:00 2001 From: Kevin Cassidy Jr Date: Tue, 13 Feb 2018 09:14:45 -0800 Subject: [PATCH 1/2] AAPT2-compatible Android build process integration --- react.gradle | 199 ++++++++++++++++++++++++++------------------------- 1 file changed, 102 insertions(+), 97 deletions(-) diff --git a/react.gradle b/react.gradle index 64b2f02f8cbf26..685862193bb945 100644 --- a/react.gradle +++ b/react.gradle @@ -6,112 +6,117 @@ def cliPath = config.cliPath ?: "node_modules/react-native/local-cli/cli.js" def bundleAssetName = config.bundleAssetName ?: "index.android.bundle" def entryFile = config.entryFile ?: "index.android.js" def bundleCommand = config.bundleCommand ?: "bundle" - -// because elvis operator -def elvisFile(thing) { - return thing ? file(thing) : null; -} - -def reactRoot = elvisFile(config.root) ?: file("../../") +def reactRoot = file(config.root ?: "../../") def inputExcludes = config.inputExcludes ?: ["android/**", "ios/**"] 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 { - // Grab all build types and product flavors - 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 - def flavorNameCapitalized = "${productFlavorName.capitalize()}" - def buildNameCapitalized = "${buildTypeName.capitalize()}" - def targetName = "${flavorNameCapitalized}${buildNameCapitalized}" - def targetPath = productFlavorName ? - "${productFlavorName}/${buildTypeName}" : - "${buildTypeName}" - - // React js bundle directories - def jsBundleDirConfigName = "jsBundleDir${targetName}" - def jsBundleDir = elvisFile(config."$jsBundleDirConfigName") ?: - 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") - - // Bundle task name for variant - def bundleJsAndAssetsTaskName = "bundle${targetName}JsAndAssets" - - // Additional node and packager commandline arguments - def nodeExecutableAndArgs = config.nodeExecutableAndArgs ?: ["node"] - def extraPackagerArgs = config.extraPackagerArgs ?: [] - - def currentBundleTask = tasks.create( - name: bundleJsAndAssetsTaskName, - type: Exec) { + android.applicationVariants.all { def variant -> + // Create variant and target names + def targetName = variant.name.capitalize() + def targetPath = variant.dirName + + // React js bundle directories + def jsBundleDir = file("$buildDir/generated/assets/react/${targetPath}") + def resourcesDir = file("$buildDir/generated/res/react/${targetPath}") + + def jsBundleFile = file("$jsBundleDir/$bundleAssetName") + + // Additional node and packager commandline arguments + def nodeExecutableAndArgs = config.nodeExecutableAndArgs ?: ["node"] + def extraPackagerArgs = config.extraPackagerArgs ?: [] + + def currentBundleTask = tasks.create( + name: "bundle${targetName}JsAndAssets", + 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.deleteDir() + jsBundleDir.mkdirs() + resourcesDir.deleteDir() + 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 = !(config."devDisabledIn${targetName}" + || targetName.toLowerCase().contains("release")) + + def extraArgs = extraPackagerArgs; + + if (bundleConfig) { + extraArgs = extraArgs.clone() + extraArgs.add("--config"); + extraArgs.add(bundleConfig); + } + + if (Os.isFamily(Os.FAMILY_WINDOWS)) { + commandLine("cmd", "/c", *nodeExecutableAndArgs, cliPath, bundleCommand, "--platform", "android", "--dev", "${devEnabled}", + "--reset-cache", "--entry-file", entryFile, "--bundle-output", jsBundleFile, "--assets-dest", resourcesDir, *extraArgs) + } else { + commandLine(*nodeExecutableAndArgs, cliPath, bundleCommand, "--platform", "android", "--dev", "${devEnabled}", + "--reset-cache", "--entry-file", entryFile, "--bundle-output", jsBundleFile, "--assets-dest", resourcesDir, *extraArgs) + } + + enabled config."bundleIn${targetName}" || + config."bundleIn${variant.buildType.name.capitalize()}" ?: + targetName.toLowerCase().contains("release") + } + + // Expose a minimal interface on the application variant and the task itself: + variant.ext.bundleJsAndAssets = currentBundleTask + currentBundleTask.ext.generatedResFolders = files(resourcesDir).builtBy(currentBundleTask) + currentBundleTask.ext.generatedAssetsFolders = files(jsBundleDir).builtBy(currentBundleTask) + + variant.registerGeneratedResFolders(currentBundleTask.generatedResFolders) + variant.mergeResources.dependsOn(currentBundleTask) + + def resourcesDirConfigValue = config."resourcesDir${targetName}" + if (resourcesDirConfigValue) { + def currentCopyResTask = tasks.create( + name: "copy${targetName}BundledResources", + type: Copy) { 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 = !(config."devDisabledIn${targetName}" - || targetName.toLowerCase().contains("release")) - - def extraArgs = extraPackagerArgs; - - if (bundleConfig) { - extraArgs = extraArgs.clone() - extraArgs.add("--config"); - extraArgs.add(bundleConfig); - } - - if (Os.isFamily(Os.FAMILY_WINDOWS)) { - commandLine("cmd", "/c", *nodeExecutableAndArgs, cliPath, bundleCommand, "--platform", "android", "--dev", "${devEnabled}", - "--reset-cache", "--entry-file", entryFile, "--bundle-output", jsBundleFile, "--assets-dest", resourcesDir, *extraArgs) - } else { - commandLine(*nodeExecutableAndArgs, cliPath, bundleCommand, "--platform", "android", "--dev", "${devEnabled}", - "--reset-cache", "--entry-file", entryFile, "--bundle-output", jsBundleFile, "--assets-dest", resourcesDir, *extraArgs) - } - - enabled config."bundleIn${targetName}" || - config."bundleIn${buildTypeName.capitalize()}" ?: - targetName.toLowerCase().contains("release") + description = "copy bundled resources into custom location for ${targetName}." + + from resourcesDir + into file(resourcesDirConfigValue) + + dependsOn(currentBundleTask) + + enabled currentBundleTask.enabled } - // Hook bundle${productFlavor}${buildType}JsAndAssets into the android build process - currentBundleTask.dependsOn("merge${targetName}Resources") - currentBundleTask.dependsOn("merge${targetName}Assets") + variant.packageApplication.dependsOn(currentCopyResTask) + } + + def currentAssetsCopyTask = tasks.create( + name: "copy${targetName}BundledJs", + type: Copy) { + group = "react" + description = "copy bundled JS into ${targetName}." - runBefore("process${flavorNameCapitalized}Armeabi-v7a${buildNameCapitalized}Resources", currentBundleTask) - runBefore("process${flavorNameCapitalized}X86${buildNameCapitalized}Resources", currentBundleTask) - runBefore("processUniversal${targetName}Resources", currentBundleTask) - runBefore("process${targetName}Resources", currentBundleTask) - runBefore("dataBindingProcessLayouts${targetName}", currentBundleTask) + 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) } } From 0d43751cabad7270d5f773005b3b20d17e078b62 Mon Sep 17 00:00:00 2001 From: Kevin Cassidy Jr Date: Wed, 25 Jul 2018 22:23:02 -0700 Subject: [PATCH 2/2] Add basic shims for Android plugin 2.3.3 --- react.gradle | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/react.gradle b/react.gradle index bf04c70f7fb189..d71b5c14d37f0a 100644 --- a/react.gradle +++ b/react.gradle @@ -79,9 +79,19 @@ afterEvaluate { currentBundleTask.ext.generatedResFolders = files(resourcesDir).builtBy(currentBundleTask) currentBundleTask.ext.generatedAssetsFolders = files(jsBundleDir).builtBy(currentBundleTask) - variant.registerGeneratedResFolders(currentBundleTask.generatedResFolders) + // registerGeneratedResFolders for Android plugin 3.x + if (variant.respondsTo("registerGeneratedResFolders")) { + variant.registerGeneratedResFolders(currentBundleTask.generatedResFolders) + } else { + variant.registerResGeneratingTask(currentBundleTask) + } variant.mergeResources.dependsOn(currentBundleTask) + // packageApplication for Android plugin 3.x + def packageTask = variant.hasProperty("packageApplication") + ? variant.packageApplication + : tasks.findByName("package${targetName}") + def resourcesDirConfigValue = config."resourcesDir${targetName}" if (resourcesDirConfigValue) { def currentCopyResTask = tasks.create( @@ -98,7 +108,7 @@ afterEvaluate { enabled currentBundleTask.enabled } - variant.packageApplication.dependsOn(currentCopyResTask) + packageTask.dependsOn(currentCopyResTask) } def currentAssetsCopyTask = tasks.create( @@ -117,6 +127,6 @@ afterEvaluate { enabled currentBundleTask.enabled } - variant.packageApplication.dependsOn(currentAssetsCopyTask) + packageTask.dependsOn(currentAssetsCopyTask) } }