@ohos-ports/react-native-gradle-plugin 0.71.19-beta.0 → 0.86.0-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (74) hide show
  1. package/README.md +11 -4
  2. package/build.gradle.kts +33 -41
  3. package/gradle/libs.versions.toml +22 -0
  4. package/gradle/wrapper/gradle-wrapper.jar +0 -0
  5. package/gradle/wrapper/gradle-wrapper.properties +3 -1
  6. package/gradle.properties +2 -0
  7. package/gradlew +32 -18
  8. package/gradlew.bat +22 -18
  9. package/package.json +21 -11
  10. package/react-native-gradle-plugin/README.md +17 -0
  11. package/react-native-gradle-plugin/build.gradle.kts +83 -0
  12. package/{src → react-native-gradle-plugin/src}/main/kotlin/com/facebook/react/ReactExtension.kt +78 -10
  13. package/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/ReactPlugin.kt +320 -0
  14. package/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/ReactRootProjectPlugin.kt +86 -0
  15. package/{src → react-native-gradle-plugin/src}/main/kotlin/com/facebook/react/TaskConfiguration.kt +36 -25
  16. package/{src → react-native-gradle-plugin/src}/main/kotlin/com/facebook/react/internal/PrivateReactExtension.kt +11 -4
  17. package/{src → react-native-gradle-plugin/src}/main/kotlin/com/facebook/react/tasks/BundleHermesCTask.kt +60 -50
  18. package/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/tasks/GenerateAutolinkingNewArchitecturesFileTask.kt +252 -0
  19. package/{src → react-native-gradle-plugin/src}/main/kotlin/com/facebook/react/tasks/GenerateCodegenArtifactsTask.kt +8 -3
  20. package/{src → react-native-gradle-plugin/src}/main/kotlin/com/facebook/react/tasks/GenerateCodegenSchemaTask.kt +11 -18
  21. package/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/tasks/GenerateEntryPointTask.kt +108 -0
  22. package/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/tasks/GeneratePackageListTask.kt +214 -0
  23. package/{src/main/kotlin/com/facebook/react/tasks → react-native-gradle-plugin/src/main/kotlin/com/facebook/react/tasks/internal}/BuildCodegenCLITask.kt +24 -17
  24. package/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/tasks/internal/CustomExecTask.kt +46 -0
  25. package/{src → react-native-gradle-plugin/src}/main/kotlin/com/facebook/react/tasks/internal/PrepareBoostTask.kt +10 -4
  26. package/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/tasks/internal/PrepareGflagsTask.kt +119 -0
  27. package/{src → react-native-gradle-plugin/src}/main/kotlin/com/facebook/react/tasks/internal/PrepareGlogTask.kt +26 -18
  28. package/{src → react-native-gradle-plugin/src}/main/kotlin/com/facebook/react/tasks/internal/PreparePrefabHeadersTask.kt +28 -12
  29. package/{src → react-native-gradle-plugin/src}/main/kotlin/com/facebook/react/tasks/internal/utils/PrefabPreprocessingEntry.kt +4 -3
  30. package/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/AgpConfiguratorUtils.kt +163 -0
  31. package/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/BackwardCompatUtils.kt +71 -0
  32. package/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/DependencyUtils.kt +299 -0
  33. package/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/JdkConfiguratorUtils.kt +64 -0
  34. package/{src → react-native-gradle-plugin/src}/main/kotlin/com/facebook/react/utils/NdkConfiguratorUtils.kt +59 -65
  35. package/{src → react-native-gradle-plugin/src}/main/kotlin/com/facebook/react/utils/PathUtils.kt +44 -30
  36. package/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/ProjectUtils.kt +119 -0
  37. package/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/PropertyUtils.kt +96 -0
  38. package/settings-plugin/build.gradle.kts +73 -0
  39. package/settings-plugin/src/main/kotlin/com/facebook/react/ReactSettingsExtension.kt +217 -0
  40. package/settings-plugin/src/main/kotlin/com/facebook/react/ReactSettingsPlugin.kt +23 -0
  41. package/settings-plugin/src/test/kotlin/com/facebook/react/ReactSettingsExtensionTest.kt +475 -0
  42. package/settings.gradle.kts +10 -1
  43. package/shared/build.gradle.kts +52 -0
  44. package/shared/src/main/kotlin/com/facebook/react/model/ModelAutolinkingAndroidProjectJson.kt +18 -0
  45. package/shared/src/main/kotlin/com/facebook/react/model/ModelAutolinkingConfigJson.kt +14 -0
  46. package/shared/src/main/kotlin/com/facebook/react/model/ModelAutolinkingDependenciesJson.kt +18 -0
  47. package/shared/src/main/kotlin/com/facebook/react/model/ModelAutolinkingDependenciesPlatformAndroidJson.kt +23 -0
  48. package/shared/src/main/kotlin/com/facebook/react/model/ModelAutolinkingDependenciesPlatformJson.kt +12 -0
  49. package/shared/src/main/kotlin/com/facebook/react/model/ModelAutolinkingProjectJson.kt +10 -0
  50. package/{src → shared/src}/main/kotlin/com/facebook/react/model/ModelCodegenConfig.kt +2 -1
  51. package/{src → shared/src}/main/kotlin/com/facebook/react/model/ModelPackageJson.kt +1 -1
  52. package/shared/src/main/kotlin/com/facebook/react/utils/JsonUtils.kt +43 -0
  53. package/shared/src/main/kotlin/com/facebook/react/utils/KotlinStdlibCompatUtils.kt +32 -0
  54. package/{src → shared/src}/main/kotlin/com/facebook/react/utils/Os.kt +7 -6
  55. package/{src → shared/src}/main/kotlin/com/facebook/react/utils/TaskUtils.kt +4 -5
  56. package/shared/src/test/kotlin/com/facebook/react/utils/JsonUtilsTest.kt +382 -0
  57. package/shared/src/test/kotlin/com/facebook/react/utils/KotlinStdlibCompatUtilsTest.kt +82 -0
  58. package/shared/src/test/kotlin/com/facebook/react/utils/OsTest.kt +87 -0
  59. package/shared/src/test/kotlin/com/facebook/react/utils/TaskUtilsTest.kt +76 -0
  60. package/shared-testutil/build.gradle.kts +46 -0
  61. package/shared-testutil/src/main/kotlin/com/facebook/react/tests/OsRule.kt +52 -0
  62. package/shared-testutil/src/main/kotlin/com/facebook/react/tests/WithOs.kt +17 -0
  63. package/build/libs/react-native-gradle-plugin.jar +0 -0
  64. package/index.js +0 -73
  65. package/src/main/kotlin/com/facebook/react/ReactPlugin.kt +0 -212
  66. package/src/main/kotlin/com/facebook/react/tasks/internal/PrepareJSCTask.kt +0 -50
  67. package/src/main/kotlin/com/facebook/react/tasks/internal/PrepareLibeventTask.kt +0 -51
  68. package/src/main/kotlin/com/facebook/react/utils/AgpConfiguratorUtils.kt +0 -54
  69. package/src/main/kotlin/com/facebook/react/utils/BackwardCompatUtils.kt +0 -48
  70. package/src/main/kotlin/com/facebook/react/utils/DependencyUtils.kt +0 -109
  71. package/src/main/kotlin/com/facebook/react/utils/JsonUtils.kt +0 -21
  72. package/src/main/kotlin/com/facebook/react/utils/ProjectUtils.kt +0 -55
  73. /package/{src → react-native-gradle-plugin/src}/main/kotlin/com/facebook/react/utils/FileUtils.kt +0 -0
  74. /package/{src → shared/src}/main/kotlin/com/facebook/react/model/ModelCodegenConfigAndroid.kt +0 -0
