diff --git a/.circleci/config.yml b/.circleci/config.yml index b3ee733c859655..71f5f6d2017f58 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -760,9 +760,11 @@ jobs: description: The Android build type. Must be one of "Debug", "Release". type: enum enum: ["Debug", "Release"] - newarchitecture: - type: boolean - default: false + architecture: + default: "OldArch" + description: Which React Native architecture to use. Must be one of "NewArch", "OldArch". + type: enum + enum: [ "NewArch", "OldArch" ] jsengine: default: "Hermes" description: Which JavaScript engine to use. Must be one of "Hermes", "JSC". @@ -775,17 +777,6 @@ jobs: - run_yarn - attach_workspace: at: . - - when: - condition: - equal: ["JSC", << parameters.jsengine >>] - steps: - - run: - name: Set enableHermes in buld.gradle to false - command: | - node ./scripts/set-rn-engine.js -e jsc - echo "Hermes disabled." - grep enableHermes: template/android/app/build.gradle - - run: name: Create Android template project command: | @@ -796,10 +787,20 @@ jobs: yarn - run: - name: Build the template application for << parameters.flavor >> with New Architecture set to << parameters.newarchitecture >>, and using the << parameters.jsengine>> JS engine. + name: Build the template application for << parameters.flavor >> with Architecture set to << parameters.architecture >>, and using the << parameters.jsengine>> JS engine. command: | cd /tmp/$PROJECT_NAME/android/ - ./gradlew assemble<< parameters.flavor >> -PnewArchEnabled=<< parameters.newarchitecture >> -PREACT_NATIVE_MAVEN_LOCAL_REPO=/root/react-native/maven-local + if [[ << parameters.architecture >> == "NewArch" ]]; then + export ORG_GRADLE_PROJECT_newArchEnabled=true + else + export ORG_GRADLE_PROJECT_newArchEnabled=false + fi + if [[ << parameters.jsengine >> == "Hermes" ]]; then + export ORG_GRADLE_PROJECT_hermesEnabled=true + else + export ORG_GRADLE_PROJECT_hermesEnabled=false + fi + ./gradlew assemble<< parameters.flavor >> -PREACT_NATIVE_MAVEN_LOCAL_REPO=/root/react-native/maven-local # ------------------------- # JOBS: Test iOS Template @@ -1602,7 +1603,7 @@ workflows: - build_npm_package matrix: parameters: - newarchitecture: [true, false] + architecture: ["NewArch", "OldArch"] jsengine: ["Hermes", "JSC"] flavor: ["Debug", "Release"] - test_buck diff --git a/packages/rn-tester/android/app/build.gradle b/packages/rn-tester/android/app/build.gradle index 86d3646ba34ce8..c7d5c448d5bd29 100644 --- a/packages/rn-tester/android/app/build.gradle +++ b/packages/rn-tester/android/app/build.gradle @@ -11,92 +11,57 @@ plugins { } /** - * 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 - * and their defaults. If you decide to add a configuration block, make sure to add it before the - * `apply from: "react.gradle"` line. - * - * project.ext.react = [ - * // the name of the generated asset file containing your JS bundle - * bundleAssetName: "index.android.bundle", - * - * // the entry file for bundle generation - * entryFile: "index.android.js", - * - * // whether to bundle JS and assets in debug mode - * bundleInDebug: false, - * - * // 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: "../../", - * - * // where to put the JS bundle asset in debug mode - * jsBundleDirDebug: "$buildDir/intermediates/assets/debug", - * - * // where to put the JS bundle asset in release mode - * jsBundleDirRelease: "$buildDir/intermediates/assets/release", - * - * // where to put drawable resources / React Native assets, e.g. the ones you use via - * // require('./image.png')), in debug mode - * resourcesDirDebug: "$buildDir/intermediates/res/merged/debug", - * - * // where to put drawable resources / React Native assets, e.g. the ones you use via - * // require('./image.png')), in release mode - * resourcesDirRelease: "$buildDir/intermediates/res/merged/release", - * - * // by default the gradle tasks are skipped if none of the JS files or assets change; this means - * // that we don't look at files in android/ or ios/ to determine whether the tasks are up to - * // date; if you have any other folders that you want to ignore for performance reasons (gradle - * // indexes the entire tree), add them here. Alternatively, if you have JS files in android/ - * // for example, you might want to remove it from here. - * inputExcludes: ["android/**", "ios/**"], - * - * // Root dir for all JS files for the app. Defaults to `root` above. - * jsRootDir: "../..", - * - * // Enable Fabric at runtime. - * enableFabric: true, - * - * // Java package name to use for any codegen artifacts produced during build time. - * // Defaults to "com.facebook.fbreact.specs". - * codegenJavaPackageName: "com.facebook.fbreact.specs", - * ] + * This is the configuration block to customize your React Native Android app. + * By default you don't need to apply any configuration, just uncomment the lines you need. */ - react { + /* Folders */ + // The root of your project, i.e. where "package.json" lives. Default is '..' + root = file("../../") + // The folder where the react-native NPM package is. Default is ../node_modules/react-native + reactNativeDir = rootDir + // The folder where the react-native Codegen package is. Default is ../node_modules/react-native-codegen + codegenDir = file("$rootDir/node_modules/react-native-codegen") + // The cli.js file which is the React Native CLI entrypoint. Default is ../node_modules/react-native/cli.js cliFile = file("$rootDir/cli.js") + + /* Variants */ + // The list of variants to that are debuggable. For those we're going to + // skip the bundling of the JS bundle and the assets. By default is just 'debug'. + // If you add flavors like lite, prod, etc. you'll have to list your debuggableVariants. + debuggableVariants = ["hermesDebug", "jscDebug"] + + /* Bundling */ + // A list containing the node command and its flags. Default is just 'node'. + // nodeExecutableAndArgs = ["node"] + // + // The command to run when bundling. By default is 'bundle' + // bundleCommand = "ram-bundle" + // + // The path to the CLI configuration file. Default is empty. + // bundleConfig = file(../rn-cli.config.js) + // + // The name of the generated asset file containing your JS bundle bundleAssetName = "RNTesterApp.android.bundle" + // + // The entry file for bundle generation. Default is 'index.android.js' or 'index.js' entryFile = file("../../js/RNTesterApp.android.js") - root = file("../../") + // + // A list of extra flags to pass to the 'bundle' commands. + // See https://github.com/react-native-community/cli/blob/main/docs/commands.md#bundle + // extraPackagerArgs = [] + + /* Hermes Commands */ + // The hermes compiler command to run. By default it is 'hermesc' hermesCommand = "$rootDir/ReactAndroid/hermes-engine/build/hermes/bin/hermesc" - debuggableVariants = ["hermesDebug", "jscDebug"] enableHermesOnlyInVariants = ["hermesDebug", "hermesRelease"] - - // Codegen Configs - reactNativeDir = rootDir - codegenDir = file("$rootDir/node_modules/react-native-codegen") } /** - * Set this to true to create three separate APKs instead of one: - * - A universal APK that works on all devices - * - An APK that only works on ARM devices - * - An APK that only works on x86 devices - * The advantage is the size of the APK is reduced by about 4MB. - * Upload all the APKs to the Play Store and people will download - * the correct one based on the CPU architecture of their device. + * Set this to true to create four separate APKs instead of one, + * one for each native architecture. This is useful if you don't + * use App Bundles (https://developer.android.com/guide/app-bundle/) + * and want to have separate APKs to upload to the Play Store. */ def enableSeparateBuildPerCPUArchitecture = true @@ -106,12 +71,11 @@ def enableSeparateBuildPerCPUArchitecture = true def enableProguardInReleaseBuilds = true /** - * Use the international variant of JavaScriptCore - * This variant includes the ICU i18n library to make APIs like `Date.toLocaleString` - * and `String.localeCompare` work when using with locales other than en-US. - * Note that this variant is about 6MiB larger per architecture than the default. + * The preferred build flavor of JavaScriptCore (JSC) + * For example, to use the international variant, you can use: + * `def jscFlavor = 'org.webkit:android-jsc-intl:+'` */ -def useIntlJsc = false +def jscFlavor = 'org.webkit:android-jsc:+' /** * Architectures to build native code for. @@ -206,11 +170,7 @@ dependencies { debugImplementation("com.facebook.flipper:flipper-network-plugin:${FLIPPER_VERSION}") debugImplementation("com.facebook.flipper:flipper-fresco-plugin:${FLIPPER_VERSION}") - if (useIntlJsc) { - jscImplementation 'org.webkit:android-jsc-intl:+' - } else { - jscImplementation 'org.webkit:android-jsc:+' - } + jscImplementation jscFlavor androidTestImplementation 'junit:junit:4.12' } diff --git a/scripts/set-rn-engine.js b/scripts/set-rn-engine.js deleted file mode 100755 index 52afa5b749dfe8..00000000000000 --- a/scripts/set-rn-engine.js +++ /dev/null @@ -1,53 +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. - * - * @format - */ - -'use strict'; - -/** - * This script updates the engine used by React Native - */ -const {echo, exec, exit, sed} = require('shelljs'); -const yargs = require('yargs'); - -let argv = yargs.option('e', { - alias: 'engine', - describe: 'Choose an engine', - type: 'string', - choices: ['hermes', 'jsc'], -}).argv; - -const engine = argv.engine; - -if (!engine) { - echo('You must specify an engine using -e'); - exit(1); -} - -// Change the template build.gradle -sed( - '-i', - /enableHermes:.*/, - engine === 'jsc' ? 'enableHermes: false' : 'enableHermes: true', - 'template/android/app/build.gradle', -); - -// Validate the hermes flag has been changed properly -const hermes = - exec( - 'grep enableHermes: template/android/app/build.gradle | awk \'{split($0,a,"[:,]"); print a[2]}\'', - {silent: true}, - ).stdout.trim() === 'true'; - -if ((engine === 'jsc' && hermes) || (engine === 'hermes' && !hermes)) { - echo('Failed to update the engine in template/android/app/build.gradle'); - echo('Fix the issue and try again'); - exit(1); -} - -exit(0); diff --git a/template/android/app/build.gradle b/template/android/app/build.gradle index 1a56feaba4970a..3ba40f561020c5 100644 --- a/template/android/app/build.gradle +++ b/template/android/app/build.gradle @@ -4,123 +4,84 @@ apply plugin: "com.facebook.react" import com.android.build.OutputFile /** - * 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 - * and their defaults. If you decide to add a configuration block, make sure to add it before the - * `apply from: "../../node_modules/react-native/react.gradle"` line. - * - * project.ext.react = [ - * // the name of the generated asset file containing your JS bundle - * bundleAssetName: "index.android.bundle", - * - * // the entry file for bundle generation. If none specified and - * // "index.android.js" exists, it will be used. Otherwise "index.js" is - * // default. Can be overridden with ENTRY_FILE environment variable. - * entryFile: "index.android.js", - * - * // https://reactnative.dev/docs/performance#enable-the-ram-format - * bundleCommand: "ram-bundle", - * - * // whether to bundle JS and assets in debug mode - * bundleInDebug: false, - * - * // 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 can be in the following formats - * // 'bundleIn${productFlavor}${buildType}' - * // 'bundleIn${buildType}' - * // bundleInFreeDebug: true, - * // bundleInPaidRelease: true, - * // bundleInBeta: true, - * - * // whether to disable dev mode in custom build variants (by default only disabled in release) - * // for example: to disable dev mode in the staging build type (if configured) - * devDisabledInStaging: true, - * // The configuration property can be in the following formats - * // 'devDisabledIn${productFlavor}${buildType}' - * // 'devDisabledIn${buildType}' - * - * // the root of your project, i.e. where "package.json" lives - * root: "../../", - * - * // where to put the JS bundle asset in debug mode - * jsBundleDirDebug: "$buildDir/intermediates/assets/debug", - * - * // where to put the JS bundle asset in release mode - * jsBundleDirRelease: "$buildDir/intermediates/assets/release", - * - * // where to put drawable resources / React Native assets, e.g. the ones you use via - * // require('./image.png')), in debug mode - * resourcesDirDebug: "$buildDir/intermediates/res/merged/debug", - * - * // where to put drawable resources / React Native assets, e.g. the ones you use via - * // require('./image.png')), in release mode - * resourcesDirRelease: "$buildDir/intermediates/res/merged/release", - * - * // by default the gradle tasks are skipped if none of the JS files or assets change; this means - * // that we don't look at files in android/ or ios/ to determine whether the tasks are up to - * // date; if you have any other folders that you want to ignore for performance reasons (gradle - * // indexes the entire tree), add them here. Alternatively, if you have JS files in android/ - * // for example, you might want to remove it from here. - * inputExcludes: ["android/**", "ios/**"], - * - * // override which node gets called and with what additional arguments - * nodeExecutableAndArgs: ["node"], - * - * // supply additional arguments to the packager - * extraPackagerArgs: [] - * ] + * This is the configuration block to customize your React Native Android app. + * By default you don't need to apply any configuration, just uncomment the lines you need. */ - -project.ext.react = [ - enableHermes: true, // clean and rebuild if changing -] +react { + /* Folders */ + // The root of your project, i.e. where "package.json" lives. Default is '..' + // root = file("../") + // The folder where the react-native NPM package is. Default is ../node_modules/react-native + // reactNativeDir = file("../node-modules/react-native") + // The folder where the react-native Codegen package is. Default is ../node_modules/react-native-codegen + // codegenDir = file("../node-modules/react-native-codegen") + // The cli.js file which is the React Native CLI entrypoint. Default is ../node_modules/react-native/cli.js + // cliFile = file("../node_modules/react-native/cli.js") + + /* Variants */ + // The list of variants to that are debuggable. For those we're going to + // skip the bundling of the JS bundle and the assets. By default is just 'debug'. + // If you add flavors like lite, prod, etc. you'll have to list your debuggableVariants. + // debuggableVariants = ["liteDebug", "prodDebug"] + + /* Bundling */ + // A list containing the node command and its flags. Default is just 'node'. + // nodeExecutableAndArgs = ["node"] + // + // The command to run when bundling. By default is 'bundle' + // bundleCommand = "ram-bundle" + // + // The path to the CLI configuration file. Default is empty. + // bundleConfig = file(../rn-cli.config.js) + // + // The name of the generated asset file containing your JS bundle + // bundleAssetName = "MyApplication.android.bundle" + // + // The entry file for bundle generation. Default is 'index.android.js' or 'index.js' + // entryFile = file("../js/MyApplication.android.js") + // + // A list of extra flags to pass to the 'bundle' commands. + // See https://github.com/react-native-community/cli/blob/main/docs/commands.md#bundle + // extraPackagerArgs = [] + + /* Hermes Commands */ + // The hermes compiler command to run. By default it is 'hermesc' + // hermesCommand = "$rootDir/my-custom-hermesc/bin/hermesc" + // + // The list of flags to pass to the Hermes compiler. By default is "-O", "-output-source-map" + // hermesFlags = ["-O", "-output-source-map"] +} /** - * Set this to true to create two separate APKs instead of one: - * - An APK that only works on ARM devices - * - An APK that only works on x86 devices - * The advantage is the size of the APK is reduced by about 4MB. - * Upload all the APKs to the Play Store and people will download - * the correct one based on the CPU architecture of their device. + * Set this to true to create four separate APKs instead of one, + * one for each native architecture. This is useful if you don't + * use App Bundles (https://developer.android.com/guide/app-bundle/) + * and want to have separate APKs to upload to the Play Store. */ def enableSeparateBuildPerCPUArchitecture = false /** - * Run Proguard to shrink the Java bytecode in release builds. + * Set this to true to Run Proguard on Release builds to minify the Java bytecode. */ def enableProguardInReleaseBuilds = false /** - * The preferred build flavor of JavaScriptCore. + * The preferred build flavor of JavaScriptCore (JSC) * * For example, to use the international variant, you can use: * `def jscFlavor = 'org.webkit:android-jsc-intl:+'` * * The international variant includes ICU i18n library and necessary data * allowing to use e.g. `Date.toLocaleString` and `String.localeCompare` that - * give correct results when using with locales other than en-US. Note that + * give correct results when using with locales other than en-US. Note that * this variant is about 6MiB larger per architecture than default. */ def jscFlavor = 'org.webkit:android-jsc:+' /** - * Whether to enable the Hermes VM. - * - * This should be set on project.ext.react and that value will be read here. If it is not set - * on project.ext.react, JavaScript will not be compiled to Hermes Bytecode - * and the benefits of using Hermes will therefore be sharply reduced. - */ -def enableHermes = project.ext.react.get("enableHermes", false); - -/** - * Architectures to build native code for. + * Private function to get the list of Native Architectures you want to build. + * This reads the value from reactNativeArchitectures in your gradle.properties + * file and works together with the --active-arch-only flag of react-native run-android. */ def reactNativeArchitectures() { def value = project.getProperties().get("reactNativeArchitectures") @@ -187,8 +148,6 @@ android { } dependencies { - implementation fileTree(dir: "libs", include: ["*.jar"]) - // The version of react-native is set by the React Native Gradle Plugin implementation("com.facebook.react:react-native") @@ -200,7 +159,7 @@ dependencies { } debugImplementation("com.facebook.flipper:flipper-fresco-plugin:${FLIPPER_VERSION}") - if (enableHermes) { + if (hermesEnabled.toBoolean()) { implementation("com.facebook.react:hermes-engine") } else { implementation jscFlavor diff --git a/template/android/build.gradle b/template/android/build.gradle index c6c8e7351ba0eb..c9a672214815b5 100644 --- a/template/android/build.gradle +++ b/template/android/build.gradle @@ -17,8 +17,6 @@ buildscript { dependencies { classpath("com.android.tools.build:gradle:7.3.1") classpath("com.facebook.react:react-native-gradle-plugin") - // NOTE: Do not place your application dependencies here; they belong - // in the individual module build.gradle files } } diff --git a/template/android/gradle.properties b/template/android/gradle.properties index fa4feae5f19024..e4af465e8a1857 100644 --- a/template/android/gradle.properties +++ b/template/android/gradle.properties @@ -38,3 +38,7 @@ reactNativeArchitectures=armeabi-v7a,arm64-v8a,x86,x86_64 # to write custom TurboModules/Fabric components OR use libraries that # are providing them. newArchEnabled=false + +# Use this property to enable or disable the Hermes JS engine. +# If set to false, you will be using JSC instead. +hermesEnabled=true