diff --git a/packages/gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/tasks/internal/BuildCodegenCLITask.kt b/packages/gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/tasks/internal/BuildCodegenCLITask.kt index ad2d51ed03e4..74eba6527070 100644 --- a/packages/gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/tasks/internal/BuildCodegenCLITask.kt +++ b/packages/gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/tasks/internal/BuildCodegenCLITask.kt @@ -28,6 +28,8 @@ abstract class BuildCodegenCLITask : Exec() { @get:Internal abstract val bashWindowsHome: Property + @get:Internal abstract val rootProjectName: Property + @get:InputFiles abstract val inputFiles: Property @get:OutputFiles abstract val outputFiles: Property @@ -35,6 +37,10 @@ abstract class BuildCodegenCLITask : Exec() { @get:OutputFile abstract val logFile: RegularFileProperty override fun exec() { + // For build from source scenario, we don't need to build the codegen at all. + if (rootProjectName.get() == "react-native-build-from-source") { + return + } val logFileConcrete = logFile.get().asFile.apply { parentFile.mkdirs() diff --git a/packages/gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/tasks/internal/CustomExecTask.kt b/packages/gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/tasks/internal/CustomExecTask.kt new file mode 100644 index 000000000000..ae6d5c108a3a --- /dev/null +++ b/packages/gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/tasks/internal/CustomExecTask.kt @@ -0,0 +1,44 @@ +/* + * Copyright (c) Meta Platforms, Inc. and 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.internal + +import java.io.File +import java.io.FileOutputStream +import org.gradle.api.file.RegularFileProperty +import org.gradle.api.provider.Property +import org.gradle.api.tasks.Exec +import org.gradle.api.tasks.Input +import org.gradle.api.tasks.Optional +import org.gradle.api.tasks.OutputFile + +/** + * A Task that will just expose an Exec-like task and that offers properties to configure the + * standard output and error. + */ +abstract class CustomExecTask : Exec() { + + @get:OutputFile @get:Optional abstract val standardOutputFile: RegularFileProperty + + @get:OutputFile @get:Optional abstract val errorOutputFile: RegularFileProperty + + @get:Input @get:Optional abstract val onlyIfProvidedPathDoesNotExists: Property + + override fun exec() { + if (onlyIfProvidedPathDoesNotExists.isPresent && + File(onlyIfProvidedPathDoesNotExists.get()).exists()) { + return + } + if (standardOutputFile.isPresent) { + standardOutput = FileOutputStream(standardOutputFile.get().asFile) + } + if (errorOutputFile.isPresent) { + errorOutput = FileOutputStream(errorOutputFile.get().asFile) + } + super.exec() + } +} diff --git a/packages/gradle-plugin/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/tasks/internal/CustomExecTaskTest.kt b/packages/gradle-plugin/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/tasks/internal/CustomExecTaskTest.kt new file mode 100644 index 000000000000..c61d5b307c42 --- /dev/null +++ b/packages/gradle-plugin/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/tasks/internal/CustomExecTaskTest.kt @@ -0,0 +1,33 @@ +/* + * Copyright (c) Meta Platforms, Inc. and 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.internal + +import com.facebook.react.tests.createTestTask +import org.assertj.core.api.Assertions.assertThat +import org.junit.Rule +import org.junit.Test +import org.junit.rules.TemporaryFolder + +class CustomExecTaskTest { + + @get:Rule val tempFolder = TemporaryFolder() + + @Test + fun customExec_inputProperties_areSetCorrectly() { + val outFile = tempFolder.newFile("stdout") + val errFile = tempFolder.newFile("stderr") + val task = + createTestTask { task -> + task.errorOutputFile.set(errFile) + task.standardOutputFile.set(outFile) + } + + assertThat(task.errorOutputFile.get().asFile).isEqualTo(errFile) + assertThat(task.standardOutputFile.get().asFile).isEqualTo(outFile) + } +} diff --git a/packages/react-native/ReactAndroid/build.gradle.kts b/packages/react-native/ReactAndroid/build.gradle.kts index 9fa0ea551a45..2f212b635800 100644 --- a/packages/react-native/ReactAndroid/build.gradle.kts +++ b/packages/react-native/ReactAndroid/build.gradle.kts @@ -293,7 +293,7 @@ val prepareDoubleConversion by from(dependenciesPath ?: tarTree(downloadDoubleConversionDest)) from("src/main/jni/third-party/double-conversion/") include("double-conversion-${DOUBLE_CONVERSION_VERSION}/src/**/*", "CMakeLists.txt") - filesMatching("*/src/**/*") { this.path = "double-conversion/${this.name}" } + filesMatching("*/src/**/*") { path = "double-conversion/${name}" } includeEmptyDirs = false into("$thirdPartyNdkDir/double-conversion") } @@ -315,7 +315,7 @@ val prepareFolly by from(dependenciesPath ?: tarTree(downloadFollyDest)) from("src/main/jni/third-party/folly/") include("folly-${FOLLY_VERSION}/folly/**/*", "CMakeLists.txt") - eachFile { this.path = this.path.removePrefix("folly-${FOLLY_VERSION}/") } + eachFile { path = path.substringAfter("/") } includeEmptyDirs = false into("$thirdPartyNdkDir/folly") } @@ -338,7 +338,7 @@ val prepareFastFloat by from(dependenciesPath ?: tarTree(downloadFastFloatDest)) from("src/main/jni/third-party/fast_float/") include("fast_float-${FAST_FLOAT_VERSION}/include/**/*", "CMakeLists.txt") - eachFile { this.path = this.path.removePrefix("fast_float-${FAST_FLOAT_VERSION}/") } + eachFile { path = path.substringAfter("/") } includeEmptyDirs = false into("$thirdPartyNdkDir/fast_float") } @@ -361,7 +361,7 @@ val prepareFmt by from(dependenciesPath ?: tarTree(downloadFmtDest)) from("src/main/jni/third-party/fmt/") include("fmt-${FMT_VERSION}/src/**/*", "fmt-${FMT_VERSION}/include/**/*", "CMakeLists.txt") - eachFile { this.path = this.path.removePrefix("fmt-${FMT_VERSION}/") } + eachFile { path = path.substringAfter("/") } includeEmptyDirs = false into("$thirdPartyNdkDir/fmt") } @@ -394,7 +394,7 @@ val prepareGtest by tasks.registering(Copy::class) { dependsOn(if (dependenciesPath != null) emptyList() else listOf(downloadGtest)) from(dependenciesPath ?: tarTree(downloadGtestDest)) - eachFile { this.path = (this.path.removePrefix("googletest-release-${GTEST_VERSION}/")) } + eachFile { path = path.substringAfter("/") } into(File(thirdPartyNdkDir, "googletest")) } @@ -426,10 +426,7 @@ val buildCodegenCLI by include("lib/**/*.js") include("lib/**/*.js.flow") }) - onlyIf { - // For build from source scenario, we don't need to build the codegen at all. - rootProject.name != "react-native-build-from-source" - } + rootProjectName.set(rootProject.name) } /** diff --git a/packages/react-native/ReactAndroid/hermes-engine/build.gradle.kts b/packages/react-native/ReactAndroid/hermes-engine/build.gradle.kts index bc5a4bdd22dc..9fa746dff892 100644 --- a/packages/react-native/ReactAndroid/hermes-engine/build.gradle.kts +++ b/packages/react-native/ReactAndroid/hermes-engine/build.gradle.kts @@ -5,8 +5,8 @@ * LICENSE file in the root directory of this source tree. */ +import com.facebook.react.tasks.internal.* import de.undercouch.gradle.tasks.download.Download -import java.io.FileOutputStream import org.apache.tools.ant.taskdefs.condition.Os plugins { @@ -124,14 +124,14 @@ val unzipHermes by // the two tasks mentioned before, so we install CMake manually to break the circular dependency. val installCMake by - tasks.registering(Exec::class) { - onlyIf { !File(cmakePath).exists() } + tasks.registering(CustomExecTask::class) { + onlyIfProvidedPathDoesNotExists.set(cmakePath) commandLine( windowsAwareCommandLine(getSDKManagerPath(), "--install", "cmake;${cmakeVersion}")) } val configureBuildForHermes by - tasks.registering(Exec::class) { + tasks.registering(CustomExecTask::class) { dependsOn(installCMake) workingDir(hermesDir) inputs.dir(hermesDir) @@ -149,11 +149,11 @@ val configureBuildForHermes by hermesBuildDir.toString(), "-DJSI_DIR=" + jsiDir.absolutePath, )) - standardOutput = FileOutputStream("$buildDir/configure-hermesc.log") + standardOutputFile.set(project.file("$buildDir/configure-hermesc.log")) } val buildHermesC by - tasks.registering(Exec::class) { + tasks.registering(CustomExecTask::class) { dependsOn(configureBuildForHermes) workingDir(hermesDir) inputs.files(hermesBuildOutputFileTree) @@ -167,8 +167,8 @@ val buildHermesC by "-j", ndkBuildJobs, ) - standardOutput = FileOutputStream("$buildDir/build-hermesc.log") - errorOutput = FileOutputStream("$buildDir/build-hermesc.error.log") + standardOutputFile.set(project.file("$buildDir/build-hermesc.log")) + errorOutputFile.set(project.file("$buildDir/build-hermesc.error.log")) } val prepareHeadersForPrefab by