diff --git a/package.json b/package.json index 4592180c303c64..6b4c69443489ed 100644 --- a/package.json +++ b/package.json @@ -29,7 +29,6 @@ "local-cli", "React-Core.podspec", "react-native.config.js", - "react.gradle", "React.podspec", "React", "ReactAndroid", diff --git a/react.gradle b/react.gradle deleted file mode 100644 index 250299bb78359f..00000000000000 --- a/react.gradle +++ /dev/null @@ -1,486 +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. - */ - -import org.apache.tools.ant.taskdefs.condition.Os -import org.gradle.internal.jvm.Jvm -import org.gradle.internal.logging.text.StyledTextOutput -import org.gradle.internal.logging.text.StyledTextOutputFactory -import org.gradle.internal.logging.text.StyledTextOutput.Style - -def out = services.get(StyledTextOutputFactory).create("ouput") -out.style(Style.Info) - .text('##############################') - .text('\n\n') - .text('Using react.gradle in your project is deprecated! You should move to "apply plugin: com.facebook.react"') - .text('\n') - .text('react.gradle is going to be removed in a future React Native project and your project will not build anymore.') - .text('\n') - .text('You can use the template as a reference:') - .text('\n') - .text('https://github.com/facebook/react-native/blob/main/template/android/app/build.gradle') - .text('\n\n') - .text('##############################') - .println('') - -def config = project.hasProperty("react") ? project.react : [:]; - -def detectEntryFile(config) { - if (System.getenv('ENTRY_FILE')) { - return System.getenv('ENTRY_FILE') - } else if (config.entryFile) { - return config.entryFile - } else if ((new File("${projectDir}/../../index.android.js")).exists()) { - return "index.android.js" - } - - return "index.js"; -} - -def composeSourceMapsPath = config.composeSourceMapsPath ?: "node_modules/react-native/scripts/compose-source-maps.js" -def bundleAssetName = config.bundleAssetName ?: "index.android.bundle" -def entryFile = detectEntryFile(config) -def bundleCommand = config.bundleCommand ?: "bundle" -def reactRoot = file(config.root ?: "../../") -def inputExcludes = config.inputExcludes ?: ["android/**", "ios/**"] -def bundleConfig = config.bundleConfig ? "${reactRoot}/${config.bundleConfig}" : null ; -def enableVmCleanup = config.enableVmCleanup == null ? true : config.enableVmCleanup -def hermesCommand = config.hermesCommand - -/** - * Detects CLI location in a similar fashion to the React Native CLI - */ -def detectCliPath(config, reactRoot) { - // 1. preconfigured path - if (config.cliPath) { - def cliJsAbsolute = new File(config.cliPath) - if (cliJsAbsolute.exists()) { - return cliJsAbsolute.getAbsolutePath() - } - def cliJsRelativeToRoot = new File("${rootDir}/${config.cliPath}") - if (cliJsRelativeToRoot.exists()) { - return cliJsRelativeToRoot.getAbsolutePath() - } - def cliJsRelativeToProject = new File("${projectDir}/${config.cliPath}") - if (cliJsRelativeToProject.exists()) { - return cliJsRelativeToProject.getAbsolutePath() - } - } - - // 2. node module path - def cliJsFromNode = new File(["node", "--print", "require.resolve('react-native/cli')"].execute(null, rootDir).text.trim()) - if (cliJsFromNode.exists()) { - return cliJsFromNode.getAbsolutePath() - } - - // 3. cli.js in the root folder - def rootCliJs = new File(reactRoot, "node_modules/react-native/cli.js") - if (rootCliJs.exists()) { - return rootCliJs.getAbsolutePath() - } - - throw new Exception("Couldn't determine CLI location. " + - "Please set `project.ext.react.cliPath` to the path of the react-native cli.js file. " + - "This file typically resides in `node_modules/react-native/cli.js`"); -} - -def reactNativeDevServerPort() { - def value = project.getProperties().get("reactNativeDevServerPort") - return value != null ? value : "8081" -} - -def reactNativeInspectorProxyPort() { - def value = project.getProperties().get("reactNativeInspectorProxyPort") - return value != null ? value : reactNativeDevServerPort() -} - -def getHermesOSBin() { - if (Os.isFamily(Os.FAMILY_WINDOWS)) return "win64-bin"; - if (Os.isFamily(Os.FAMILY_MAC)) return "osx-bin"; - if (Os.isOs(null, "linux", "amd64", null)) return "linux64-bin"; - throw new Exception("OS not recognized. Please set project.ext.react.hermesCommand " + - "to the path of a working Hermes compiler."); -} - -// Make sure not to inspect the Hermes config unless we need it, -// to avoid breaking any JSC-only setups. -def getHermesCommand = { - // 1. If the project specifies a Hermes command, don't second guess it. - if (config.hermesCommand?.trim()) { - if (hermesCommand.contains("%OS-BIN%")) { - return hermesCommand - .replaceAll("%OS-BIN%", getHermesOSBin()) - .replace('/' as char, File.separatorChar) - } else { - return hermesCommand - .replace('/' as char, File.separatorChar) - } - } - - def hermescBin = Os.isFamily(Os.FAMILY_WINDOWS) ? 'hermesc.exe' : 'hermesc' - - // 2. If the project is building hermes-engine from source, use hermesc from there - // Also note that user can override the hermes source location with - // the `REACT_NATIVE_OVERRIDE_HERMES_DIR` env variable. - def hermesOverrideDir = System.getenv("REACT_NATIVE_OVERRIDE_HERMES_DIR") - def builtHermesc = hermesOverrideDir ? - new File(hermesOverrideDir, "build/bin/$hermescBin") : - new File(reactRoot, "node_modules/react-native/ReactAndroid/hermes-engine/build/hermes/bin/$hermescBin") - - if (builtHermesc.exists()) { - return builtHermesc.getAbsolutePath() - } - - // 3. If the react-native contains a pre-built hermesc, use it. - def prebuiltHermesPath = "node_modules/react-native/sdks/hermesc/%OS-BIN%/$hermescBin" - .replaceAll("%OS-BIN%", getHermesOSBin()) - .replace('/' as char, File.separatorChar); - def prebuiltHermes = new File(reactRoot, prebuiltHermesPath) - if (prebuiltHermes.exists()) { - return prebuiltHermes.getAbsolutePath() - } - - throw new Exception("Couldn't determine Hermesc location. " + - "Please set `project.ext.react.hermesCommand` to the path of the hermesc binary file. " + - "node_modules/react-native/sdks/hermesc/%OS-BIN%/hermesc"); -} - -// Set enableHermesForVariant to a function to configure per variant, -// or set `enableHermes` to True/False to set all of them -def enableHermesForVariant = config.enableHermesForVariant ?: { - def variant -> config.enableHermes ?: false -} - -// Set hermesFlagsForVariant to a function to configure per variant, -// or set `hermesFlagsRelease` and `hermesFlagsDebug` to an array -def hermesFlagsForVariant = config.hermesFlagsForVariant ?: { - def variant -> - def hermesFlags; - if (variant.name.toLowerCase().contains("release")) { - // Can't use ?: since that will also substitute valid empty lists - hermesFlags = config.hermesFlagsRelease - if (hermesFlags == null) hermesFlags = ["-O", "-output-source-map"] - } else { - hermesFlags = config.hermesFlagsDebug - if (hermesFlags == null) hermesFlags = [] - } - return hermesFlags -} - -// Set disableDevForVariant to a function to configure per variant, -// defaults to `devDisabledIn${targetName}` or True for Release variants and False for debug variants -def disableDevForVariant = config.disableDevForVariant ?: { - def variant -> - config."devDisabledIn${variant.name.capitalize()}" || - variant.name.toLowerCase().contains("release") -} - -// Set bundleForVariant to a function to configure per variant, -// defaults to `bundleIn${targetName}` or True for Release variants and False for debug variants -def bundleForVariant = config.bundleForVariant ?: { - def variant -> - config."bundleIn${variant.name.capitalize()}" || - config."bundleIn${variant.buildType.name.capitalize()}" || - variant.name.toLowerCase().contains("release") -} - -// Set deleteDebugFilesForVariant to a function to configure per variant, -// defaults to True for Release variants and False for debug variants -def deleteDebugFilesForVariant = config.deleteDebugFilesForVariant ?: { - def variant -> variant.name.toLowerCase().contains("release") -} - -android { - buildTypes.all { - resValue "integer", "react_native_dev_server_port", reactNativeDevServerPort() - resValue "integer", "react_native_inspector_proxy_port", reactNativeInspectorProxyPort() - } -} - -def jvmVersion = Jvm.current().javaVersion.majorVersion -if (jvmVersion.toInteger() <= 8) { - println "\n\n\n" - println "**************************************************************************************************************" - println "\n\n" - println "ERROR: requires JDK11 or higher." - println "Incompatible major version detected: '" + jvmVersion + "'" - println "\n\n" - println "**************************************************************************************************************" - println "\n\n\n" - System.exit(1) -} - -afterEvaluate { - def isAndroidLibrary = plugins.hasPlugin("com.android.library") - def variants = isAndroidLibrary ? android.libraryVariants : android.applicationVariants - variants.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") - def jsSourceMapsDir = file("$buildDir/generated/sourcemaps/react/${targetPath}") - def jsIntermediateSourceMapsDir = file("$buildDir/intermediates/sourcemaps/react/${targetPath}") - def jsPackagerSourceMapFile = file("$jsIntermediateSourceMapsDir/${bundleAssetName}.packager.map") - def jsCompilerSourceMapFile = file("$jsIntermediateSourceMapsDir/${bundleAssetName}.compiler.map") - def jsOutputSourceMapFile = file("$jsSourceMapsDir/${bundleAssetName}.map") - - // Additional node and packager commandline arguments - def nodeExecutableAndArgs = config.nodeExecutableAndArgs ?: ["node"] - def cliPath = detectCliPath(config, reactRoot) - - def execCommand = [] - - if (Os.isFamily(Os.FAMILY_WINDOWS)) { - execCommand.addAll(["cmd", "/c", *nodeExecutableAndArgs, cliPath]) - } else { - execCommand.addAll([*nodeExecutableAndArgs, cliPath]) - } - - def enableHermes = enableHermesForVariant(variant) - - 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() - jsIntermediateSourceMapsDir.deleteDir() - jsIntermediateSourceMapsDir.mkdirs() - jsSourceMapsDir.deleteDir() - jsSourceMapsDir.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 = !disableDevForVariant(variant) - - def extraArgs = [] - - if (bundleConfig) { - extraArgs.add("--config") - extraArgs.add(bundleConfig) - } - - // Hermes doesn't require JS minification. - if (enableHermes && !devEnabled) { - extraArgs.add("--minify") - extraArgs.add("false") - } - - if (config.extraPackagerArgs) { - extraArgs.addAll(config.extraPackagerArgs) - } - - commandLine(*execCommand, bundleCommand, "--platform", "android", "--dev", "${devEnabled}", - "--reset-cache", "--entry-file", entryFile, "--bundle-output", jsBundleFile, "--assets-dest", resourcesDir, - "--sourcemap-output", enableHermes ? jsPackagerSourceMapFile : jsOutputSourceMapFile, *extraArgs) - - - if (enableHermes) { - doLast { - def hermesFlags = hermesFlagsForVariant(variant) - def hbcTempFile = file("${jsBundleFile}.hbc") - exec { - if (Os.isFamily(Os.FAMILY_WINDOWS)) { - commandLine("cmd", "/c", getHermesCommand(), "-emit-binary", "-out", hbcTempFile, jsBundleFile, *hermesFlags) - } else { - commandLine(getHermesCommand(), "-emit-binary", "-out", hbcTempFile, jsBundleFile, *hermesFlags) - } - } - ant.move( - file: hbcTempFile, - toFile: jsBundleFile - ); - if (hermesFlags.contains("-output-source-map")) { - ant.move( - // Hermes will generate a source map with this exact name - file: "${jsBundleFile}.hbc.map", - tofile: jsCompilerSourceMapFile - ); - exec { - // TODO: set task dependencies for caching - - // Set up the call to the compose-source-maps script - workingDir(reactRoot) - if (Os.isFamily(Os.FAMILY_WINDOWS)) { - commandLine("cmd", "/c", *nodeExecutableAndArgs, composeSourceMapsPath, jsPackagerSourceMapFile, jsCompilerSourceMapFile, "-o", jsOutputSourceMapFile) - } else { - commandLine(*nodeExecutableAndArgs, composeSourceMapsPath, jsPackagerSourceMapFile, jsCompilerSourceMapFile, "-o", jsOutputSourceMapFile) - } - } - } - } - } - - enabled bundleForVariant(variant) - } - - // 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) - - // registerGeneratedResFolders for Android plugin 3.x - if (variant.respondsTo("registerGeneratedResFolders")) { - variant.registerGeneratedResFolders(currentBundleTask.generatedResFolders) - } else { - variant.registerResGeneratingTask(currentBundleTask) - } - variant.mergeResourcesProvider.get().dependsOn(currentBundleTask) - - // packageApplication for Android plugin 3.x - def packageTask = variant.hasProperty("packageApplication") - ? variant.packageApplicationProvider.get() - : tasks.findByName("package${targetName}") - if (variant.hasProperty("packageLibrary")) { - packageTask = variant.packageLibrary - } - - // pre bundle build task for Android plugin 3.2+ - def buildPreBundleTask = tasks.findByName("build${targetName}PreBundle") - - def resourcesDirConfigValue = config."resourcesDir${targetName}" - if (resourcesDirConfigValue) { - def currentCopyResTask = tasks.create( - name: "copy${targetName}BundledResources", - type: Copy) { - group = "react" - description = "copy bundled resources into custom location for ${targetName}." - - from(resourcesDir) - into(file(resourcesDirConfigValue)) - - dependsOn(currentBundleTask) - - enabled(currentBundleTask.enabled) - } - - packageTask.dependsOn(currentCopyResTask) - if (buildPreBundleTask != null) { - buildPreBundleTask.dependsOn(currentCopyResTask) - } - } - - def currentAssetsCopyTask = tasks.create( - name: "copy${targetName}BundledJs", - type: Copy) { - group = "react" - description = "copy bundled JS into ${targetName}." - - from(jsBundleDir) - if (config."jsBundleDir${targetName}") { - into(file(config."jsBundleDir${targetName}")) - } else { - into ("$buildDir/intermediates") - if (isAndroidLibrary) { - into ("library_assets/${variant.name}/out") - } else { - into ("assets/${targetPath}") - - // Workaround for Android Gradle Plugin 3.2+ new asset directory - into ("merged_assets/${variant.name}/merge${targetName}Assets/out") - - // Workaround for Android Gradle Plugin 3.4+ new asset directory - into ("merged_assets/${variant.name}/out") - - // Workaround for Android Gradle Plugin 7.1 asset directory - into("$buildDir/intermediates/assets/${variant.name}") - } - } - - // mergeAssets must run first, as it clears the intermediates directory - dependsOn(variant.mergeAssetsProvider.get()) - - enabled(currentBundleTask.enabled) - dependsOn(currentBundleTask) - } - - // 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 - def mergeResourcesTask = tasks.findByName("merge${targetName}Resources") - mergeResourcesTask.dependsOn(currentAssetsCopyTask) - - packageTask.dependsOn(currentAssetsCopyTask) - if (buildPreBundleTask != null) { - buildPreBundleTask.dependsOn(currentAssetsCopyTask) - } - - // 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. - def cleanup = deleteDebugFilesForVariant(variant) - - def vmSelectionAction = { libDir -> - fileTree(libDir).matching { - if (enableHermes) { - // For Hermes, delete all the libjsc* files - include "**/libjsc*.so" - - if (cleanup) { - // Reduce size by deleting the debugger/inspector - include '**/libhermes_executor_debug.so' - } else { - // 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 { details -> - def targetVariant1 = ".*/transforms/[^/]*/${variant.name}/.*" - def targetVariant2 = ".*/merged_native_libs/${variant.name}/out/lib/.*" - def targetVariant3 = ".*/stripped_native_libs/${variant.name}/out/lib/.*" - def path = details.file.getAbsolutePath().replace(File.separatorChar, '/' as char) - if ((path.matches(targetVariant1) || path.matches(targetVariant2) || path.matches(targetVariant3)) && details.file.isFile()) { - details.file.delete() - } - } - } - - if (enableVmCleanup) { - def task = tasks.findByName("package${targetName}") - if (task != null) { - def transformsLibDir = "$buildDir/intermediates/transforms/" - task.doFirst { vmSelectionAction(transformsLibDir) } - } - - def sTask = tasks.findByName("strip${targetName}DebugSymbols") - if (sTask != null) { - def strippedLibDir = "$buildDir/intermediates/stripped_native_libs/${variant.name}/out/lib/" - sTask.doLast { vmSelectionAction(strippedLibDir) } - } - - def mTask = tasks.findByName("merge${targetName}NativeLibs") - if (mTask != null) { - def mergedLibDir = "$buildDir/intermediates/merged_native_libs/${variant.name}/out/lib/" - mTask.doLast { vmSelectionAction(mergedLibDir) } - } - } - } -}