diff --git a/packages/react-native-gradle-plugin/src/main/java/com/facebook/react/codegen/plugin/CodegenPlugin.java b/packages/react-native-gradle-plugin/src/main/java/com/facebook/react/codegen/plugin/CodegenPlugin.java index 468098fa256560..26800e283cbcba 100644 --- a/packages/react-native-gradle-plugin/src/main/java/com/facebook/react/codegen/plugin/CodegenPlugin.java +++ b/packages/react-native-gradle-plugin/src/main/java/com/facebook/react/codegen/plugin/CodegenPlugin.java @@ -11,6 +11,7 @@ import com.facebook.react.ReactExtension; import com.facebook.react.codegen.generator.JavaGenerator; import com.facebook.react.tasks.BuildCodegenCLITask; +import com.facebook.react.tasks.GenerateCodegenSchemaTask; import com.facebook.react.utils.GradleUtils; import com.facebook.react.utils.PathUtils; import com.google.common.collect.ImmutableList; @@ -51,45 +52,19 @@ public void apply(final Project project) { task.getBashWindowsHome().set(bashWindowsHome); }); - project - .getTasks() - .register( - "generateCodegenSchemaFromJavaScript", - Exec.class, - task -> { - // This is needed when using codegen from source, not from npm. - task.dependsOn(buildCodegenTask); - - task.doFirst( - s -> { - generatedSrcDir.delete(); - generatedSrcDir.mkdirs(); - }); - - task.getInputs() - .files( - project.fileTree( - ImmutableMap.of("dir", extension.getCodegenDir().getAsFile().get()))); - task.getInputs() - .files( - project.fileTree( - ImmutableMap.of( - "dir", - extension.getJsRootDir().getAsFile().get(), - "includes", - ImmutableList.of("**/*.js")))); - task.getOutputs().file(generatedSchemaFile); - - ImmutableList execCommands = - new ImmutableList.Builder() - .add(os.contains("windows") ? "yarn.cmd" : "yarn") - .addAll(ImmutableList.copyOf(extension.getNodeExecutableAndArgs().get())) - .add(PathUtils.codegenGenerateSchemaCLI(extension).getAbsolutePath()) - .add(generatedSchemaFile.getAbsolutePath()) - .add(extension.getJsRootDir().getAsFile().get().getAbsolutePath()) - .build(); - task.commandLine(execCommands); - }); + TaskProvider generateCodegenSchemaTask = + project + .getTasks() + .register( + "generateCodegenSchemaFromJavaScript", + GenerateCodegenSchemaTask.class, + task -> { + task.getJsRootDir().set(extension.getJsRootDir()); + task.getNodeExecutableAndArgs().set(extension.getNodeExecutableAndArgs()); + task.getCodegenDir().set(extension.getCodegenDir()); + task.getGeneratedSrcDir().set(generatedSrcDir); + task.dependsOn(buildCodegenTask); + }); // 3. Task: generate Java code from schema. project @@ -98,7 +73,7 @@ public void apply(final Project project) { "generateCodegenArtifactsFromSchema", Exec.class, task -> { - task.dependsOn("generateCodegenSchemaFromJavaScript"); + task.dependsOn(generateCodegenSchemaTask); task.getInputs() .files( diff --git a/packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/tasks/GenerateCodegenSchemaTask.kt b/packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/tasks/GenerateCodegenSchemaTask.kt new file mode 100644 index 00000000000000..0c42f7929e83e8 --- /dev/null +++ b/packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/tasks/GenerateCodegenSchemaTask.kt @@ -0,0 +1,56 @@ +/* + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +package com.facebook.react.tasks + +import com.facebook.react.utils.windowsAwareYarn +import org.gradle.api.file.DirectoryProperty +import org.gradle.api.file.RegularFile +import org.gradle.api.provider.ListProperty +import org.gradle.api.provider.Provider +import org.gradle.api.tasks.* + +/** + * A task that will collect all the *.js files inside the provided [jsRootDir] and will run the + * `combine-js-to-schema-cli.js` on top of it (from `react-native-codegen`). The output is a + * `schema.json` file that contains an intermediate representation of the code to be generated. + */ +abstract class GenerateCodegenSchemaTask : Exec() { + + @get:Internal abstract val jsRootDir: DirectoryProperty + + @get:Internal abstract val codegenDir: DirectoryProperty + + @get:Internal abstract val generatedSrcDir: DirectoryProperty + + @get:Input abstract val nodeExecutableAndArgs: ListProperty + + @get:InputFiles val jsInputFiles = project.fileTree(jsRootDir) { it.include("**/*.js") } + + @get:OutputFile + val generatedSchemaFile: Provider = generatedSrcDir.file("schema.json") + + override fun exec() { + generatedSrcDir.asFile.get().apply { + delete() + mkdirs() + } + + commandLine( + windowsAwareYarn( + *nodeExecutableAndArgs.get().toTypedArray(), + codegenDir + .file("lib/cli/combine/combine-js-to-schema-cli.js") + .get() + .asFile + .absolutePath, + generatedSchemaFile.get().asFile.absolutePath, + jsRootDir.asFile.get().absolutePath, + )) + super.exec() + } +} diff --git a/packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/TaskUtils.kt b/packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/TaskUtils.kt index 514d3aac733ffc..dc4f1ac01c8c08 100644 --- a/packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/TaskUtils.kt +++ b/packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/TaskUtils.kt @@ -14,6 +14,13 @@ internal fun windowsAwareCommandLine(vararg args: Any): List = args.toList() } +internal fun windowsAwareYarn(vararg args: Any): List = + if (Os.isWindows()) { + listOf("yarn.cmd") + args + } else { + listOf("yarn") + args + } + internal fun windowsAwareBashCommandLine( vararg args: String, bashWindowsHome: String? = null diff --git a/packages/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/utils/TaskUtilsTest.kt b/packages/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/utils/TaskUtilsTest.kt index 81221c7a06200e..90ac0063189bfd 100644 --- a/packages/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/utils/TaskUtilsTest.kt +++ b/packages/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/utils/TaskUtilsTest.kt @@ -42,6 +42,24 @@ class TaskUtilsTest { assertEquals(listOf("cmd", "/c", "a", "b", "c"), windowsAwareCommandLine("a", "b", "c")) } + @Test + @WithOs(OS.MAC) + fun windowsAwareYarn_onMac_returnsTheList() { + assertEquals(listOf("yarn", "a", "b", "c"), windowsAwareYarn("a", "b", "c")) + } + + @Test + @WithOs(OS.UNIX) + fun windowsAwareYarn_onLinux_returnsTheList() { + assertEquals(listOf("yarn", "a", "b", "c"), windowsAwareYarn("a", "b", "c")) + } + + @Test + @WithOs(OS.WIN) + fun windowsAwareYarn_onWindows_prependsCmd() { + assertEquals(listOf("yarn.cmd", "a", "b", "c"), windowsAwareYarn("a", "b", "c")) + } + @Test @WithOs(OS.MAC) fun windowsAwareBashCommandLine_onMac_returnsTheList() {