@react-native/gradle-plugin 0.72.2

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 (34) hide show
  1. package/README.md +16 -0
  2. package/build.gradle.kts +68 -0
  3. package/gradle/wrapper/gradle-wrapper.jar +0 -0
  4. package/gradle/wrapper/gradle-wrapper.properties +5 -0
  5. package/gradlew +234 -0
  6. package/gradlew.bat +89 -0
  7. package/package.json +28 -0
  8. package/settings.gradle.kts +16 -0
  9. package/src/main/kotlin/com/facebook/react/ReactExtension.kt +151 -0
  10. package/src/main/kotlin/com/facebook/react/ReactPlugin.kt +163 -0
  11. package/src/main/kotlin/com/facebook/react/TaskConfiguration.kt +76 -0
  12. package/src/main/kotlin/com/facebook/react/model/ModelCodegenConfig.kt +15 -0
  13. package/src/main/kotlin/com/facebook/react/model/ModelCodegenConfigAndroid.kt +10 -0
  14. package/src/main/kotlin/com/facebook/react/model/ModelPackageJson.kt +10 -0
  15. package/src/main/kotlin/com/facebook/react/tasks/BuildCodegenCLITask.kt +58 -0
  16. package/src/main/kotlin/com/facebook/react/tasks/BundleHermesCTask.kt +190 -0
  17. package/src/main/kotlin/com/facebook/react/tasks/GenerateCodegenArtifactsTask.kt +81 -0
  18. package/src/main/kotlin/com/facebook/react/tasks/GenerateCodegenSchemaTask.kt +80 -0
  19. package/src/main/kotlin/com/facebook/react/tasks/internal/PrepareBoostTask.kt +46 -0
  20. package/src/main/kotlin/com/facebook/react/tasks/internal/PrepareGlogTask.kt +79 -0
  21. package/src/main/kotlin/com/facebook/react/tasks/internal/PrepareJSCTask.kt +50 -0
  22. package/src/main/kotlin/com/facebook/react/tasks/internal/PrepareLibeventTask.kt +51 -0
  23. package/src/main/kotlin/com/facebook/react/tasks/internal/PreparePrefabHeadersTask.kt +62 -0
  24. package/src/main/kotlin/com/facebook/react/tasks/internal/utils/PrefabPreprocessingEntry.kt +27 -0
  25. package/src/main/kotlin/com/facebook/react/utils/AgpConfiguratorUtils.kt +54 -0
  26. package/src/main/kotlin/com/facebook/react/utils/BackwardCompatUtils.kt +48 -0
  27. package/src/main/kotlin/com/facebook/react/utils/DependencyUtils.kt +89 -0
  28. package/src/main/kotlin/com/facebook/react/utils/FileUtils.kt +20 -0
  29. package/src/main/kotlin/com/facebook/react/utils/JsonUtils.kt +21 -0
  30. package/src/main/kotlin/com/facebook/react/utils/NdkConfiguratorUtils.kt +139 -0
  31. package/src/main/kotlin/com/facebook/react/utils/Os.kt +31 -0
  32. package/src/main/kotlin/com/facebook/react/utils/PathUtils.kt +220 -0
  33. package/src/main/kotlin/com/facebook/react/utils/ProjectUtils.kt +46 -0
  34. package/src/main/kotlin/com/facebook/react/utils/TaskUtils.kt +28 -0
