@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.
- package/README.md +16 -0
- package/build.gradle.kts +68 -0
- package/gradle/wrapper/gradle-wrapper.jar +0 -0
- package/gradle/wrapper/gradle-wrapper.properties +5 -0
- package/gradlew +234 -0
- package/gradlew.bat +89 -0
- package/package.json +28 -0
- package/settings.gradle.kts +16 -0
- package/src/main/kotlin/com/facebook/react/ReactExtension.kt +151 -0
- package/src/main/kotlin/com/facebook/react/ReactPlugin.kt +163 -0
- package/src/main/kotlin/com/facebook/react/TaskConfiguration.kt +76 -0
- package/src/main/kotlin/com/facebook/react/model/ModelCodegenConfig.kt +15 -0
- package/src/main/kotlin/com/facebook/react/model/ModelCodegenConfigAndroid.kt +10 -0
- package/src/main/kotlin/com/facebook/react/model/ModelPackageJson.kt +10 -0
- package/src/main/kotlin/com/facebook/react/tasks/BuildCodegenCLITask.kt +58 -0
- package/src/main/kotlin/com/facebook/react/tasks/BundleHermesCTask.kt +190 -0
- package/src/main/kotlin/com/facebook/react/tasks/GenerateCodegenArtifactsTask.kt +81 -0
- package/src/main/kotlin/com/facebook/react/tasks/GenerateCodegenSchemaTask.kt +80 -0
- package/src/main/kotlin/com/facebook/react/tasks/internal/PrepareBoostTask.kt +46 -0
- package/src/main/kotlin/com/facebook/react/tasks/internal/PrepareGlogTask.kt +79 -0
- package/src/main/kotlin/com/facebook/react/tasks/internal/PrepareJSCTask.kt +50 -0
- package/src/main/kotlin/com/facebook/react/tasks/internal/PrepareLibeventTask.kt +51 -0
- package/src/main/kotlin/com/facebook/react/tasks/internal/PreparePrefabHeadersTask.kt +62 -0
- package/src/main/kotlin/com/facebook/react/tasks/internal/utils/PrefabPreprocessingEntry.kt +27 -0
- package/src/main/kotlin/com/facebook/react/utils/AgpConfiguratorUtils.kt +54 -0
- package/src/main/kotlin/com/facebook/react/utils/BackwardCompatUtils.kt +48 -0
- package/src/main/kotlin/com/facebook/react/utils/DependencyUtils.kt +89 -0
- package/src/main/kotlin/com/facebook/react/utils/FileUtils.kt +20 -0
- package/src/main/kotlin/com/facebook/react/utils/JsonUtils.kt +21 -0
- package/src/main/kotlin/com/facebook/react/utils/NdkConfiguratorUtils.kt +139 -0
- package/src/main/kotlin/com/facebook/react/utils/Os.kt +31 -0
- package/src/main/kotlin/com/facebook/react/utils/PathUtils.kt +220 -0
- package/src/main/kotlin/com/facebook/react/utils/ProjectUtils.kt +46 -0
- 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
|
+
}
|