From c6d7af60fa17a12ad0e84f82d87399bc0a7afe6e Mon Sep 17 00:00:00 2001 From: Andrei Shikov Date: Mon, 22 Feb 2021 08:13:28 -0800 Subject: [PATCH] Use lazy configuration APIs in the react app plugin Summary: Changelog: [Internal] - Use lazy task APIs in the Gradle new plugin Gradle now migrates to [lazy task APIs](https://docs.gradle.org/current/userguide/lazy_configuration.html) to help with project configuration time. It helps even in the rn-tester case, e.g. `./gradlew help` executes in 2-3s instead of 20s. The migration is quite simple - use `Provider` and `tasks.register` instead of `task.create` everywhere. Reviewed By: mdvacca Differential Revision: D25946748 fbshipit-source-id: 2ccd2f881afe7601e506dc7adcc8a658c7267328 --- .../com/facebook/react/TaskConfiguration.kt | 131 +++++++++--------- .../react/tasks/BundleJsAndAssetsTask.kt | 26 ++-- .../facebook/react/tasks/HermesBinaryTask.kt | 16 +-- 3 files changed, 86 insertions(+), 87 deletions(-) diff --git a/packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/TaskConfiguration.kt b/packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/TaskConfiguration.kt index f929168d5d3..82f8eb084a7 100644 --- a/packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/TaskConfiguration.kt +++ b/packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/TaskConfiguration.kt @@ -10,13 +10,12 @@ package com.facebook.react import com.android.build.gradle.api.ApplicationVariant import com.android.build.gradle.api.BaseVariant import com.android.build.gradle.api.LibraryVariant +import com.android.build.gradle.internal.tasks.factory.dependsOn import com.facebook.react.tasks.BundleJsAndAssetsTask import com.facebook.react.tasks.HermesBinaryTask -import org.gradle.api.Action import org.gradle.api.Project -import org.gradle.api.Task import org.gradle.api.tasks.Copy -import org.gradle.kotlin.dsl.create +import org.gradle.kotlin.dsl.extra import org.gradle.kotlin.dsl.register import java.io.File @@ -47,10 +46,10 @@ internal fun Project.configureReactTasks(variant: BaseVariant, config: ReactAppE val enableHermes = config.enableHermesForVariant(variant) val bundleEnabled = variant.checkBundleEnabled(config) - val bundleTask = tasks.register("bundle${targetName}JsAndAssets") { + val bundleTask = tasks.register("createBundle${targetName}JsAndAssets") { val task = this task.group = REACT_GROUP - task.description = "bundle JS and assets for $targetName." + task.description = "create JS bundle and assets for $targetName." task.reactRoot = config.reactRoot task.sources = fileTree(config.reactRoot) { @@ -85,7 +84,7 @@ internal fun Project.configureReactTasks(variant: BaseVariant, config: ReactAppE task.jsSourceMapsDir = jsSourceMapsDir task.jsSourceMapsFile = if (enableHermes) jsPackagerSourceMapFile else jsOutputSourceMapFile - enabled = bundleEnabled + task.enabled = bundleEnabled } val hermesTask = tasks.register("emit${targetName}HermesResources") { @@ -104,28 +103,39 @@ internal fun Project.configureReactTasks(variant: BaseVariant, config: ReactAppE task.dependsOn(bundleTask) - enabled = bundleEnabled && enableHermes + task.enabled = bundleEnabled && enableHermes } - // todo expose bundle task and its generated folders - val generatedResFolders = files(resourcesDir).builtBy(hermesTask, bundleTask) - //val generatedAssetsFolders = files(jsBundleDir).builtBy(hermesTask, bundleTask) + val aggregatedBundleTask = tasks.register("bundle${targetName}JsAndAssets") { + val task = this + task.group = REACT_GROUP + task.description = "bundle JS and resources for $targetName" + task.dependsOn(bundleTask, hermesTask) + + // this was exposed before, do we still need it? + task.extra["generatedResFolders"] = files(resourcesDir).builtBy(task) + task.extra["generatedAssetsFolders"] = files(jsBundleDir).builtBy(task) + } + + val generatedResFolders = files(resourcesDir).builtBy(aggregatedBundleTask) + + // Android configuration variant.registerGeneratedResFolders(generatedResFolders) - variant.mergeResourcesProvider.get().dependsOn(bundleTask, hermesTask) val packageTask = when (variant) { - is ApplicationVariant -> variant.packageApplicationProvider.get() - is LibraryVariant -> variant.packageLibraryProvider.get() - else -> tasks.findByName("package$targetName") ?: error("Couldn't find a package task for $targetName") + is ApplicationVariant -> variant.packageApplicationProvider + is LibraryVariant -> variant.packageLibraryProvider + else -> tasks.named("package$targetName") } - // pre bundle build task for Android plugin 3.2+ - val buildPreBundleTask = tasks.findByName("build${targetName}PreBundle") + val mergeResourcesTask = variant.mergeResourcesProvider + val mergeAssetsTask = variant.mergeAssetsProvider + val preBundleTask = tasks.named("build${targetName}PreBundle") val resourcesDirConfigValue = config.resourcesDir[variant.name] if (resourcesDirConfigValue != null) { - val currentCopyResTask = tasks.create("copy${targetName}BundledResources") { + val currentCopyResTask = tasks.register("copy${targetName}BundledResources") { group = "react" description = "copy bundled resources into custom location for $targetName." @@ -138,48 +148,43 @@ internal fun Project.configureReactTasks(variant: BaseVariant, config: ReactAppE } packageTask.dependsOn(currentCopyResTask) - buildPreBundleTask?.dependsOn(currentCopyResTask) + preBundleTask.dependsOn(currentCopyResTask) } - val currentAssetsCopyTask = tasks.create("copy${targetName}BundledJs") { + packageTask.configure { + if (config.enableVmCleanup) { + doFirst { + cleanupVMFiles(enableHermes, isRelease, targetPath) + } + } + } + + val currentAssetsCopyTask = tasks.register("copy${targetName}BundledJs") { group = "react" description = "copy bundled JS into $targetName." + from(jsBundleDir) + val jsBundleDirConfigValue = config.jsBundleDir[targetName] if (jsBundleDirConfigValue != null) { - from(jsBundleDir) into(jsBundleDirConfigValue) } else { - into("$buildDir/intermediates") - into("assets/$targetPath") { - from(jsBundleDir) - } - - // Workaround for Android Gradle Plugin 3.2+ new asset directory - into("merged_assets/${variant.name}/merge${targetName}Assets/out") { - from(jsBundleDir) - } - - // Workaround for Android Gradle Plugin 3.4+ new asset directory - into("merged_assets/${variant.name}/out") { - from(jsBundleDir) - } + into(mergeAssetsTask.map { it.outputDir.get() }) } - // mergeAssets must run first, as it clears the intermediates directory - dependsOn(variant.mergeAssetsProvider.get()) + dependsOn(mergeAssetsTask) enabled = bundleEnabled } // mergeResources task runs before the bundle file is copied to the intermediate asset directory from Android plugin 4.1+. // This ensures to copy the bundle file before mergeResources task starts - val mergeResourcesTask = tasks.findByName("merge${targetName}Resources") - mergeResourcesTask?.dependsOn(currentAssetsCopyTask) - + mergeResourcesTask.dependsOn(currentAssetsCopyTask) packageTask.dependsOn(currentAssetsCopyTask) - buildPreBundleTask?.dependsOn(currentAssetsCopyTask) + preBundleTask.dependsOn(currentAssetsCopyTask) +} +private fun Project.cleanupVMFiles(enableHermes: Boolean, isRelease: Boolean, targetPath: String) { // Delete the VM related libraries that this build doesn't need. // The application can manage this manually by setting 'enableVmCleanup: false' // @@ -187,36 +192,30 @@ internal fun Project.configureReactTasks(variant: BaseVariant, config: ReactAppE // two separate HermesDebug and HermesRelease AARs, but until then we'll // kludge it by deleting the .so files out of the /transforms/ directory. val libDir = "$buildDir/intermediates/transforms/" - val vmSelectionAction = Action { - fileTree(libDir) { - if (enableHermes) { - // For Hermes, delete all the libjsc* files - include("**/libjsc*.so") + fileTree(libDir) { + if (enableHermes) { + // For Hermes, delete all the libjsc* files + include("**/libjsc*.so") - if (isRelease) { - // Reduce size by deleting the debugger/inspector - include("**/libhermes-inspector.so") - include("**/libhermes-executor-debug.so") - } else { - // Release libs take precedence and must be removed - // to allow debugging - include("**/libhermes-executor-release.so") - } + if (isRelease) { + // Reduce size by deleting the debugger/inspector + include("**/libhermes-inspector.so") + include("**/libhermes-executor-debug.so") } else { - // For JSC, delete all the libhermes* files - include("**/libhermes*.so") - } - }.visit { - val targetVariant = ".*/transforms/[^/]*/$targetPath/.*".toRegex() - val path = file.absolutePath.replace(File.separatorChar, '/') - if (path.matches(targetVariant) && file.isFile()) { - file.delete() + // Release libs take precedence and must be removed + // to allow debugging + include("**/libhermes-executor-release.so") } + } else { + // For JSC, delete all the libhermes* files + include("**/libhermes*.so") + } + }.visit { + val targetVariant = ".*/transforms/[^/]*/$targetPath/.*".toRegex() + val path = file.absolutePath.replace(File.separatorChar, '/') + if (path.matches(targetVariant) && file.isFile()) { + file.delete() } - } - - if (config.enableVmCleanup) { - packageTask.doFirst(vmSelectionAction) } } diff --git a/packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/tasks/BundleJsAndAssetsTask.kt b/packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/tasks/BundleJsAndAssetsTask.kt index b793469dce9..30e8e6fb908 100644 --- a/packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/tasks/BundleJsAndAssetsTask.kt +++ b/packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/tasks/BundleJsAndAssetsTask.kt @@ -17,34 +17,34 @@ import org.gradle.api.tasks.TaskAction import java.io.File open class BundleJsAndAssetsTask : DefaultTask() { - lateinit var reactRoot: File + internal lateinit var reactRoot: File @get:InputFiles @Suppress("UNUSED") // used to invalidate caches - lateinit var sources: FileTree + internal lateinit var sources: FileTree @get:Input - lateinit var execCommand: List + internal lateinit var execCommand: List @get:Input - lateinit var bundleCommand: String + internal lateinit var bundleCommand: String @get:Input - var devEnabled: Boolean = true + internal var devEnabled: Boolean = true @get:Input - lateinit var entryFile: File + internal lateinit var entryFile: File @get:Input - var extraArgs: List = emptyList() + internal var extraArgs: List = emptyList() @get:OutputDirectory - lateinit var jsBundleDir: File + internal lateinit var jsBundleDir: File @get:OutputFile - lateinit var jsBundleFile: File + internal lateinit var jsBundleFile: File @get:OutputDirectory - lateinit var resourcesDir: File + internal lateinit var resourcesDir: File @get:OutputDirectory - lateinit var jsIntermediateSourceMapsDir: File + internal lateinit var jsIntermediateSourceMapsDir: File @get:OutputDirectory - lateinit var jsSourceMapsDir: File + internal lateinit var jsSourceMapsDir: File @get:OutputFile - lateinit var jsSourceMapsFile: File + internal lateinit var jsSourceMapsFile: File @TaskAction fun run() { diff --git a/packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/tasks/HermesBinaryTask.kt b/packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/tasks/HermesBinaryTask.kt index eb05b60b667..8f0db469e95 100644 --- a/packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/tasks/HermesBinaryTask.kt +++ b/packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/tasks/HermesBinaryTask.kt @@ -15,24 +15,24 @@ import org.gradle.api.tasks.TaskAction import java.io.File open class HermesBinaryTask : DefaultTask() { - lateinit var reactRoot: File + internal lateinit var reactRoot: File @get:Input - lateinit var hermesCommand: String + internal lateinit var hermesCommand: String @get:Input - var hermesFlags: List = emptyList() + internal var hermesFlags: List = emptyList() @get:InputFile - lateinit var jsBundleFile: File + internal lateinit var jsBundleFile: File @get:Input - lateinit var composeSourceMapsCommand: List + internal lateinit var composeSourceMapsCommand: List @get:Input - lateinit var jsPackagerSourceMapFile: File + internal lateinit var jsPackagerSourceMapFile: File @get:OutputFile - lateinit var jsCompilerSourceMapFile: File + internal lateinit var jsCompilerSourceMapFile: File @get:OutputFile - lateinit var jsOutputSourceMapFile: File + internal lateinit var jsOutputSourceMapFile: File @TaskAction fun run() {