@@ -7,11 +7,10 @@
7
7
 
8
8
  package com.facebook.react.utils
9
9
 
10
- import com.android.build.api.variant.AndroidComponentsExtension
10
+ import com.android.build.api.variant.ApplicationAndroidComponentsExtension
11
11
  import com.android.build.api.variant.Variant
12
12
  import com.facebook.react.ReactExtension
13
13
  import com.facebook.react.utils.ProjectUtils.getReactNativeArchitectures
14
- import com.facebook.react.utils.ProjectUtils.isNewArchEnabled
15
14
  import java.io.File
16
15
  import org.gradle.api.Project
17
16
 
@@ -19,11 +18,8 @@ internal object NdkConfiguratorUtils {
19
18
  @Suppress("UnstableApiUsage")
20
19
  fun configureReactNativeNdk(project: Project, extension: ReactExtension) {
21
20
  project.pluginManager.withPlugin("com.android.application") {
22
- project.extensions.getByType(AndroidComponentsExtension::class.java).finalizeDsl { ext ->
23
- if (!project.isNewArchEnabled) {
24
- // For Old Arch, we don't need to setup the NDK
25
- return@finalizeDsl
26
- }
21
+ project.extensions.getByType(ApplicationAndroidComponentsExtension::class.java).finalizeDsl {
22
+ ext ->
27
23
  // We enable prefab so users can consume .so/headers from ReactAndroid and hermes-engine
28
24
  // .aar
29
25
  ext.buildFeatures.prefab = true
@@ -34,22 +30,30 @@ internal object NdkConfiguratorUtils {
34
30
  ext.externalNativeBuild.cmake.path =
35
31
  File(
36
32
  extension.reactNativeDir.get().asFile,
37
- "ReactAndroid/cmake-utils/default-app-setup/CMakeLists.txt")
33
+ "ReactAndroid/cmake-utils/default-app-setup/CMakeLists.txt",
34
+ )
38
35
  }
39
36
 
40
37
  // Parameters should be provided in an additive manner (do not override what
41
38
  // the user provided, but allow for sensible defaults).
42
39
  val cmakeArgs = ext.defaultConfig.externalNativeBuild.cmake.arguments
43
- if ("-DPROJECT_BUILD_DIR" !in cmakeArgs) {
44
- cmakeArgs.add("-DPROJECT_BUILD_DIR=${project.buildDir}")
40
+ if (cmakeArgs.none { it.startsWith("-DPROJECT_BUILD_DIR") }) {
41
+ cmakeArgs.add("-DPROJECT_BUILD_DIR=${project.layout.buildDirectory.get().asFile}")
42
+ }
43
+ if (cmakeArgs.none { it.startsWith("-DPROJECT_ROOT_DIR") }) {
44
+ cmakeArgs.add("-DPROJECT_ROOT_DIR=${project.rootProject.layout.projectDirectory.asFile}")
45
45
  }
46
- if ("-DREACT_ANDROID_DIR" !in cmakeArgs) {
46
+ if (cmakeArgs.none { it.startsWith("-DREACT_ANDROID_DIR") }) {
47
47
  cmakeArgs.add(
48
- "-DREACT_ANDROID_DIR=${extension.reactNativeDir.file("ReactAndroid").get().asFile}")
48
+ "-DREACT_ANDROID_DIR=${extension.reactNativeDir.file("ReactAndroid").get().asFile}"
49
+ )
49
50
  }
50
- if ("-DANDROID_STL" !in cmakeArgs) {
51
+ if (cmakeArgs.none { it.startsWith("-DANDROID_STL") }) {
51
52
  cmakeArgs.add("-DANDROID_STL=c++_shared")
52
53
  }
54
+ if (cmakeArgs.none { it.startsWith("-DANDROID_SUPPORT_FLEXIBLE_PAGE_SIZES") }) {
55
+ cmakeArgs.add("-DANDROID_SUPPORT_FLEXIBLE_PAGE_SIZES=ON")
56
+ }
53
57
 
54
58
  val architectures = project.getReactNativeArchitectures()
55
59
  // abiFilters are split ABI are not compatible each other, so we set the abiFilters
@@ -68,48 +72,23 @@ internal object NdkConfiguratorUtils {
68
72
  */
69
73
  fun configureNewArchPackagingOptions(
70
74
  project: Project,
75
+ extension: ReactExtension,
71
76
  variant: Variant,
72
77
  ) {
73
- if (!project.isNewArchEnabled) {
74
- // For Old Arch, we set a pickFirst only on libraries that we know are
75
- // clashing with our direct dependencies (FBJNI, Flipper and Hermes).
76
- variant.packaging.jniLibs.pickFirsts.addAll(
77
- listOf(
78
- "**/libfbjni.so",
79
- "**/libc++_shared.so",
80
- ))
81
- } else {
82
- // We set some packagingOptions { pickFirst ... } for our users for libraries we own.
83
- variant.packaging.jniLibs.pickFirsts.addAll(
84
- listOf(
85
- // This is the .so provided by FBJNI via prefab
86
- "**/libfbjni.so",
87
- // Those are prefab libraries we distribute via ReactAndroid
88
- // Due to a bug in AGP, they fire a warning on console as both the JNI
89
- // and the prefab .so files gets considered. See more on:
90
- "**/libfabricjni.so",
91
- "**/libfolly_runtime.so",
92
- "**/libglog.so",
93
- "**/libjsi.so",
94
- "**/libreact_codegen_rncore.so",
95
- "**/libreact_debug.so",
96
- "**/libreact_nativemodule_core.so",
97
- "**/libreact_newarchdefaults.so",
98
- "**/libreact_render_componentregistry.so",
99
- "**/libreact_render_core.so",
100
- "**/libreact_render_debug.so",
101
- "**/libreact_render_graphics.so",
102
- "**/libreact_render_imagemanager.so",
103
- "**/libreact_render_mapbuffer.so",
104
- "**/librrc_image.so",
105
- "**/librrc_view.so",
106
- "**/libruntimeexecutor.so",
107
- "**/libturbomodulejsijni.so",
108
- "**/libyoga.so",
109
- // AGP will give priority of libc++_shared coming from App modules.
110
- "**/libc++_shared.so",
111
- ))
112
- }
78
+ // We set some packagingOptions { pickFirst ... } for our users for libraries we own.
79
+ variant.packaging.jniLibs.pickFirsts.addAll(
80
+ listOf(
81
+ // This is the .so provided by FBJNI via prefab
82
+ "**/libfbjni.so",
83
+ // Those are prefab libraries we distribute via ReactAndroid
84
+ // Due to a bug in AGP, they fire a warning on console as both the JNI
85
+ // and the prefab .so files gets considered.
86
+ "**/libreactnative.so",
87
+ "**/libjsi.so",
88
+ // AGP will give priority of libc++_shared coming from App modules.
89
+ "**/libc++_shared.so",
90
+ )
91
+ )
113
92
  }
114
93
 
115
94
  /**
@@ -120,27 +99,42 @@ internal object NdkConfiguratorUtils {
120
99
  config: ReactExtension,
121
100
  variant: Variant,
122
101
  hermesEnabled: Boolean,
102
+ useThirdPartyJSC: Boolean,
123
103
  ) {
124
104
  if (config.enableSoCleanup.get()) {
125
- val (excludes, includes) = getPackagingOptionsForVariant(hermesEnabled)
105
+ val (excludes, includes) = getPackagingOptionsForVariant(hermesEnabled, useThirdPartyJSC)
126
106
  variant.packaging.jniLibs.excludes.addAll(excludes)
127
107
  variant.packaging.jniLibs.pickFirsts.addAll(includes)
128
108
  }
129
109
  }
130
110
 
131
- fun getPackagingOptionsForVariant(hermesEnabled: Boolean): Pair<List<String>, List<String>> {
111
+ fun getPackagingOptionsForVariant(
112
+ hermesEnabled: Boolean,
113
+ useThirdPartyJSC: Boolean,
114
+ ): Pair<List<String>, List<String>> {
132
115
  val excludes = mutableListOf<String>()
133
116
  val includes = mutableListOf<String>()
134
- if (hermesEnabled) {
135
- excludes.add("**/libjsc.so")
136
- excludes.add("**/libjscexecutor.so")
137
- includes.add("**/libhermes.so")
138
- includes.add("**/libhermes_executor.so")
139
- } else {
140
- excludes.add("**/libhermes.so")
141
- excludes.add("**/libhermes_executor.so")
142
- includes.add("**/libjsc.so")
143
- includes.add("**/libjscexecutor.so")
117
+
118
+ // note: libjsctooling.so is kept here for backward compatibility.
119
+ when {
120
+ hermesEnabled -> {
121
+ excludes.add("**/libjsc.so")
122
+ excludes.add("**/libjsctooling.so")
123
+ includes.add("**/libhermesvm.so")
124
+ includes.add("**/libhermestooling.so")
125
+ }
126
+ useThirdPartyJSC -> {
127
+ excludes.add("**/libhermesvm.so")
128
+ excludes.add("**/libhermestooling.so")
129
+ excludes.add("**/libjsctooling.so")
130
+ includes.add("**/libjsc.so")
131
+ }
132
+ else -> {
133
+ excludes.add("**/libhermesvm.so")
134
+ excludes.add("**/libhermestooling.so")
135
+ includes.add("**/libjsc.so")
136
+ includes.add("**/libjsctooling.so")
137
+ }
144
138
  }
145
139
  return excludes to includes
146
140
  }
@@ -11,6 +11,7 @@ package com.facebook.react.utils
11
11
 
12
12
  import com.facebook.react.ReactExtension
13
13
  import com.facebook.react.model.ModelPackageJson
14
+ import com.facebook.react.utils.KotlinStdlibCompatUtils.capitalizeCompat
14
15
  import com.facebook.react.utils.Os.cliPath
15
16
  import java.io.File
16
17
  import org.gradle.api.Project
@@ -29,7 +30,8 @@ internal fun detectedEntryFile(config: ReactExtension, envVariableOverride: Stri
29
30
  detectEntryFile(
30
31
  entryFile = config.entryFile.orNull?.asFile,
31
32
  reactRoot = config.root.get().asFile,
32
- envVariableOverride = envVariableOverride)
33
+ envVariableOverride = envVariableOverride,
34
+ )
33
35
 
34
36
  /**
35
37
  * Computes the CLI file for React Native. The Algo follows this order:
@@ -40,17 +42,19 @@ internal fun detectedEntryFile(config: ReactExtension, envVariableOverride: Stri
40
42
  */
41
43
  internal fun detectedCliFile(config: ReactExtension): File =
42
44
  detectCliFile(
45
+ project = config.project,
43
46
  reactNativeRoot = config.root.get().asFile,
44
- preconfiguredCliFile = config.cliFile.asFile.orNull)
47
+ preconfiguredCliFile = config.cliFile.asFile.orNull,
48
+ )
45
49
 
46
50
  /**
47
51
  * Computes the `hermesc` command location. The Algo follows this order:
48
52
  * 1. The path provided by the `hermesCommand` config in the `react` Gradle extension
49
53
  * 2. The file located in `node_modules/react-native/sdks/hermes/build/bin/hermesc`. This will be
50
- * used if the user is building Hermes from source.
54
+ * used if the user is building Hermes from source.
51
55
  * 3. The file located in `node_modules/react-native/sdks/hermesc/%OS-BIN%/hermesc` where `%OS-BIN%`
52
- * is substituted with the correct OS arch. This will be used if the user is using a precompiled
53
- * hermes-engine package.
56
+ * is substituted with the correct OS arch. This will be used if the user is using a precompiled
57
+ * hermes-engine package.
54
58
  * 4. Fails otherwise
55
59
  */
56
60
  internal fun detectedHermesCommand(config: ReactExtension): String =
@@ -59,7 +63,7 @@ internal fun detectedHermesCommand(config: ReactExtension): String =
59
63
  private fun detectEntryFile(
60
64
  entryFile: File?,
61
65
  reactRoot: File,
62
- envVariableOverride: String? = null
66
+ envVariableOverride: String? = null,
63
67
  ): File =
64
68
  when {
65
69
  envVariableOverride != null -> File(reactRoot, envVariableOverride)
@@ -68,7 +72,11 @@ private fun detectEntryFile(
68
72
  else -> File(reactRoot, "index.js")
69
73
  }
70
74
 
71
- private fun detectCliFile(reactNativeRoot: File, preconfiguredCliFile: File?): File {
75
+ private fun detectCliFile(
76
+ project: Project,
77
+ reactNativeRoot: File,
78
+ preconfiguredCliFile: File?,
79
+ ): File {
72
80
  // 1. preconfigured path
73
81
  if (preconfiguredCliFile != null) {
74
82
  if (preconfiguredCliFile.exists()) {
@@ -78,13 +86,12 @@ private fun detectCliFile(reactNativeRoot: File, preconfiguredCliFile: File?): F
78
86
 
79
87
  // 2. node module path
80
88
  val nodeProcess =
81
- Runtime.getRuntime()
82
- .exec(
83
- arrayOf("node", "--print", "require.resolve('react-native/cli');"),
84
- emptyArray(),
85
- reactNativeRoot)
89
+ project.providers.exec { exec ->
90
+ exec.commandLine("node", "--print", "require.resolve('react-native/cli');")
91
+ exec.workingDir(reactNativeRoot)
92
+ }
86
93
 
87
- val nodeProcessOutput = nodeProcess.inputStream.use { it.bufferedReader().readText().trim() }
94
+ val nodeProcessOutput = nodeProcess.standardOutput.asText.get().trim()
88
95
 
89
96
  if (nodeProcessOutput.isNotEmpty()) {
90
97
  val nodeModuleCliJs = File(nodeProcessOutput)
@@ -102,26 +109,31 @@ private fun detectCliFile(reactNativeRoot: File, preconfiguredCliFile: File?): F
102
109
  error(
103
110
  """
104
111
  Couldn't determine CLI location!
105
-
106
- Please set `react { cliFile = file(...) }` inside your
112
+
113
+ Please set `react { cliFile = file(...) }` inside your
107
114
  build.gradle to the path of the react-native cli.js file.
108
115
  This file typically resides in `node_modules/react-native/cli.js`
109
- """
110
- .trimIndent())
116
+ """
117
+ .trimIndent()
118
+ )
111
119
  }
112
120
 
113
121
  /**
114
122
  * Computes the `hermesc` command location. The Algo follows this order:
115
123
  * 1. The path provided by the `hermesCommand` config in the `react` Gradle extension
116
124
  * 2. The file located in `node_modules/react-native/sdks/hermes/build/bin/hermesc`. This will be
117
- * used if the user is building Hermes from source.
125
+ * used if the user is building Hermes from source.
118
126
  * 3. The file located in `node_modules/react-native/sdks/hermesc/%OS-BIN%/hermesc` where `%OS-BIN%`
119
- * is substituted with the correct OS arch. This will be used if the user is using a precompiled
120
- * hermes-engine package.
127
+ * is substituted with the correct OS arch. This will be used if the user is using a precompiled
128
+ * hermes-engine package. Or, if the user has opted in to use Hermes V1, the used file will be
129
+ * located in `node_modules/hermes-compiler/%OS-BIN%/hermesc` where `%OS-BIN%` is substituted
130
+ * with the correct OS arch.
121
131
  * 4. Fails otherwise
122
132
  */
123
- internal fun detectOSAwareHermesCommand(projectRoot: File, hermesCommand: String): String {
124
- // 1. If the project specifies a Hermes command, don't second guess it.
133
+ internal fun detectOSAwareHermesCommand(
134
+ projectRoot: File,
135
+ hermesCommand: String,
136
+ ): String { // 1. If the project specifies a Hermes command, don't second guess it.
125
137
  if (hermesCommand.isNotBlank()) {
126
138
  val osSpecificHermesCommand =
127
139
  if ("%OS-BIN%" in hermesCommand) {
@@ -141,9 +153,9 @@ internal fun detectOSAwareHermesCommand(projectRoot: File, hermesCommand: String
141
153
  return builtHermesc.cliPath(projectRoot)
142
154
  }
143
155
 
144
- // 3. If the react-native contains a pre-built hermesc, use it.
156
+ // 3. Use hermes-compiler from npm
145
157
  val prebuiltHermesPath =
146
- HERMESC_IN_REACT_NATIVE_DIR.plus(getHermesCBin())
158
+ HERMES_COMPILER_NPM_DIR.plus(getHermesCBin())
147
159
  .replace("%OS-BIN%", getHermesOSBin())
148
160
  // Execution on Windows fails with / as separator
149
161
  .replace('/', File.separatorChar)
@@ -156,7 +168,8 @@ internal fun detectOSAwareHermesCommand(projectRoot: File, hermesCommand: String
156
168
  error(
157
169
  "Couldn't determine Hermesc location. " +
158
170
  "Please set `react.hermesCommand` to the path of the hermesc binary file. " +
159
- "node_modules/react-native/sdks/hermesc/%OS-BIN%/hermesc")
171
+ "node_modules/react-native/sdks/hermesc/%OS-BIN%/hermesc"
172
+ )
160
173
  }
161
174
 
162
175
  /**
@@ -182,13 +195,14 @@ internal fun getHermesOSBin(): String {
182
195
  if (Os.isLinuxAmd64()) return "linux64-bin"
183
196
  error(
184
197
  "OS not recognized. Please set project.react.hermesCommand " +
185
- "to the path of a working Hermes compiler.")
198
+ "to the path of a working Hermes compiler."
199
+ )
186
200
  }
187
201
 
188
202
  internal fun projectPathToLibraryName(projectPath: String): String =
189
203
  projectPath
190
204
  .split(':', '-', '_', '.')
191
- .joinToString("") { token -> token.replaceFirstChar { it.uppercase() } }
205
+ .joinToString("") { token -> token.capitalizeCompat() }
192
206
  .plus("Spec")
193
207
 
194
208
  /**
@@ -220,12 +234,12 @@ internal fun findPackageJsonFile(project: Project, rootProperty: DirectoryProper
220
234
  */
221
235
  internal fun readPackageJsonFile(
222
236
  project: Project,
223
- rootProperty: DirectoryProperty
237
+ rootProperty: DirectoryProperty,
224
238
  ): ModelPackageJson? {
225
239
  val packageJson = findPackageJsonFile(project, rootProperty)
226
- return packageJson?.let { JsonUtils.fromCodegenJson(it) }
240
+ return packageJson?.let { JsonUtils.fromPackageJson(it) }
227
241
  }
228
242
 
229
- private const val HERMESC_IN_REACT_NATIVE_DIR = "node_modules/react-native/sdks/hermesc/%OS-BIN%/"
243
+ private const val HERMES_COMPILER_NPM_DIR = "node_modules/hermes-compiler/hermesc/%OS-BIN%/"
230
244
  private const val HERMESC_BUILT_FROM_SOURCE_DIR =
231
245
  "node_modules/react-native/ReactAndroid/hermes-engine/build/hermes/bin/"
@@ -0,0 +1,119 @@
1
+ /*
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ */
7
+
8
+ package com.facebook.react.utils
9
+
10
+ import com.facebook.react.ReactExtension
11
+ import com.facebook.react.model.ModelPackageJson
12
+ import com.facebook.react.utils.KotlinStdlibCompatUtils.lowercaseCompat
13
+ import com.facebook.react.utils.KotlinStdlibCompatUtils.toBooleanStrictOrNullCompat
14
+ import com.facebook.react.utils.PropertyUtils.EDGE_TO_EDGE_ENABLED
15
+ import com.facebook.react.utils.PropertyUtils.HERMES_ENABLED
16
+ import com.facebook.react.utils.PropertyUtils.HERMES_V1_ENABLED
17
+ import com.facebook.react.utils.PropertyUtils.REACT_NATIVE_ARCHITECTURES
18
+ import com.facebook.react.utils.PropertyUtils.SCOPED_EDGE_TO_EDGE_ENABLED
19
+ import com.facebook.react.utils.PropertyUtils.SCOPED_HERMES_ENABLED
20
+ import com.facebook.react.utils.PropertyUtils.SCOPED_HERMES_V1_ENABLED
21
+ import com.facebook.react.utils.PropertyUtils.SCOPED_REACT_NATIVE_ARCHITECTURES
22
+ import com.facebook.react.utils.PropertyUtils.SCOPED_USE_THIRD_PARTY_JSC
23
+ import com.facebook.react.utils.PropertyUtils.USE_THIRD_PARTY_JSC
24
+ import org.gradle.api.Project
25
+ import org.gradle.api.file.DirectoryProperty
26
+ import org.jetbrains.kotlin.gradle.plugin.extraProperties
27
+
28
+ internal object ProjectUtils {
29
+
30
+ const val HERMES_FALLBACK = true
31
+
32
+ const val HERMES_V1_ENABLED_FALLBACK = true
33
+
34
+ internal fun Project.isNewArchEnabled(): Boolean = true
35
+
36
+ internal val Project.isHermesEnabled: Boolean
37
+ get() =
38
+ if (project.hasProperty(HERMES_ENABLED) || project.hasProperty(SCOPED_HERMES_ENABLED)) {
39
+ val propertyString =
40
+ if (project.hasProperty(HERMES_ENABLED)) {
41
+ HERMES_ENABLED
42
+ } else {
43
+ SCOPED_HERMES_ENABLED
44
+ }
45
+ project
46
+ .property(propertyString)
47
+ .toString()
48
+ .lowercaseCompat()
49
+ .toBooleanStrictOrNullCompat() ?: true
50
+ } else if (project.extensions.extraProperties.has("react")) {
51
+ @Suppress("UNCHECKED_CAST")
52
+ val reactMap = project.extensions.extraProperties.get("react") as? Map<String, Any?>
53
+ when (val enableHermesKey = reactMap?.get("enableHermes")) {
54
+ is Boolean -> enableHermesKey
55
+ is String -> enableHermesKey.lowercaseCompat().toBooleanStrictOrNullCompat() ?: true
56
+ else -> HERMES_FALLBACK
57
+ }
58
+ } else {
59
+ HERMES_FALLBACK
60
+ }
61
+
62
+ internal val Project.isEdgeToEdgeEnabled: Boolean
63
+ get() =
64
+ (project.hasProperty(EDGE_TO_EDGE_ENABLED) &&
65
+ project.property(EDGE_TO_EDGE_ENABLED).toString().toBoolean()) ||
66
+ (project.hasProperty(SCOPED_EDGE_TO_EDGE_ENABLED) &&
67
+ project.property(SCOPED_EDGE_TO_EDGE_ENABLED).toString().toBoolean())
68
+
69
+ internal val Project.useThirdPartyJSC: Boolean
70
+ get() =
71
+ (project.hasProperty(USE_THIRD_PARTY_JSC) &&
72
+ project.property(USE_THIRD_PARTY_JSC).toString().toBoolean()) ||
73
+ (project.hasProperty(SCOPED_USE_THIRD_PARTY_JSC) &&
74
+ project.property(SCOPED_USE_THIRD_PARTY_JSC).toString().toBoolean())
75
+
76
+ internal val Project.isHermesV1Enabled: Boolean
77
+ get() =
78
+ if (
79
+ project.hasProperty(HERMES_V1_ENABLED) || project.hasProperty(SCOPED_HERMES_V1_ENABLED)
80
+ ) {
81
+ (project.hasProperty(HERMES_V1_ENABLED) &&
82
+ project.property(HERMES_V1_ENABLED).toString().toBoolean()) ||
83
+ (project.hasProperty(SCOPED_HERMES_V1_ENABLED) &&
84
+ project.property(SCOPED_HERMES_V1_ENABLED).toString().toBoolean()) ||
85
+ (project.extraProperties.has(HERMES_V1_ENABLED) &&
86
+ project.extraProperties.get(HERMES_V1_ENABLED).toString().toBoolean()) ||
87
+ (project.extraProperties.has(SCOPED_HERMES_V1_ENABLED) &&
88
+ project.extraProperties.get(SCOPED_HERMES_V1_ENABLED).toString().toBoolean())
89
+ } else {
90
+ HERMES_V1_ENABLED_FALLBACK
91
+ }
92
+
93
+ internal fun Project.needsCodegenFromPackageJson(rootProperty: DirectoryProperty): Boolean {
94
+ val parsedPackageJson = readPackageJsonFile(this, rootProperty)
95
+ return needsCodegenFromPackageJson(parsedPackageJson)
96
+ }
97
+
98
+ internal fun Project.needsCodegenFromPackageJson(model: ModelPackageJson?): Boolean {
99
+ return model?.codegenConfig != null
100
+ }
101
+
102
+ internal fun Project.getReactNativeArchitectures(): List<String> {
103
+ val architectures = mutableListOf<String>()
104
+ if (project.hasProperty(REACT_NATIVE_ARCHITECTURES)) {
105
+ val architecturesString = project.property(REACT_NATIVE_ARCHITECTURES).toString()
106
+ architectures.addAll(architecturesString.split(",").filter { it.isNotBlank() })
107
+ } else if (project.hasProperty(SCOPED_REACT_NATIVE_ARCHITECTURES)) {
108
+ val architecturesString = project.property(SCOPED_REACT_NATIVE_ARCHITECTURES).toString()
109
+ architectures.addAll(architecturesString.split(",").filter { it.isNotBlank() })
110
+ }
111
+ return architectures
112
+ }
113
+
114
+ internal fun Project.reactNativeDir(extension: ReactExtension): String =
115
+ extension.reactNativeDir.get().asFile.absolutePath
116
+
117
+ internal fun Project.hasPropertySetToFalse(property: String): Boolean =
118
+ this.hasProperty(property) && this.property(property).toString().toBoolean() == false
119
+ }
@@ -0,0 +1,96 @@
1
+ /*
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ */
7
+
8
+ package com.facebook.react.utils
9
+
10
+ /** Collection of all the Gradle Properties that are accepted by React Native Gradle Plugin. */
11
+ object PropertyUtils {
12
+
13
+ /** Public property that toggles the New Architecture */
14
+ const val NEW_ARCH_ENABLED = "newArchEnabled"
15
+ const val SCOPED_NEW_ARCH_ENABLED = "react.newArchEnabled"
16
+
17
+ /** Public property that toggles Hermes */
18
+ const val HERMES_ENABLED = "hermesEnabled"
19
+ const val SCOPED_HERMES_ENABLED = "react.hermesEnabled"
20
+
21
+ /** Public property that toggles Hermes V1 */
22
+ const val HERMES_V1_ENABLED = "hermesV1Enabled"
23
+ const val SCOPED_HERMES_V1_ENABLED = "react.hermesV1Enabled"
24
+
25
+ /** Public property that toggles edge-to-edge */
26
+ const val EDGE_TO_EDGE_ENABLED = "edgeToEdgeEnabled"
27
+ const val SCOPED_EDGE_TO_EDGE_ENABLED = "react.edgeToEdgeEnabled"
28
+
29
+ /** Public property that excludes jsctooling from core */
30
+ const val USE_THIRD_PARTY_JSC = "useThirdPartyJSC"
31
+ const val SCOPED_USE_THIRD_PARTY_JSC = "react.useThirdPartyJSC"
32
+
33
+ /** Public property that allows to control which architectures to build for React Native. */
34
+ const val REACT_NATIVE_ARCHITECTURES = "reactNativeArchitectures"
35
+ const val SCOPED_REACT_NATIVE_ARCHITECTURES = "react.nativeArchitectures"
36
+
37
+ /** Public property that allows to control whether the JitPack repository is included or not */
38
+ const val INCLUDE_JITPACK_REPOSITORY = "includeJitpackRepository"
39
+ const val SCOPED_INCLUDE_JITPACK_REPOSITORY = "react.includeJitpackRepository"
40
+
41
+ /**
42
+ * Public property that allows to configure an enterprise repository proxy as exclusive repository
43
+ */
44
+ const val EXCLUSIVE_ENTEPRISE_REPOSITORY = "exclusiveEnterpriseRepository"
45
+ const val SCOPED_EXCLUSIVE_ENTEPRISE_REPOSITORY = "react.exclusiveEnterpriseRepository"
46
+
47
+ /** By default we include JitPack to avoid breaking user builds */
48
+ internal const val INCLUDE_JITPACK_REPOSITORY_DEFAULT = true
49
+
50
+ /**
51
+ * Internal Property that acts as a killswitch to configure the JDK version and align it for app
52
+ * and all the libraries.
53
+ */
54
+ const val INTERNAL_DISABLE_JAVA_VERSION_ALIGNMENT = "react.internal.disableJavaVersionAlignment"
55
+
56
+ /**
57
+ * Internal Property that allows to specify a local Maven repository to use for React Native
58
+ * artifacts It's used on CI to test templates against a version of React Native built on the fly.
59
+ */
60
+ const val INTERNAL_REACT_NATIVE_MAVEN_LOCAL_REPO = "react.internal.mavenLocalRepo"
61
+
62
+ /**
63
+ * Internal property used to specify where the Windows Bash executable is located. This is useful
64
+ * for contributors who are running Windows on their machine.
65
+ */
66
+ const val INTERNAL_REACT_WINDOWS_BASH = "react.internal.windowsBashPath"
67
+
68
+ /**
69
+ * Controls whether to use Hermes from stable builds. This will force hermes version set in the
70
+ * sdks/hermes-engine/version.properties file to be used. This has a higher priority than
71
+ * react.internal.useHermesNightly.
72
+ */
73
+ const val INTERNAL_USE_HERMES_STABLE = "react.internal.useHermesStable"
74
+
75
+ /**
76
+ * Internal property to force the build to use Hermes from the latest nightly. This speeds up the
77
+ * build at the cost of not testing the latest integration against Hermes.
78
+ */
79
+ const val INTERNAL_USE_HERMES_NIGHTLY = "react.internal.useHermesNightly"
80
+
81
+ /** Internal property used to override the publishing group for the React Native artifacts. */
82
+ const val INTERNAL_REACT_PUBLISHING_GROUP = "react.internal.publishingGroup"
83
+ const val INTERNAL_HERMES_PUBLISHING_GROUP = "react.internal.hermesPublishingGroup"
84
+ const val DEFAULT_INTERNAL_REACT_PUBLISHING_GROUP = "com.facebook.react"
85
+ const val DEFAULT_INTERNAL_HERMES_PUBLISHING_GROUP = "com.facebook.hermes"
86
+
87
+ /** Internal property used to control the version name of React Native */
88
+ const val INTERNAL_VERSION_NAME = "VERSION_NAME"
89
+
90
+ /**
91
+ * Internal properties, shared with iOS, used to control the version name of Hermes Engine. They
92
+ * are stored in sdks/hermes-engine/version.properties
93
+ */
94
+ const val INTERNAL_HERMES_VERSION_NAME = "HERMES_VERSION_NAME"
95
+ const val INTERNAL_HERMES_V1_VERSION_NAME = "HERMES_V1_VERSION_NAME"
96
+ }
@@ -0,0 +1,73 @@
1
+ /*
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ */
7
+
8
+ import org.gradle.api.tasks.testing.logging.TestExceptionFormat
9
+ import org.jetbrains.kotlin.gradle.dsl.JvmTarget
10
+ import org.jetbrains.kotlin.gradle.dsl.KotlinVersion
11
+ import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
12
+
13
+ plugins {
14
+ alias(libs.plugins.kotlin.jvm)
15
+ alias(libs.plugins.ktfmt)
16
+ id("java-gradle-plugin")
17
+ }
18
+
19
+ repositories {
20
+ google()
21
+ mavenCentral()
22
+ }
23
+
24
+ gradlePlugin {
25
+ plugins {
26
+ create("react.settings") {
27
+ id = "com.facebook.react.settings"
28
+ implementationClass = "com.facebook.react.ReactSettingsPlugin"
29
+ }
30
+ }
31
+ }
32
+
33
+ group = "com.facebook.react"
34
+
35
+ dependencies {
36
+ implementation(project(":shared"))
37
+
38
+ implementation(gradleApi())
39
+ implementation(libs.gson)
40
+ implementation(libs.guava)
41
+ implementation(libs.javapoet)
42
+
43
+ testImplementation(libs.junit)
44
+ testImplementation(libs.assertj)
45
+ testImplementation(project(":shared-testutil"))
46
+ }
47
+
48
+ // We intentionally don't build for Java 17 as users will see a cryptic bytecode version
49
+ // error first. Instead we produce a Java 11-compatible Gradle Plugin, so that AGP can print their
50
+ // nice message showing that JDK 11 (or 17) is required first
51
+ java { targetCompatibility = JavaVersion.VERSION_11 }
52
+
53
+ kotlin { jvmToolchain(26) }
54
+
55
+ tasks.withType<KotlinCompile>().configureEach {
56
+ compilerOptions {
57
+ apiVersion.set(KotlinVersion.KOTLIN_1_8)
58
+ // See comment above on JDK 11 support
59
+ jvmTarget.set(JvmTarget.JVM_11)
60
+ allWarningsAsErrors.set(
61
+ project.properties["enableWarningsAsErrors"]?.toString()?.toBoolean() ?: false
62
+ )
63
+ }
64
+ }
65
+
66
+ tasks.withType<Test>().configureEach {
67
+ testLogging {
68
+ exceptionFormat = TestExceptionFormat.FULL
69
+ showExceptions = true
70
+ showCauses = true
71
+ showStackTraces = true
72
+ }
73
+ }