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 26800e283cbcba..28c0eafa71be2a 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 @@ -9,18 +9,13 @@ import com.android.build.gradle.BaseExtension; import com.facebook.react.ReactExtension; -import com.facebook.react.codegen.generator.JavaGenerator; import com.facebook.react.tasks.BuildCodegenCLITask; +import com.facebook.react.tasks.GenerateCodegenArtifactsTask; import com.facebook.react.tasks.GenerateCodegenSchemaTask; import com.facebook.react.utils.GradleUtils; -import com.facebook.react.utils.PathUtils; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; import java.io.File; -import org.gradle.api.GradleException; import org.gradle.api.Project; import org.gradle.api.Task; -import org.gradle.api.tasks.Exec; import org.gradle.api.tasks.TaskProvider; /** @@ -35,10 +30,6 @@ public void apply(final Project project) { // 1. Set up build dir. final File generatedSrcDir = new File(project.getBuildDir(), "generated/source/codegen"); - final File generatedSchemaFile = new File(generatedSrcDir, "schema.json"); - - // 2. Task: produce schema from JS files. - String os = System.getProperty("os.name").toLowerCase(); TaskProvider buildCodegenTask = project @@ -52,6 +43,7 @@ public void apply(final Project project) { task.getBashWindowsHome().set(bashWindowsHome); }); + // 2. Task: produce schema from JS files. TaskProvider generateCodegenSchemaTask = project .getTasks() @@ -67,48 +59,23 @@ public void apply(final Project project) { }); // 3. Task: generate Java code from schema. - project - .getTasks() - .register( - "generateCodegenArtifactsFromSchema", - Exec.class, - task -> { - task.dependsOn(generateCodegenSchemaTask); - - task.getInputs() - .files( - project.fileTree( - ImmutableMap.of("dir", extension.getCodegenDir().getAsFile().get()))); - task.getInputs() - .files(PathUtils.codegenGenerateSchemaCLI(extension).getAbsolutePath()); - task.getInputs().files(generatedSchemaFile); - task.getOutputs().dir(generatedSrcDir); - - if (extension.getUseJavaGenerator().get()) { - task.doLast( - s -> { - generateJavaFromSchemaWithJavaGenerator( - generatedSchemaFile, - extension.getCodegenJavaPackageName().get(), - generatedSrcDir); - }); - } - - ImmutableList execCommands = - new ImmutableList.Builder() - .add(os.contains("windows") ? "yarn.cmd" : "yarn") - .addAll(ImmutableList.copyOf(extension.getNodeExecutableAndArgs().get())) - .add( - PathUtils.codegenGenerateNativeModuleSpecsCLI(extension) - .getAbsolutePath()) - .add("android") - .add(generatedSchemaFile.getAbsolutePath()) - .add(generatedSrcDir.getAbsolutePath()) - .add(extension.getLibraryName().get()) - .add(extension.getCodegenJavaPackageName().get()) - .build(); - task.commandLine(execCommands); - }); + TaskProvider generateCodegenArtifactsTask = + project + .getTasks() + .register( + "generateCodegenArtifactsFromSchema", + GenerateCodegenArtifactsTask.class, + task -> { + task.dependsOn(generateCodegenSchemaTask); + task.getReactRoot().set(extension.getReactRoot()); + task.getJsRootDir().set(extension.getJsRootDir()); + task.getNodeExecutableAndArgs().set(extension.getNodeExecutableAndArgs()); + task.getCodegenDir().set(extension.getCodegenDir()); + task.getUseJavaGenerator().set(extension.getUseJavaGenerator()); + task.getCodegenJavaPackageName().set(extension.getCodegenJavaPackageName()); + task.getLibraryName().set(extension.getLibraryName()); + task.getGeneratedSrcDir().set(generatedSrcDir); + }); // 4. Add dependencies & generated sources to the project. // Note: This last step needs to happen after the project has been evaluated. @@ -118,7 +85,7 @@ public void apply(final Project project) { // This will invoke the codegen before compiling the entire project. Task preBuild = project.getTasks().findByName("preBuild"); if (preBuild != null) { - preBuild.dependsOn("generateCodegenArtifactsFromSchema"); + preBuild.dependsOn(generateCodegenArtifactsTask); } /** @@ -138,16 +105,4 @@ public void apply(final Project project) { .srcDir(new File(generatedSrcDir, "java")); }); } - - // Use Java-based generator implementation to produce the source files, instead of using the - // JS-based generator. - private void generateJavaFromSchemaWithJavaGenerator( - final File schemaFile, final String javaPackageName, final File outputDir) { - final JavaGenerator generator = new JavaGenerator(schemaFile, javaPackageName, outputDir); - try { - generator.build(); - } catch (final Exception ex) { - throw new GradleException("Failed to generate Java from schema.", ex); - } - } } diff --git a/packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/tasks/GenerateCodegenArtifactsTask.kt b/packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/tasks/GenerateCodegenArtifactsTask.kt new file mode 100644 index 00000000000000..971b3ee887a69b --- /dev/null +++ b/packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/tasks/GenerateCodegenArtifactsTask.kt @@ -0,0 +1,76 @@ +/* + * 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.codegen.generator.JavaGenerator +import com.facebook.react.utils.windowsAwareYarn +import org.gradle.api.GradleException +import org.gradle.api.file.Directory +import org.gradle.api.file.DirectoryProperty +import org.gradle.api.file.RegularFile +import org.gradle.api.provider.ListProperty +import org.gradle.api.provider.Property +import org.gradle.api.provider.Provider +import org.gradle.api.tasks.* + +abstract class GenerateCodegenArtifactsTask : Exec() { + + @get:Internal abstract val reactRoot: DirectoryProperty + + @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:Input abstract val useJavaGenerator: Property + + @get:Input abstract val codegenJavaPackageName: Property + + @get:Input abstract val libraryName: Property + + @get:InputFile + val combineJsToSchemaCli: Provider = + codegenDir.file("lib/cli/combine/combine-js-to-schema-cli.js") + + @get:InputFile + val generatedSchemaFile: Provider = generatedSrcDir.file("schema.json") + + @get:OutputDirectory val generatedJavaFiles: Provider = generatedSrcDir.dir("java") + + @get:OutputDirectory val generatedJniFiles: Provider = generatedSrcDir.dir("jni") + + override fun exec() { + commandLine( + windowsAwareYarn( + *nodeExecutableAndArgs.get().toTypedArray(), + reactRoot.file("scripts/generate-specs-cli.js").get().asFile.absolutePath, + "android", + generatedSchemaFile.get().asFile.absolutePath, + generatedSrcDir.get().asFile.absolutePath, + libraryName.get(), + codegenJavaPackageName.get())) + super.exec() + + if (useJavaGenerator.getOrElse(false)) { + // Use Java-based generator implementation to produce the source files, + // instead of using the JS-based generator. + try { + JavaGenerator( + generatedSchemaFile.get().asFile, + codegenJavaPackageName.get(), + generatedSrcDir.get().asFile) + .build() + } catch (e: Exception) { + throw GradleException("Failed to generate Java from schema.", e) + } + } + } +} diff --git a/packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/PathUtils.kt b/packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/PathUtils.kt index d3c318b75b3879..4a215f22fc3fa0 100644 --- a/packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/PathUtils.kt +++ b/packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/PathUtils.kt @@ -122,9 +122,3 @@ internal fun projectPathToLibraryName(projectPath: String): String = .split(':', '-', '_', '.') .joinToString("") { it.capitalize(Locale.ROOT) } .plus("Spec") - -fun codegenGenerateSchemaCLI(config: ReactExtension): File = - config.codegenDir.file("lib/cli/combine/combine-js-to-schema-cli.js").get().asFile - -fun codegenGenerateNativeModuleSpecsCLI(config: ReactExtension): File = - config.reactRoot.file("scripts/generate-specs-cli.js").get().asFile diff --git a/packages/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/tests/PathUtilsTest.kt b/packages/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/tests/PathUtilsTest.kt index 0dbae619df468a..3710eef4af9671 100644 --- a/packages/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/tests/PathUtilsTest.kt +++ b/packages/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/tests/PathUtilsTest.kt @@ -142,30 +142,4 @@ class PathUtilsTest { fun projectPathToLibraryName_withDotsAndUnderscores() { assertEquals("SampleAndroidAppSpec", projectPathToLibraryName("sample_android.app")) } - - @Test - fun codegenGenerateSchemaCLI_worksCorrectly() { - val extension = TestReactExtension(ProjectBuilder.builder().build()) - extension.codegenDir.set(tempFolder.root) - val expected = - File(tempFolder.root, "lib/cli/combine/combine-js-to-schema-cli.js").apply { - parentFile.mkdirs() - createNewFile() - } - - assertEquals(expected, codegenGenerateSchemaCLI(extension)) - } - - @Test - fun codegenGenerateNativeModuleSpecsCLI_worksCorrectly() { - val extension = TestReactExtension(ProjectBuilder.builder().build()) - extension.reactRoot.set(tempFolder.root) - val expected = - File(tempFolder.root, "scripts/generate-specs-cli.js").apply { - parentFile.mkdirs() - createNewFile() - } - - assertEquals(expected, codegenGenerateNativeModuleSpecsCLI(extension)) - } }