@@ -0,0 +1,163 @@
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
9
+
10
+ import com.android.build.api.variant.AndroidComponentsExtension
11
+ import com.android.build.gradle.internal.tasks.factory.dependsOn
12
+ import com.facebook.react.tasks.BuildCodegenCLITask
13
+ import com.facebook.react.tasks.GenerateCodegenArtifactsTask
14
+ import com.facebook.react.tasks.GenerateCodegenSchemaTask
15
+ import com.facebook.react.utils.AgpConfiguratorUtils.configureBuildConfigFields
16
+ import com.facebook.react.utils.AgpConfiguratorUtils.configureDevPorts
17
+ import com.facebook.react.utils.BackwardCompatUtils.configureBackwardCompatibilityReactMap
18
+ import com.facebook.react.utils.DependencyUtils.configureDependencies
19
+ import com.facebook.react.utils.DependencyUtils.configureRepositories
20
+ import com.facebook.react.utils.DependencyUtils.readVersionString
21
+ import com.facebook.react.utils.JsonUtils
22
+ import com.facebook.react.utils.NdkConfiguratorUtils.configureReactNativeNdk
23
+ import com.facebook.react.utils.ProjectUtils.needsCodegenFromPackageJson
24
+ import com.facebook.react.utils.findPackageJsonFile
25
+ import java.io.File
26
+ import kotlin.system.exitProcess
27
+ import org.gradle.api.Plugin
28
+ import org.gradle.api.Project
29
+ import org.gradle.api.Task
30
+ import org.gradle.internal.jvm.Jvm
31
+
32
+ class ReactPlugin : Plugin<Project> {
33
+ override fun apply(project: Project) {
34
+ checkJvmVersion(project)
35
+ val extension = project.extensions.create("react", ReactExtension::class.java, project)
36
+
37
+ // App Only Configuration
38
+ project.pluginManager.withPlugin("com.android.application") {
39
+ project.afterEvaluate {
40
+ val reactNativeDir = extension.reactNativeDir.get().asFile
41
+ val propertiesFile = File(reactNativeDir, "ReactAndroid/gradle.properties")
42
+ val versionString = readVersionString(propertiesFile)
43
+ configureDependencies(project, versionString)
44
+ configureRepositories(project, reactNativeDir)
45
+ }
46
+
47
+ configureReactNativeNdk(project, extension)
48
+ configureBuildConfigFields(project)
49
+ configureDevPorts(project)
50
+ configureBackwardCompatibilityReactMap(project)
51
+
52
+ project.extensions.getByType(AndroidComponentsExtension::class.java).apply {
53
+ onVariants(selector().all()) { variant ->
54
+ project.configureReactTasks(variant = variant, config = extension)
55
+ }
56
+ }
57
+ configureCodegen(project, extension, isLibrary = false)
58
+ }
59
+
60
+ // Library Only Configuration
61
+ project.pluginManager.withPlugin("com.android.library") {
62
+ configureCodegen(project, extension, isLibrary = true)
63
+ }
64
+ }
65
+
66
+ private fun checkJvmVersion(project: Project) {
67
+ val jvmVersion = Jvm.current()?.javaVersion?.majorVersion
68
+ if ((jvmVersion?.toIntOrNull() ?: 0) <= 8) {
69
+ project.logger.error(
70
+ """
71
+
72
+ ********************************************************************************
73
+
74
+ ERROR: requires JDK11 or higher.
75
+ Incompatible major version detected: '$jvmVersion'
76
+
77
+ ********************************************************************************
78
+
79
+ """
80
+ .trimIndent())
81
+ exitProcess(1)
82
+ }
83
+ }
84
+
85
+ /**
86
+ * A plugin to enable react-native-codegen in Gradle environment. See the Gradle API docs for more
87
+ * information: https://docs.gradle.org/current/javadoc/org/gradle/api/Project.html
88
+ */
89
+ @Suppress("UnstableApiUsage")
90
+ private fun configureCodegen(project: Project, extension: ReactExtension, isLibrary: Boolean) {
91
+ // First, we set up the output dir for the codegen.
92
+ val generatedSrcDir = File(project.buildDir, "generated/source/codegen")
93
+
94
+ val buildCodegenTask =
95
+ project.tasks.register("buildCodegenCLI", BuildCodegenCLITask::class.java) {
96
+ it.codegenDir.set(extension.codegenDir)
97
+ val bashWindowsHome = project.findProperty("REACT_WINDOWS_BASH") as String?
98
+ it.bashWindowsHome.set(bashWindowsHome)
99
+
100
+ // Please note that appNeedsCodegen is triggering a read of the package.json at
101
+ // configuration time as we need to feed the onlyIf condition of this task.
102
+ // Therefore, the appNeedsCodegen needs to be invoked inside this lambda.
103
+ val needsCodegenFromPackageJson = project.needsCodegenFromPackageJson(extension)
104
+ it.onlyIf { isLibrary || needsCodegenFromPackageJson }
105
+ }
106
+
107
+ // We create the task to produce schema from JS files.
108
+ val generateCodegenSchemaTask =
109
+ project.tasks.register(
110
+ "generateCodegenSchemaFromJavaScript", GenerateCodegenSchemaTask::class.java) { it ->
111
+ it.dependsOn(buildCodegenTask)
112
+ it.nodeExecutableAndArgs.set(extension.nodeExecutableAndArgs)
113
+ it.codegenDir.set(extension.codegenDir)
114
+ it.generatedSrcDir.set(generatedSrcDir)
115
+
116
+ // We're reading the package.json at configuration time to properly feed
117
+ // the `jsRootDir` @Input property of this task & the onlyIf. Therefore, the
118
+ // parsePackageJson should be invoked inside this lambda.
119
+ val packageJson = findPackageJsonFile(project, extension)
120
+ val parsedPackageJson = packageJson?.let { JsonUtils.fromCodegenJson(it) }
121
+
122
+ val jsSrcsDirInPackageJson = parsedPackageJson?.codegenConfig?.jsSrcsDir
123
+ if (jsSrcsDirInPackageJson != null) {
124
+ it.jsRootDir.set(File(packageJson.parentFile, jsSrcsDirInPackageJson))
125
+ } else {
126
+ it.jsRootDir.set(extension.jsRootDir)
127
+ }
128
+ val needsCodegenFromPackageJson = project.needsCodegenFromPackageJson(extension)
129
+ it.onlyIf { isLibrary || needsCodegenFromPackageJson }
130
+ }
131
+
132
+ // We create the task to generate Java code from schema.
133
+ val generateCodegenArtifactsTask =
134
+ project.tasks.register(
135
+ "generateCodegenArtifactsFromSchema", GenerateCodegenArtifactsTask::class.java) {
136
+ it.dependsOn(generateCodegenSchemaTask)
137
+ it.reactNativeDir.set(extension.reactNativeDir)
138
+ it.nodeExecutableAndArgs.set(extension.nodeExecutableAndArgs)
139
+ it.generatedSrcDir.set(generatedSrcDir)
140
+ it.packageJsonFile.set(findPackageJsonFile(project, extension))
141
+ it.codegenJavaPackageName.set(extension.codegenJavaPackageName)
142
+ it.libraryName.set(extension.libraryName)
143
+
144
+ // Please note that appNeedsCodegen is triggering a read of the package.json at
145
+ // configuration time as we need to feed the onlyIf condition of this task.
146
+ // Therefore, the appNeedsCodegen needs to be invoked inside this lambda.
147
+ val needsCodegenFromPackageJson = project.needsCodegenFromPackageJson(extension)
148
+ it.onlyIf { isLibrary || needsCodegenFromPackageJson }
149
+ }
150
+
151
+ // We update the android configuration to include the generated sources.
152
+ // This equivalent to this DSL:
153
+ //
154
+ // android { sourceSets { main { java { srcDirs += "$generatedSrcDir/java" } } } }
155
+ project.extensions.getByType(AndroidComponentsExtension::class.java).finalizeDsl { ext ->
156
+ ext.sourceSets.getByName("main").java.srcDir(File(generatedSrcDir, "java"))
157
+ }
158
+
159
+ // `preBuild` is one of the base tasks automatically registered by AGP.
160
+ // This will invoke the codegen before compiling the entire project.
161
+ project.tasks.named("preBuild", Task::class.java).dependsOn(generateCodegenArtifactsTask)
162
+ }
163
+ }
@@ -0,0 +1,76 @@
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
9
+
10
+ import com.android.build.api.variant.Variant
11
+ import com.facebook.react.tasks.BundleHermesCTask
12
+ import com.facebook.react.utils.NdkConfiguratorUtils.configureJsEnginePackagingOptions
13
+ import com.facebook.react.utils.NdkConfiguratorUtils.configureNewArchPackagingOptions
14
+ import com.facebook.react.utils.ProjectUtils.isHermesEnabled
15
+ import com.facebook.react.utils.detectedCliFile
16
+ import com.facebook.react.utils.detectedEntryFile
17
+ import java.io.File
18
+ import org.gradle.api.Project
19
+
20
+ @Suppress("SpreadOperator", "UnstableApiUsage")
21
+ internal fun Project.configureReactTasks(variant: Variant, config: ReactExtension) {
22
+ val targetName = variant.name.replaceFirstChar { it.uppercase() }
23
+ val targetPath = variant.name
24
+
25
+ // React js bundle directories
26
+ val resourcesDir = File(buildDir, "generated/res/react/$targetPath")
27
+ // Bundle: generated/assets/react/path/index.android.bundle
28
+ val jsBundleDir = File(buildDir, "generated/assets/react/$targetPath")
29
+ // Sourcemap: generated/sourcemaps/react/path/index.android.bundle.map
30
+ val jsSourceMapsDir = File(buildDir, "generated/sourcemaps/react/$targetPath")
31
+ // Intermediate packager: intermediates/sourcemaps/react/path/index.android.bundle.packager.map
32
+ // Intermediate compiler: intermediates/sourcemaps/react/path/index.android.bundle.compiler.map
33
+ val jsIntermediateSourceMapsDir = File(buildDir, "intermediates/sourcemaps/react/$targetPath")
34
+
35
+ // The location of the cli.js file for React Native
36
+ val cliFile = detectedCliFile(config)
37
+
38
+ val isHermesEnabledInProject = project.isHermesEnabled
39
+ val isHermesEnabledInThisVariant =
40
+ if (config.enableHermesOnlyInVariants.get().isNotEmpty()) {
41
+ config.enableHermesOnlyInVariants.get().contains(variant.name) && isHermesEnabledInProject
42
+ } else {
43
+ isHermesEnabledInProject
44
+ }
45
+ val isDebuggableVariant =
46
+ config.debuggableVariants.get().any { it.equals(variant.name, ignoreCase = true) }
47
+
48
+ configureNewArchPackagingOptions(project, variant)
49
+ configureJsEnginePackagingOptions(config, variant, isHermesEnabledInThisVariant)
50
+
51
+ if (!isDebuggableVariant) {
52
+ val bundleTask =
53
+ tasks.register("createBundle${targetName}JsAndAssets", BundleHermesCTask::class.java) {
54
+ it.root.set(config.root)
55
+ it.nodeExecutableAndArgs.set(config.nodeExecutableAndArgs)
56
+ it.cliFile.set(cliFile)
57
+ it.bundleCommand.set(config.bundleCommand)
58
+ it.entryFile.set(detectedEntryFile(config))
59
+ it.extraPackagerArgs.set(config.extraPackagerArgs)
60
+ it.bundleConfig.set(config.bundleConfig)
61
+ it.bundleAssetName.set(config.bundleAssetName)
62
+ it.jsBundleDir.set(jsBundleDir)
63
+ it.resourcesDir.set(resourcesDir)
64
+ it.hermesEnabled.set(isHermesEnabledInThisVariant)
65
+ it.minifyEnabled.set(!isHermesEnabledInThisVariant)
66
+ it.devEnabled.set(false)
67
+ it.jsIntermediateSourceMapsDir.set(jsIntermediateSourceMapsDir)
68
+ it.jsSourceMapsDir.set(jsSourceMapsDir)
69
+ it.hermesCommand.set(config.hermesCommand)
70
+ it.hermesFlags.set(config.hermesFlags)
71
+ it.reactNativeDir.set(config.reactNativeDir)
72
+ }
73
+ variant.sources.res?.addGeneratedSourceDirectory(bundleTask, BundleHermesCTask::resourcesDir)
74
+ variant.sources.assets?.addGeneratedSourceDirectory(bundleTask, BundleHermesCTask::jsBundleDir)
75
+ }
76
+ }
@@ -0,0 +1,15 @@
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.model
9
+
10
+ data class ModelCodegenConfig(
11
+ val name: String?,
12
+ val type: String?,
13
+ val jsSrcsDir: String?,
14
+ val android: ModelCodegenConfigAndroid?
15
+ )
@@ -0,0 +1,10 @@
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.model
9
+
10
+ data class ModelCodegenConfigAndroid(val javaPackageName: String?)
@@ -0,0 +1,10 @@
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.model
9
+
10
+ data class ModelPackageJson(val codegenConfig: ModelCodegenConfig?)
@@ -0,0 +1,58 @@
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.tasks
9
+
10
+ import com.facebook.react.utils.Os.unixifyPath
11
+ import com.facebook.react.utils.windowsAwareBashCommandLine
12
+ import org.gradle.api.file.DirectoryProperty
13
+ import org.gradle.api.file.FileCollection
14
+ import org.gradle.api.provider.Property
15
+ import org.gradle.api.tasks.*
16
+
17
+ /**
18
+ * A Task that will call the `scripts/oss/build.sh` script to trigger the creation of the codegen
19
+ * lib artifacts.
20
+ *
21
+ * NOTE: This task is required when using react-native-codegen from source, instead of npm.
22
+ */
23
+ abstract class BuildCodegenCLITask : Exec() {
24
+
25
+ @get:Internal abstract val codegenDir: DirectoryProperty
26
+
27
+ @get:Internal abstract val bashWindowsHome: Property<String>
28
+
29
+ @get:InputFiles
30
+ val input: FileCollection by lazy {
31
+ codegenDir.get().files("scripts", "src", "package.json", ".babelrc", ".prettierrc")
32
+ }
33
+
34
+ @get:OutputDirectories
35
+ val output: FileCollection by lazy { codegenDir.get().files("lib", "node_modules") }
36
+
37
+ init {
38
+ // We need this condition as we want a single instance of BuildCodegenCLITask to execute
39
+ // per project. Therefore we can safely skip the task if the lib/cli/ folder is available.
40
+ onlyIf {
41
+ val cliDir = codegenDir.file("lib/cli/").get().asFile
42
+ !cliDir.exists() || cliDir.listFiles()?.size == 0
43
+ }
44
+ }
45
+
46
+ override fun exec() {
47
+ commandLine(
48
+ windowsAwareBashCommandLine(
49
+ codegenDir.asFile.get().canonicalPath.unixifyPath().plus(BUILD_SCRIPT_PATH),
50
+ bashWindowsHome = bashWindowsHome.orNull,
51
+ ))
52
+ super.exec()
53
+ }
54
+
55
+ companion object {
56
+ private const val BUILD_SCRIPT_PATH = "/scripts/oss/build.sh"
57
+ }
58
+ }
@@ -0,0 +1,190 @@
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.tasks
9
+
10
+ import com.facebook.react.utils.detectOSAwareHermesCommand
11
+ import com.facebook.react.utils.moveTo
12
+ import com.facebook.react.utils.windowsAwareCommandLine
13
+ import java.io.File
14
+ import org.gradle.api.DefaultTask
15
+ import org.gradle.api.file.ConfigurableFileTree
16
+ import org.gradle.api.file.DirectoryProperty
17
+ import org.gradle.api.file.RegularFileProperty
18
+ import org.gradle.api.provider.ListProperty
19
+ import org.gradle.api.provider.Property
20
+ import org.gradle.api.tasks.*
21
+
22
+ abstract class BundleHermesCTask : DefaultTask() {
23
+
24
+ init {
25
+ group = "react"
26
+ }
27
+
28
+ @get:Internal abstract val root: DirectoryProperty
29
+
30
+ @get:InputFiles
31
+ val sources: ConfigurableFileTree =
32
+ project.fileTree(root) {
33
+ it.include("**/*.js")
34
+ it.include("**/*.jsx")
35
+ it.include("**/*.ts")
36
+ it.include("**/*.tsx")
37
+ it.exclude("**/android/**/*")
38
+ it.exclude("**/ios/**/*")
39
+ it.exclude("**/build/**/*")
40
+ it.exclude("**/node_modules/**/*")
41
+ }
42
+
43
+ @get:Input abstract val nodeExecutableAndArgs: ListProperty<String>
44
+
45
+ @get:InputFile abstract val cliFile: RegularFileProperty
46
+
47
+ @get:Internal abstract val reactNativeDir: DirectoryProperty
48
+
49
+ @get:Input abstract val bundleCommand: Property<String>
50
+
51
+ @get:InputFile abstract val entryFile: RegularFileProperty
52
+
53
+ @get:InputFile @get:Optional abstract val bundleConfig: RegularFileProperty
54
+
55
+ @get:Input abstract val bundleAssetName: Property<String>
56
+
57
+ @get:Input abstract val minifyEnabled: Property<Boolean>
58
+
59
+ @get:Input abstract val hermesEnabled: Property<Boolean>
60
+
61
+ @get:Input abstract val devEnabled: Property<Boolean>
62
+
63
+ @get:Input abstract val extraPackagerArgs: ListProperty<String>
64
+
65
+ @get:Input abstract val hermesCommand: Property<String>
66
+
67
+ @get:Input abstract val hermesFlags: ListProperty<String>
68
+
69
+ @get:OutputDirectory abstract val jsBundleDir: DirectoryProperty
70
+
71
+ @get:OutputDirectory abstract val resourcesDir: DirectoryProperty
72
+
73
+ @get:OutputDirectory abstract val jsIntermediateSourceMapsDir: RegularFileProperty
74
+
75
+ @get:OutputDirectory abstract val jsSourceMapsDir: DirectoryProperty
76
+
77
+ @TaskAction
78
+ fun run() {
79
+ jsBundleDir.get().asFile.mkdirs()
80
+ resourcesDir.get().asFile.mkdirs()
81
+ jsIntermediateSourceMapsDir.get().asFile.mkdirs()
82
+ jsSourceMapsDir.get().asFile.mkdirs()
83
+ val bundleAssetFilename = bundleAssetName.get()
84
+
85
+ val bundleFile = File(jsBundleDir.get().asFile, bundleAssetFilename)
86
+ val packagerSourceMap = resolvePackagerSourceMapFile(bundleAssetFilename)
87
+
88
+ val bundleCommand = getBundleCommand(bundleFile, packagerSourceMap)
89
+ runCommand(bundleCommand)
90
+
91
+ if (hermesEnabled.get()) {
92
+ val detectedHermesCommand = detectOSAwareHermesCommand(root.get().asFile, hermesCommand.get())
93
+ val bytecodeFile = File("${bundleFile}.hbc")
94
+ val outputSourceMap = resolveOutputSourceMap(bundleAssetFilename)
95
+ val compilerSourceMap = resolveCompilerSourceMap(bundleAssetFilename)
96
+
97
+ val hermesCommand = getHermescCommand(detectedHermesCommand, bytecodeFile, bundleFile)
98
+ runCommand(hermesCommand)
99
+ bytecodeFile.moveTo(bundleFile)
100
+
101
+ if (hermesFlags.get().contains("-output-source-map")) {
102
+ val hermesTempSourceMapFile = File("$bytecodeFile.map")
103
+ hermesTempSourceMapFile.moveTo(compilerSourceMap)
104
+
105
+ val reactNativeDir = reactNativeDir.get().asFile
106
+ val composeScriptFile = File(reactNativeDir, "scripts/compose-source-maps.js")
107
+ val composeSourceMapsCommand =
108
+ getComposeSourceMapsCommand(
109
+ composeScriptFile, packagerSourceMap, compilerSourceMap, outputSourceMap)
110
+ runCommand(composeSourceMapsCommand)
111
+ }
112
+ }
113
+ }
114
+
115
+ internal fun resolvePackagerSourceMapFile(bundleAssetName: String) =
116
+ if (hermesEnabled.get()) {
117
+ File(jsIntermediateSourceMapsDir.get().asFile, "$bundleAssetName.packager.map")
118
+ } else {
119
+ resolveOutputSourceMap(bundleAssetName)
120
+ }
121
+
122
+ internal fun resolveOutputSourceMap(bundleAssetName: String) =
123
+ File(jsSourceMapsDir.get().asFile, "$bundleAssetName.map")
124
+
125
+ internal fun resolveCompilerSourceMap(bundleAssetName: String) =
126
+ File(jsIntermediateSourceMapsDir.get().asFile, "$bundleAssetName.compiler.map")
127
+
128
+ private fun runCommand(command: List<Any>) {
129
+ project.exec {
130
+ it.workingDir(root.get().asFile)
131
+ it.commandLine(command)
132
+ }
133
+ }
134
+
135
+ internal fun getBundleCommand(bundleFile: File, sourceMapFile: File): List<Any> =
136
+ windowsAwareCommandLine(
137
+ buildList {
138
+ addAll(nodeExecutableAndArgs.get())
139
+ add(cliFile.get().asFile.absolutePath)
140
+ add(bundleCommand.get())
141
+ add("--platform")
142
+ add("android")
143
+ add("--dev")
144
+ add(devEnabled.get().toString())
145
+ add("--reset-cache")
146
+ add("--entry-file")
147
+ add(entryFile.get().asFile.toString())
148
+ add("--bundle-output")
149
+ add(bundleFile.toString())
150
+ add("--assets-dest")
151
+ add(resourcesDir.get().asFile.toString())
152
+ add("--sourcemap-output")
153
+ add(sourceMapFile.toString())
154
+ if (bundleConfig.isPresent) {
155
+ add("--config")
156
+ add(bundleConfig.get().asFile.absolutePath)
157
+ }
158
+ add("--minify")
159
+ add(minifyEnabled.get().toString())
160
+ addAll(extraPackagerArgs.get())
161
+ add("--verbose")
162
+ })
163
+
164
+ internal fun getHermescCommand(
165
+ hermesCommand: String,
166
+ bytecodeFile: File,
167
+ bundleFile: File
168
+ ): List<Any> =
169
+ windowsAwareCommandLine(
170
+ hermesCommand,
171
+ "-emit-binary",
172
+ "-out",
173
+ bytecodeFile.absolutePath,
174
+ bundleFile.absolutePath,
175
+ *hermesFlags.get().toTypedArray())
176
+
177
+ internal fun getComposeSourceMapsCommand(
178
+ composeScript: File,
179
+ packagerSourceMap: File,
180
+ compilerSourceMap: File,
181
+ outputSourceMap: File
182
+ ): List<Any> =
183
+ windowsAwareCommandLine(
184
+ *nodeExecutableAndArgs.get().toTypedArray(),
185
+ composeScript.absolutePath,
186
+ packagerSourceMap.toString(),
187
+ compilerSourceMap.toString(),
188
+ "-o",
189
+ outputSourceMap.toString())
190
+ }
@@ -0,0 +1,81 @@
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.tasks
9
+
10
+ import com.facebook.react.utils.JsonUtils
11
+ import com.facebook.react.utils.windowsAwareCommandLine
12
+ import org.gradle.api.file.Directory
13
+ import org.gradle.api.file.DirectoryProperty
14
+ import org.gradle.api.file.RegularFile
15
+ import org.gradle.api.file.RegularFileProperty
16
+ import org.gradle.api.provider.ListProperty
17
+ import org.gradle.api.provider.Property
18
+ import org.gradle.api.provider.Provider
19
+ import org.gradle.api.tasks.Exec
20
+ import org.gradle.api.tasks.Input
21
+ import org.gradle.api.tasks.InputFile
22
+ import org.gradle.api.tasks.Internal
23
+ import org.gradle.api.tasks.OutputDirectory
24
+
25
+ abstract class GenerateCodegenArtifactsTask : Exec() {
26
+
27
+ @get:Internal abstract val reactNativeDir: DirectoryProperty
28
+
29
+ @get:Internal abstract val generatedSrcDir: DirectoryProperty
30
+
31
+ @get:InputFile abstract val packageJsonFile: RegularFileProperty
32
+
33
+ @get:Input abstract val nodeExecutableAndArgs: ListProperty<String>
34
+
35
+ @get:Input abstract val codegenJavaPackageName: Property<String>
36
+
37
+ @get:Input abstract val libraryName: Property<String>
38
+
39
+ @get:InputFile
40
+ val generatedSchemaFile: Provider<RegularFile> = generatedSrcDir.file("schema.json")
41
+
42
+ @get:OutputDirectory val generatedJavaFiles: Provider<Directory> = generatedSrcDir.dir("java")
43
+
44
+ @get:OutputDirectory val generatedJniFiles: Provider<Directory> = generatedSrcDir.dir("jni")
45
+
46
+ override fun exec() {
47
+ val (resolvedLibraryName, resolvedCodegenJavaPackageName) = resolveTaskParameters()
48
+ setupCommandLine(resolvedLibraryName, resolvedCodegenJavaPackageName)
49
+ super.exec()
50
+ }
51
+
52
+ internal fun resolveTaskParameters(): Pair<String, String> {
53
+ val parsedPackageJson =
54
+ if (packageJsonFile.isPresent && packageJsonFile.get().asFile.exists()) {
55
+ JsonUtils.fromCodegenJson(packageJsonFile.get().asFile)
56
+ } else {
57
+ null
58
+ }
59
+ val resolvedLibraryName = parsedPackageJson?.codegenConfig?.name ?: libraryName.get()
60
+ val resolvedCodegenJavaPackageName =
61
+ parsedPackageJson?.codegenConfig?.android?.javaPackageName ?: codegenJavaPackageName.get()
62
+ return resolvedLibraryName to resolvedCodegenJavaPackageName
63
+ }
64
+
65
+ internal fun setupCommandLine(libraryName: String, codegenJavaPackageName: String) {
66
+ commandLine(
67
+ windowsAwareCommandLine(
68
+ *nodeExecutableAndArgs.get().toTypedArray(),
69
+ reactNativeDir.file("scripts/generate-specs-cli.js").get().asFile.absolutePath,
70
+ "--platform",
71
+ "android",
72
+ "--schemaPath",
73
+ generatedSchemaFile.get().asFile.absolutePath,
74
+ "--outputDir",
75
+ generatedSrcDir.get().asFile.absolutePath,
76
+ "--libraryName",
77
+ libraryName,
78
+ "--javaPackageName",
79
+ codegenJavaPackageName))
80
+ }
81
+ }
@@ -0,0 +1,80 @@
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.tasks
9
+
10
+ import com.facebook.react.utils.windowsAwareCommandLine
11
+ import org.gradle.api.file.DirectoryProperty
12
+ import org.gradle.api.file.RegularFile
13
+ import org.gradle.api.provider.ListProperty
14
+ import org.gradle.api.provider.Provider
15
+ import org.gradle.api.tasks.*
16
+
17
+ /**
18
+ * A task that will collect all the *.js files inside the provided [jsRootDir] and will run the
19
+ * `combine-js-to-schema-cli.js` on top of it (from `react-native-codegen`). The output is a
20
+ * `schema.json` file that contains an intermediate representation of the code to be generated.
21
+ */
22
+ abstract class GenerateCodegenSchemaTask : Exec() {
23
+
24
+ @get:Internal abstract val jsRootDir: DirectoryProperty
25
+
26
+ @get:Internal abstract val codegenDir: DirectoryProperty
27
+
28
+ @get:Internal abstract val generatedSrcDir: DirectoryProperty
29
+
30
+ @get:Input abstract val nodeExecutableAndArgs: ListProperty<String>
31
+
32
+ @get:InputFiles
33
+ val jsInputFiles =
34
+ project.fileTree(jsRootDir) {
35
+ it.include("**/*.js")
36
+ it.include("**/*.ts")
37
+ // Those are known build paths where the source map or other
38
+ // .js files could be stored/generated. We want to make sure we don't pick them up
39
+ // for execution avoidance.
40
+ it.exclude("**/generated/source/codegen/**/*")
41
+ it.exclude("**/build/ASSETS/**/*")
42
+ it.exclude("**/build/RES/**/*")
43
+ it.exclude("**/build/generated/assets/react/**/*")
44
+ it.exclude("**/build/generated/res/react/**/*")
45
+ it.exclude("**/build/generated/sourcemaps/react/**/*")
46
+ it.exclude("**/build/intermediates/sourcemaps/react/**/*")
47
+ }
48
+
49
+ @get:OutputFile
50
+ val generatedSchemaFile: Provider<RegularFile> = generatedSrcDir.file("schema.json")
51
+
52
+ override fun exec() {
53
+ wipeOutputDir()
54
+ setupCommandLine()
55
+ super.exec()
56
+ }
57
+
58
+ internal fun wipeOutputDir() {
59
+ generatedSrcDir.asFile.get().apply {
60
+ deleteRecursively()
61
+ mkdirs()
62
+ }
63
+ }
64
+
65
+ internal fun setupCommandLine() {
66
+ commandLine(
67
+ windowsAwareCommandLine(
68
+ *nodeExecutableAndArgs.get().toTypedArray(),
69
+ codegenDir
70
+ .file("lib/cli/combine/combine-js-to-schema-cli.js")
71
+ .get()
72
+ .asFile
73
+ .absolutePath,
74
+ "--platform",
75
+ "android",
76
+ generatedSchemaFile.get().asFile.absolutePath,
77
+ jsRootDir.asFile.get().absolutePath,
78
+ ))
79
+ }
80
+ }