From 8ad86c70b6341f2e8bd40f5ba86f1a0d451008b0 Mon Sep 17 00:00:00 2001 From: Nicola Corti Date: Mon, 24 Oct 2022 07:00:36 -0700 Subject: [PATCH] RNGP - Add Variant Support (#35063) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/35063 This is part of a series of tasks to make the React Native Gradle Plugin (RNGP) variant-aware. Here I'm add Variant support to RNGP via the Variant API from AGP 7.x A short summary of changes: - I've pushed a number of breaking changes to ReactExtension (we should document them in the release notes). Specifically I've removed properties which I believe were unnecessary and confusing - I've removed all the extra logic to do the .so cleanups and use the new tasks that use the Artifacts API - I've introduced only a `debuggableVariants` to make all the decisions for the bundling and minification which should be sufficient for users - I've removed all the funcional interfaces are replaced them with lists as they're easy to handle and understand for users. Changelog: [Android] [Changed] - Added Flavor Support to React Native Gradle Plugin (RNGP) Reviewed By: cipolleschi Differential Revision: D40335028 fbshipit-source-id: d9ac1437de8a27db2e93df15b13772b221e036b2 --- .../com/facebook/react/ReactExtension.kt | 105 ++----- .../kotlin/com/facebook/react/ReactPlugin.kt | 7 +- .../com/facebook/react/TaskConfiguration.kt | 293 +++++------------- .../react/tasks/BundleJsAndAssetsTask.kt | 73 ----- .../facebook/react/tasks/HermesBinaryTask.kt | 77 ----- packages/rn-tester/android/app/build.gradle | 7 +- 6 files changed, 96 insertions(+), 466 deletions(-) delete mode 100644 packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/tasks/BundleJsAndAssetsTask.kt delete mode 100644 packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/tasks/HermesBinaryTask.kt diff --git a/packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/ReactExtension.kt b/packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/ReactExtension.kt index a2bfff06b0d656..4e7573876540cf 100644 --- a/packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/ReactExtension.kt +++ b/packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/ReactExtension.kt @@ -7,15 +7,12 @@ package com.facebook.react -import com.android.build.gradle.api.BaseVariant import com.facebook.react.utils.projectPathToLibraryName -import java.io.File import javax.inject.Inject import org.gradle.api.Project import org.gradle.api.file.DirectoryProperty import org.gradle.api.file.RegularFileProperty import org.gradle.api.provider.ListProperty -import org.gradle.api.provider.MapProperty import org.gradle.api.provider.Property abstract class ReactExtension @Inject constructor(project: Project) { @@ -54,10 +51,10 @@ abstract class ReactExtension @Inject constructor(project: Project) { val bundleCommand: Property = objects.property(String::class.java).convention("bundle") /** - * Custom configuration for the [bundleCommand]. If provided it will be passed over with a + * Custom configuration file for the [bundleCommand]. If provided, it will be passed over with a * `--config` flag to the bundle command. */ - val bundleConfig: Property = objects.property(String::class.java) + val bundleConfig: RegularFileProperty = objects.fileProperty() /** * The Bundle Asset name. This name will be used also for deriving other bundle outputs such as @@ -69,69 +66,24 @@ abstract class ReactExtension @Inject constructor(project: Project) { objects.property(String::class.java).convention("index.android.bundle") /** - * Variant Name to File destination map that allows to specify where is the resource dir for a - * specific variant. If a value is supplied, the plugin will copy the bundled resource for that - * variant from `generated/res/react/` into the custom specified location. Default: {} + * Toggles the .so Cleanup step. If enabled, we will clean up all the unnecessary files before the + * bundle task. If disabled, the developers will have to manually cleanup the files. Default: true */ - val resourcesDir: MapProperty = - objects.mapProperty(String::class.java, File::class.java).convention(emptyMap()) - - /** - * Variant Name to File destination map that allows to specify where is the asset dir for a - * specific variant. If a value is supplied, the plugin will copy the bundled JS for that variant - * from `generated/assets/react/` into the custom specified location. Default: {} - */ - val jsBundleDir: MapProperty = - objects.mapProperty(String::class.java, File::class.java).convention(emptyMap()) - - /** ANT-style excludes for the bundle command. Default: ["android / **", "ios / **"] */ - val inputExcludes: ListProperty = - objects.listProperty(String::class.java).convention(listOf("android/**", "ios/**")) - - /** - * Toggles the VM Cleanup step. If enabled, before the bundle task we will clean up all the - * unnecessary files. If disabled, the developers will have to manually cleanup the files. - * Default: true - */ - val enableVmCleanup: Property = objects.property(Boolean::class.java).convention(true) + val enableSoCleanup: Property = objects.property(Boolean::class.java).convention(true) /** Extra args that will be passed to the [bundleCommand] Default: [] */ val extraPackagerArgs: ListProperty = objects.listProperty(String::class.java).convention(emptyList()) /** - * Allows to disable dev mode for certain variants. That's useful if you have a production variant - * (say `canary`) where you don't want dev mode to be enabled. Default: [] - */ - val devDisabledInVariants: ListProperty = - objects.listProperty(String::class.java).convention(emptyList()) - - /** - * Functional interface to disable dev mode only on specific [BaseVariant] Default: will check - * [devDisabledInVariants] or return True for Release variants and False for Debug variants. - */ - var disableDevForVariant: (BaseVariant) -> Boolean = { variant -> - variant.name in devDisabledInVariants.get() || variant.isRelease - } - - /** - * Variant Name to Boolean map that allows to toggle the bundle command for a specific variant. - * Default: {} - */ - // todo maybe lambda as for hermes? - val bundleIn: MapProperty = - objects.mapProperty(String::class.java, Boolean::class.java).convention(emptyMap()) - - /** - * Functional interface to toggle the bundle command only on specific [BaseVariant] Default: will - * check [bundleIn] or return True for Release variants and False for Debug variants. + * Allows to specify the debuggable variants (by default just 'debug'). Variants in this list + * will: + * - Not be bundled (the bundle file will not be created and won't be copied over). + * - Have the Hermes Debug flags set. That's useful if you have another variant (say `canary`) + * where you want dev mode to be enabled. Default: ['debug'] */ - var bundleForVariant: (BaseVariant) -> Boolean = { variant -> - if (bundleIn.getting(variant.name).isPresent) bundleIn.getting(variant.name).get() - else if (bundleIn.getting(variant.buildType.name).isPresent) - bundleIn.getting(variant.buildType.name).get() - else variant.isRelease - } + val debuggableVariants: ListProperty = + objects.listProperty(String::class.java).convention(listOf("debug")) /** Hermes Config */ @@ -141,35 +93,18 @@ abstract class ReactExtension @Inject constructor(project: Project) { */ val hermesCommand: Property = objects.property(String::class.java).convention("") - /** Toggle Hermes for the whole build. Default: false */ - val enableHermes: Property = objects.property(Boolean::class.java).convention(false) - /** - * Functional interface to selectively enabled Hermes only on specific [BaseVariant] Default: will - * return [enableHermes] for all the variants. - */ - var enableHermesForVariant: (BaseVariant) -> Boolean = { enableHermes.get() } - - /** - * Functional interface specify flags for Hermes on specific [BaseVariant] Default: will return - * [hermesFlagsRelease] for Release variants and [hermesFlagsDebug] for Debug variants. - */ - var hermesFlagsForVariant: (BaseVariant) -> List = { variant -> - if (variant.isRelease) hermesFlagsRelease.get() else hermesFlagsDebug.get() - } - - /** - * Functional interface to delete debug files only on specific [BaseVariant] Default: will return - * True for Release variants and False for Debug variants. + * Whether to enable Hermes only on certain variants. If specified as a non-empty list, hermesc + * and the .so cleanup for Hermes will be executed only for variants in this list. An empty list + * assumes you're either using Hermes for all variants or not (see [enableHermes]). + * + * Default: [] */ - var deleteDebugFilesForVariant: (BaseVariant) -> Boolean = { variant -> variant.isRelease } - - /** Flags to pass to Hermes for Debug variants. Default: [] */ - val hermesFlagsDebug: ListProperty = + val enableHermesOnlyInVariants: ListProperty = objects.listProperty(String::class.java).convention(emptyList()) - /** Flags to pass to Hermes for Release variants. Default: ["-O", "-output-source-map"] */ - val hermesFlagsRelease: ListProperty = + /** Flags to pass to Hermesc. Default: ["-O", "-output-source-map"] */ + val hermesFlags: ListProperty = objects.listProperty(String::class.java).convention(listOf("-O", "-output-source-map")) /** diff --git a/packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/ReactPlugin.kt b/packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/ReactPlugin.kt index c40f1491269ca7..24790daa83c565 100644 --- a/packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/ReactPlugin.kt +++ b/packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/ReactPlugin.kt @@ -8,7 +8,6 @@ package com.facebook.react import com.android.build.api.variant.AndroidComponentsExtension -import com.android.build.gradle.AppExtension import com.android.build.gradle.internal.tasks.factory.dependsOn import com.facebook.react.tasks.BuildCodegenCLITask import com.facebook.react.tasks.GenerateCodegenArtifactsTask @@ -47,10 +46,8 @@ class ReactPlugin : Plugin { configureBuildConfigFields(project) configureDevPorts(project) - project.afterEvaluate { - project.extensions.getByType(AppExtension::class.java).applicationVariants.all { - project.configureReactTasks(variant = it, config = extension) - } + project.extensions.getByType(AndroidComponentsExtension::class.java).onVariants { variant -> + project.configureReactTasks(variant = variant, config = extension) } configureCodegen(project, extension, isLibrary = false) } 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 bba9e91f959c11..4ec27e9f559d94 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 @@ -7,246 +7,95 @@ 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 com.android.build.api.artifact.SingleArtifact +import com.android.build.api.variant.Variant +import com.facebook.react.tasks.BundleHermesCTask +import com.facebook.react.tasks.NativeLibraryAabCleanupTask +import com.facebook.react.tasks.NativeLibraryApkCleanupTask +import com.facebook.react.utils.ProjectUtils.isHermesEnabled import com.facebook.react.utils.detectedCliPath import com.facebook.react.utils.detectedEntryFile import java.io.File import org.gradle.api.Project -import org.gradle.api.Task -import org.gradle.api.tasks.Copy -import org.gradle.api.tasks.TaskProvider -private const val REACT_GROUP = "react" - -@Suppress("SpreadOperator") -internal fun Project.configureReactTasks(variant: BaseVariant, config: ReactExtension) { +@Suppress("SpreadOperator", "UnstableApiUsage") +internal fun Project.configureReactTasks(variant: Variant, config: ReactExtension) { val targetName = variant.name.replaceFirstChar { it.uppercase() } - val targetPath = variant.dirName + val targetPath = variant.name // React js bundle directories - val jsBundleDir = File(buildDir, "generated/assets/react/$targetPath") val resourcesDir = File(buildDir, "generated/res/react/$targetPath") - - val bundleAssetName = config.bundleAssetName.get() - val jsBundleFile = File(jsBundleDir, bundleAssetName) + // Bundle: generated/assets/react/path/index.android.bundle + val jsBundleDir = File(buildDir, "generated/assets/react/$targetPath") + // Sourcemap: generated/sourcemaps/react/path/index.android.bundle.map val jsSourceMapsDir = File(buildDir, "generated/sourcemaps/react/$targetPath") + // Intermediate packager: intermediates/sourcemaps/react/path/index.android.bundle.packager.map + // Intermediate compiler: intermediates/sourcemaps/react/path/index.android.bundle.compiler.map val jsIntermediateSourceMapsDir = File(buildDir, "intermediates/sourcemaps/react/$targetPath") - val jsPackagerSourceMapFile = File(jsIntermediateSourceMapsDir, "${bundleAssetName}.packager.map") - val jsCompilerSourceMapFile = File(jsIntermediateSourceMapsDir, "${bundleAssetName}.compiler.map") - val jsOutputSourceMapFile = File(jsSourceMapsDir, "${bundleAssetName}.map") // Additional node and packager commandline arguments - val nodeExecutableAndArgs = config.nodeExecutableAndArgs.get() val cliPath = detectedCliPath(project.projectDir, config) - val execCommand = nodeExecutableAndArgs + cliPath - val enableHermes = config.enableHermesForVariant(variant) - val cleanup = config.deleteDebugFilesForVariant(variant) - val bundleEnabled = config.bundleForVariant(variant) - - val bundleTask = - tasks.register("createBundle${targetName}JsAndAssets", BundleJsAndAssetsTask::class.java) { - it.group = REACT_GROUP - it.description = "create JS bundle and assets for $targetName." - - it.reactRoot = config.root.get().asFile - it.sources = - fileTree(config.root) { fileTree -> fileTree.setExcludes(config.inputExcludes.get()) } - it.execCommand = execCommand - it.bundleCommand = config.bundleCommand.get() - it.devEnabled = !config.disableDevForVariant(variant) - it.entryFile = detectedEntryFile(config) - - val extraArgs = mutableListOf() - - if (config.bundleConfig.isPresent) { - extraArgs.add("--config") - extraArgs.add(config.bundleConfig.get()) - } - - // Hermes doesn't require JS minification. - if (enableHermes && !it.devEnabled) { - extraArgs.add("--minify") - extraArgs.add("false") - } - - extraArgs.addAll(config.extraPackagerArgs.get()) - - it.extraArgs = extraArgs - - it.jsBundleDir = jsBundleDir - it.jsBundleFile = jsBundleFile - it.resourcesDir = resourcesDir - it.jsIntermediateSourceMapsDir = jsIntermediateSourceMapsDir - it.jsSourceMapsDir = jsSourceMapsDir - it.jsSourceMapsFile = if (enableHermes) jsPackagerSourceMapFile else jsOutputSourceMapFile - - it.enabled = bundleEnabled - } - - val hermesTask = - tasks.register("emit${targetName}HermesResources", HermesBinaryTask::class.java) { - it.group = REACT_GROUP - it.description = "bundle hermes resources for $targetName" - - it.root = config.root.get().asFile - it.hermesCommand = config.hermesCommand.get() - it.hermesFlags = config.hermesFlagsForVariant(variant) - it.jsBundleFile = jsBundleFile - it.composeSourceMapsCommand = nodeExecutableAndArgs + config.composeSourceMapsPath.get() - it.jsPackagerSourceMapFile = jsPackagerSourceMapFile - it.jsCompilerSourceMapFile = jsCompilerSourceMapFile - it.jsOutputSourceMapFile = jsOutputSourceMapFile - - it.dependsOn(bundleTask) - - it.enabled = bundleEnabled && enableHermes - } - - val aggregatedBundleTask = - tasks.register("bundle${targetName}JsAndAssets") { - it.group = REACT_GROUP - it.description = "bundle JS and resources for $targetName" - - it.dependsOn(bundleTask, hermesTask) - - // this was exposed before, do we still need it? - it.extensions.extraProperties["generatedResFolders"] = files(resourcesDir).builtBy(it) - it.extensions.extraProperties["generatedAssetsFolders"] = files(jsBundleDir).builtBy(it) - } - - val generatedResFolders = files(resourcesDir).builtBy(aggregatedBundleTask) - - // Android configuration - variant.registerGeneratedResFolders(generatedResFolders) - - val packageTask: TaskProvider? = - when (variant) { - is ApplicationVariant -> variant.packageApplicationProvider - is LibraryVariant -> variant.packageLibraryProvider - else -> tasks.named("package$targetName") + val enableHermesInProject = project.isHermesEnabled + val enableHermesInThisVariant = + if (config.enableHermesOnlyInVariants.get().isNotEmpty()) { + config.enableHermesOnlyInVariants.get().contains(variant.name) && enableHermesInProject + } else { + enableHermesInProject } - val stripDebugSymbolsTask: TaskProvider? = tasks.named("strip${targetName}DebugSymbols") - val mergeNativeLibsTask: TaskProvider? = tasks.named("merge${targetName}NativeLibs") - - val mergeResourcesTask = variant.mergeResourcesProvider - val mergeAssetsTask = variant.mergeAssetsProvider - val preBundleTask = tasks.named("build${targetName}PreBundle") - - val resourcesDirConfigValue = config.resourcesDir.getting(variant.name) - if (resourcesDirConfigValue.isPresent) { - val currentCopyResTask = - tasks.register("copy${targetName}BundledResources", Copy::class.java) { - it.group = "react" - it.description = "copy bundled resources into custom location for $targetName." - - it.from(resourcesDir) - it.into(file(resourcesDirConfigValue.get())) - - it.dependsOn(bundleTask) - - it.enabled = bundleEnabled + val isDebuggableVariant = + config.debuggableVariants.get().any { it.equals(variant.name, ignoreCase = true) } + + if (!isDebuggableVariant) { + val bundleTask = + tasks.register("createBundle${targetName}JsAndAssets", BundleHermesCTask::class.java) { + it.root.set(config.root) + it.nodeExecutableAndArgs.set(config.nodeExecutableAndArgs) + it.cliPath.set(cliPath) + it.bundleCommand.set(config.bundleCommand) + it.entryFile.set(detectedEntryFile(config)) + it.extraPackagerArgs.set(config.extraPackagerArgs) + it.bundleConfig.set(config.bundleConfig) + it.bundleAssetName.set(config.bundleAssetName) + it.jsBundleDir.set(jsBundleDir) + it.resourcesDir.set(resourcesDir) + it.hermesEnabled.set(enableHermesInThisVariant) + it.minifyEnabled.set(!enableHermesInThisVariant) + it.devEnabled.set(false) + it.jsIntermediateSourceMapsDir.set(jsIntermediateSourceMapsDir) + it.jsSourceMapsDir.set(jsSourceMapsDir) + it.hermesCommand.set(config.hermesCommand) + it.hermesFlags.set(config.hermesFlags) + it.composeSourceMapsPath.set(config.composeSourceMapsPath) } - - packageTask?.dependsOn(currentCopyResTask) - preBundleTask.dependsOn(currentCopyResTask) + variant.sources.res?.addGeneratedSourceDirectory(bundleTask, BundleHermesCTask::resourcesDir) + variant.sources.assets?.addGeneratedSourceDirectory(bundleTask, BundleHermesCTask::jsBundleDir) } - packageTask?.configure { - if (config.enableVmCleanup.get()) { - val libDir = "$buildDir/intermediates/transforms/" - val targetVariant = ".*/transforms/[^/]*/${variant.name}/.*".toRegex() - it.doFirst { cleanupVMFiles(libDir, targetVariant, enableHermes, cleanup) } - } + if (config.enableSoCleanup.get()) { + val nativeLibraryApkCleanupTask = + project.tasks.register( + "nativeLibrary${targetName}ApkCleanup", NativeLibraryApkCleanupTask::class.java) { + it.debuggableVariant.set(isDebuggableVariant) + it.enableHermes.set(enableHermesInThisVariant) + } + val nativeLibraryBundleCleanupTask = + project.tasks.register( + "nativeLibrary${targetName}BundleCleanup", NativeLibraryAabCleanupTask::class.java) { + it.debuggableVariant.set(isDebuggableVariant) + it.enableHermes.set(enableHermesInThisVariant) + } + + variant.artifacts + .use(nativeLibraryApkCleanupTask) + .wiredWithDirectories( + NativeLibraryApkCleanupTask::inputApkDirectory, + NativeLibraryApkCleanupTask::outputApkDirectory) + .toTransform(SingleArtifact.APK) + variant.artifacts + .use(nativeLibraryBundleCleanupTask) + .wiredWithFiles( + NativeLibraryAabCleanupTask::inputBundle, NativeLibraryAabCleanupTask::outputBundle) + .toTransform(SingleArtifact.BUNDLE) } - - stripDebugSymbolsTask?.configure { - if (config.enableVmCleanup.get()) { - val libDir = "$buildDir/intermediates/stripped_native_libs/${variant.name}/out/lib/" - val targetVariant = ".*/stripped_native_libs/${variant.name}/out/lib/.*".toRegex() - it.doLast { cleanupVMFiles(libDir, targetVariant, enableHermes, cleanup) } - } - } - - mergeNativeLibsTask?.configure { - if (config.enableVmCleanup.get()) { - val libDir = "$buildDir/intermediates/merged_native_libs/${variant.name}/out/lib/" - val targetVariant = ".*/merged_native_libs/${variant.name}/out/lib/.*".toRegex() - it.doLast { cleanupVMFiles(libDir, targetVariant, enableHermes, cleanup) } - } - } - - val currentAssetsCopyTask = - tasks.register("copy${targetName}BundledJs", Copy::class.java) { - it.group = "react" - it.description = "copy bundled JS into $targetName." - - it.from(jsBundleDir) - - val jsBundleDirConfigValue = config.jsBundleDir.getting(targetName) - if (jsBundleDirConfigValue.isPresent) { - it.into(jsBundleDirConfigValue.get()) - } else { - it.into(mergeAssetsTask.map { mergeFoldersTask -> mergeFoldersTask.outputDir.get() }) - // Workaround for Android Gradle Plugin 7.3 asset directory - it.into("$buildDir/intermediates/assets/${variant.name}") - } - - it.dependsOn(mergeAssetsTask) - - it.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 - mergeResourcesTask.dependsOn(currentAssetsCopyTask) - packageTask?.dependsOn(currentAssetsCopyTask) - preBundleTask.dependsOn(currentAssetsCopyTask) } - -private fun Project.cleanupVMFiles( - libDir: String, - targetVariant: Regex, - enableHermes: Boolean, - cleanup: Boolean -) { - // Delete the VM related libraries that this build doesn't need. - // The application can manage this manually by setting 'enableVmCleanup: false' - // - // This should really be done by packaging all Hermes related libs into - // two separate HermesDebug and HermesRelease AARs, but until then we'll - // kludge it by deleting the .so files out of the /transforms/ directory. - fileTree(libDir) { - if (enableHermes) { - // For Hermes, delete all the libjsc* files - it.include("**/libjsc*.so") - - if (cleanup) { - // Reduce size by deleting the debugger/inspector - it.include("**/libhermes-executor-debug.so") - } else { - // Release libs take precedence and must be removed - // to allow debugging - it.include("**/libhermes-executor-release.so") - } - } else { - // For JSC, delete all the libhermes* files - it.include("**/libhermes*.so") - } - } - .visit { visit -> - val path = visit.file.absolutePath.replace(File.separatorChar, '/') - if (path.matches(targetVariant) && visit.file.isFile) { - visit.file.delete() - } - } -} - -internal val BaseVariant.isRelease: Boolean - get() = name.lowercase().contains("release") 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 deleted file mode 100644 index 2e1a0b8be81900..00000000000000 --- a/packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/tasks/BundleJsAndAssetsTask.kt +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -package com.facebook.react.tasks - -import com.facebook.react.utils.recreateDir -import com.facebook.react.utils.windowsAwareCommandLine -import java.io.File -import org.gradle.api.file.FileTree -import org.gradle.api.tasks.* - -abstract class BundleJsAndAssetsTask : Exec() { - - @get:Internal lateinit var reactRoot: File - - @get:InputFiles - @Suppress("UNUSED") // used to invalidate caches - lateinit var sources: FileTree - - @get:Input lateinit var execCommand: List - @get:Input lateinit var bundleCommand: String - @get:Input var devEnabled: Boolean = true - @get:InputFile lateinit var entryFile: File - @get:Input var extraArgs: List = emptyList() - - @get:OutputDirectory lateinit var jsBundleDir: File - @get:OutputFile lateinit var jsBundleFile: File - @get:OutputDirectory lateinit var resourcesDir: File - @get:OutputDirectory lateinit var jsIntermediateSourceMapsDir: File - @get:OutputDirectory lateinit var jsSourceMapsDir: File - @get:OutputFile lateinit var jsSourceMapsFile: File - - override fun exec() { - cleanOutputDirectories() - configureBundleCommand() - super.exec() - } - - private fun cleanOutputDirectories() { - jsBundleDir.recreateDir() - resourcesDir.recreateDir() - jsIntermediateSourceMapsDir.recreateDir() - jsSourceMapsDir.recreateDir() - } - - private fun configureBundleCommand() { - workingDir(reactRoot) - - @Suppress("SpreadOperator") - commandLine( - windowsAwareCommandLine( - *execCommand.toTypedArray(), - bundleCommand, - "--platform", - "android", - "--dev", - devEnabled, - "--reset-cache", - "--entry-file", - entryFile, - "--bundle-output", - jsBundleFile, - "--assets-dest", - resourcesDir, - "--sourcemap-output", - jsSourceMapsFile, - *extraArgs.toTypedArray())) - } -} 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 deleted file mode 100644 index 3f9e635973847e..00000000000000 --- a/packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/tasks/HermesBinaryTask.kt +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -package com.facebook.react.tasks - -import com.facebook.react.utils.detectOSAwareHermesCommand -import com.facebook.react.utils.moveTo -import com.facebook.react.utils.windowsAwareCommandLine -import java.io.File -import org.gradle.api.DefaultTask -import org.gradle.api.tasks.Input -import org.gradle.api.tasks.InputFile -import org.gradle.api.tasks.Internal -import org.gradle.api.tasks.OutputFile -import org.gradle.api.tasks.TaskAction - -open class HermesBinaryTask : DefaultTask() { - - @get:Internal internal lateinit var root: File - - @get:Input internal lateinit var hermesCommand: String - @get:Input internal var hermesFlags: List = emptyList() - @get:InputFile internal lateinit var jsBundleFile: File - - @get:Input internal lateinit var composeSourceMapsCommand: List - @get:InputFile internal lateinit var jsPackagerSourceMapFile: File - - @get:OutputFile internal lateinit var jsCompilerSourceMapFile: File - @get:OutputFile internal lateinit var jsOutputSourceMapFile: File - - @TaskAction - fun run() { - val detectedHermesCommand = detectOSAwareHermesCommand(root, hermesCommand) - val bytecodeTempFile = File("$jsBundleFile.hbc") - emitHermesBinary(hermesCommand = detectedHermesCommand, outputFile = bytecodeTempFile) - bytecodeTempFile.moveTo(jsBundleFile) - - if (hermesFlags.contains("-output-source-map")) { - val hermesTempSourceMapFile = File("$bytecodeTempFile.map") - hermesTempSourceMapFile.moveTo(jsCompilerSourceMapFile) - composeSourceMaps() - } - } - - private fun emitHermesBinary(hermesCommand: String, outputFile: File) { - project.exec { - @Suppress("SpreadOperator") - it.commandLine( - windowsAwareCommandLine( - hermesCommand, - "-emit-binary", - "-out", - outputFile, - jsBundleFile, - *hermesFlags.toTypedArray())) - } - } - - private fun composeSourceMaps() { - project.exec { - it.workingDir(root) - - @Suppress("SpreadOperator") - it.commandLine( - windowsAwareCommandLine( - *composeSourceMapsCommand.toTypedArray(), - jsPackagerSourceMapFile, - jsCompilerSourceMapFile, - "-o", - jsOutputSourceMapFile)) - } - } -} diff --git a/packages/rn-tester/android/app/build.gradle b/packages/rn-tester/android/app/build.gradle index a7f7e9100fe0be..e0fc0dcf655e8c 100644 --- a/packages/rn-tester/android/app/build.gradle +++ b/packages/rn-tester/android/app/build.gradle @@ -80,10 +80,10 @@ react { bundleAssetName = "RNTesterApp.android.bundle" entryFile = file("../../js/RNTesterApp.android.js") root = file("../../") - inputExcludes = ["android/**", "./**", ".gradle/**"] composeSourceMapsPath = "$rootDir/scripts/compose-source-maps.js" hermesCommand = "$rootDir/ReactAndroid/hermes-engine/build/hermes/bin/hermesc" - enableHermesForVariant { def v -> v.name.contains("hermes") } + debuggableVariants = ["hermesDebug", "jscDebug"] + enableHermesOnlyInVariants = ["hermesDebug", "hermesRelease"] // Codegen Configs reactNativeDir = rootDir @@ -228,6 +228,5 @@ android { afterEvaluate { // As we're consuming Hermes from source, we want to make sure // `hermesc` is built before we actually invoke the `emit*HermesResource` task - emitHermesDebugHermesResources.dependsOn(":ReactAndroid:hermes-engine:buildHermes") - emitHermesReleaseHermesResources.dependsOn(":ReactAndroid:hermes-engine:buildHermes") + createBundleHermesReleaseJsAndAssets.dependsOn(":ReactAndroid:hermes-engine:buildHermes") }