Export prepareJSC to an internal task (#32427)
Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/32427 This diff refactors the `prepareJSC` task to a separate Gradle task in the `.internal` package. The reason for this change is that `prepareJSC` was just a plain `Task` and not a `Copy` task. It was defining a top level `doLast` action and would result in being invalidated whenever the `build.gradle` file would change. This means that the JSC headers/source files would have been extracted again, effectively invalidating the timestamps for the native build. Changelog: [Internal] [Changed] - Export prepareJSC to an internal task Reviewed By: ShikaSD Differential Revision: D31682293 fbshipit-source-id: 3d4cd9d9ce2fcd45e61f3c8c6685b69a622a1912
This commit is contained in:
Родитель
52b0cc0355
Коммит
75b2e5cc97
|
@ -161,35 +161,11 @@ final def prepareGlog = tasks.register("prepareGlog", PrepareGlogTask) {
|
|||
}
|
||||
|
||||
// Create Android.mk library module based on jsc from npm
|
||||
task prepareJSC {
|
||||
doLast {
|
||||
def jscPackagePath = findNodeModulePath(projectDir, "jsc-android")
|
||||
if (!jscPackagePath) {
|
||||
throw new GradleScriptException("Could not find the jsc-android npm package", null)
|
||||
}
|
||||
|
||||
def jscDist = file("$jscPackagePath/dist")
|
||||
if (!jscDist.exists()) {
|
||||
throw new GradleScriptException("The jsc-android npm package is missing its \"dist\" directory", null)
|
||||
}
|
||||
|
||||
def jscAAR = fileTree(jscDist).matching({ it.include "**/android-jsc/**/*.aar" }).singleFile
|
||||
def soFiles = zipTree(jscAAR).matching({ it.include "**/*.so" })
|
||||
|
||||
def headerFiles = fileTree(jscDist).matching({ it.include "**/include/*.h" })
|
||||
|
||||
copy {
|
||||
from(soFiles)
|
||||
from(headerFiles)
|
||||
from("src/main/jni/third-party/jsc/Android.mk")
|
||||
|
||||
filesMatching("**/*.h", { it.path = "JavaScriptCore/${it.name}" })
|
||||
|
||||
includeEmptyDirs(false)
|
||||
into("$thirdPartyNdkDir/jsc")
|
||||
}
|
||||
}
|
||||
tasks.register('prepareJSC', PrepareJSCTask) {
|
||||
it.jscPackagePath.set(findNodeModulePath(projectDir, "jsc-android"))
|
||||
it.outputDir = project.layout.buildDirectory.dir("third-party-ndk/jsc")
|
||||
}
|
||||
|
||||
task downloadNdkBuildDependencies {
|
||||
if (!boostPath) {
|
||||
dependsOn(downloadBoost)
|
||||
|
|
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
* 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.internal
|
||||
|
||||
import java.io.File
|
||||
import org.gradle.api.DefaultTask
|
||||
import org.gradle.api.file.DirectoryProperty
|
||||
import org.gradle.api.provider.Property
|
||||
import org.gradle.api.tasks.*
|
||||
|
||||
/**
|
||||
* A task that takes care of unbundling JSC and preparing it for be consumed by the Android NDK.
|
||||
* Specifically it will unbundle shared libs, headers and will copy over the Makefile from
|
||||
* `src/main/jni/third-party/jsc/`
|
||||
*/
|
||||
abstract class PrepareJSCTask : DefaultTask() {
|
||||
|
||||
@get:Input abstract val jscPackagePath: Property<String>
|
||||
|
||||
@get:OutputDirectory abstract val outputDir: DirectoryProperty
|
||||
|
||||
@TaskAction
|
||||
fun taskAction() {
|
||||
if (!jscPackagePath.isPresent || jscPackagePath.orNull == null) {
|
||||
error("Could not find the jsc-android npm package")
|
||||
}
|
||||
val jscDist = File(jscPackagePath.get(), "dist")
|
||||
if (!jscDist.exists()) {
|
||||
error("The jsc-android npm package is missing its \"dist\" directory")
|
||||
}
|
||||
val jscAAR =
|
||||
project.fileTree(jscDist).matching { it.include("**/android-jsc/**/*.aar") }.singleFile
|
||||
val soFiles = project.zipTree(jscAAR).matching { it.include("**/*.so") }
|
||||
val headerFiles = project.fileTree(jscDist).matching { it.include("**/include/*.h") }
|
||||
|
||||
project.copy { it ->
|
||||
it.from(soFiles)
|
||||
it.from(headerFiles)
|
||||
it.from(project.file("src/main/jni/third-party/jsc/Android.mk"))
|
||||
it.filesMatching("**/*.h") { it.path = "JavaScriptCore/${it.name}" }
|
||||
it.includeEmptyDirs = false
|
||||
it.into(outputDir)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,128 @@
|
|||
/*
|
||||
* 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.internal
|
||||
|
||||
import com.facebook.react.tests.createProject
|
||||
import com.facebook.react.tests.createTestTask
|
||||
import com.facebook.react.tests.zipFiles
|
||||
import java.io.*
|
||||
import org.junit.Assert.*
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.junit.rules.TemporaryFolder
|
||||
|
||||
class PrepareJSCTaskTest {
|
||||
|
||||
@get:Rule val tempFolder = TemporaryFolder()
|
||||
|
||||
@Test(expected = IllegalStateException::class)
|
||||
fun prepareJSCTask_withMissingPackage_fails() {
|
||||
val task = createTestTask<PrepareJSCTask>()
|
||||
|
||||
task.taskAction()
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException::class)
|
||||
fun prepareJSCTask_withNullPackage_fails() {
|
||||
val task = createTestTask<PrepareJSCTask> { it.jscPackagePath.set(null as String?) }
|
||||
|
||||
task.taskAction()
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException::class)
|
||||
fun prepareJSCTask_withMissingDistFolder_fails() {
|
||||
val task =
|
||||
createTestTask<PrepareJSCTask> { it.jscPackagePath.set(tempFolder.root.absolutePath) }
|
||||
|
||||
task.taskAction()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun prepareJSCTask_ignoresEmptyDirs() {
|
||||
prepareInputFolder()
|
||||
val output = tempFolder.newFolder("output")
|
||||
File(tempFolder.root, "dist/just/an/empty/folders/").apply { mkdirs() }
|
||||
|
||||
val task =
|
||||
createTestTask<PrepareJSCTask> {
|
||||
it.jscPackagePath.set(tempFolder.root.absolutePath)
|
||||
it.outputDir.set(output)
|
||||
}
|
||||
|
||||
task.taskAction()
|
||||
|
||||
assertFalse(File(output, "just/an/empty/folders/").exists())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun prepareJSCTask_copiesSoFiles() {
|
||||
val soFile = tempFolder.newFile("libsomething.so")
|
||||
prepareInputFolder(aarContent = listOf(soFile))
|
||||
val output = tempFolder.newFolder("output")
|
||||
|
||||
val task =
|
||||
createTestTask<PrepareJSCTask> {
|
||||
it.jscPackagePath.set(tempFolder.root.absolutePath)
|
||||
it.outputDir.set(output)
|
||||
}
|
||||
|
||||
task.taskAction()
|
||||
|
||||
assertEquals("libsomething.so", output.listFiles()?.first()?.name)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun prepareJSCTask_copiesHeaderFilesToCorrectFolder() {
|
||||
prepareInputFolder()
|
||||
File(tempFolder.root, "dist/include/justaheader.h").apply {
|
||||
parentFile.mkdirs()
|
||||
createNewFile()
|
||||
}
|
||||
val output = tempFolder.newFolder("output")
|
||||
|
||||
val task =
|
||||
createTestTask<PrepareJSCTask> {
|
||||
it.jscPackagePath.set(tempFolder.root.absolutePath)
|
||||
it.outputDir.set(output)
|
||||
}
|
||||
|
||||
task.taskAction()
|
||||
|
||||
assertTrue(File(output, "JavaScriptCore/justaheader.h").exists())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun prepareJSCTask_copiesMakefile() {
|
||||
val project = createProject()
|
||||
prepareInputFolder()
|
||||
File(project.projectDir, "src/main/jni/third-party/jsc/Android.mk").apply {
|
||||
parentFile.mkdirs()
|
||||
createNewFile()
|
||||
}
|
||||
val output = tempFolder.newFolder("output")
|
||||
|
||||
val task =
|
||||
createTestTask<PrepareJSCTask>(project = project) {
|
||||
it.jscPackagePath.set(tempFolder.root.absolutePath)
|
||||
it.outputDir.set(output)
|
||||
}
|
||||
|
||||
task.taskAction()
|
||||
|
||||
assertTrue(File(output, "Android.mk").exists())
|
||||
}
|
||||
|
||||
private fun prepareInputFolder(aarContent: List<File> = listOf(tempFolder.newFile())) {
|
||||
val dist = tempFolder.newFolder("dist")
|
||||
File(dist, "android-jsc/android-library.aar").apply {
|
||||
parentFile.mkdirs()
|
||||
createNewFile()
|
||||
}
|
||||
zipFiles(File(dist, "android-jsc/android-library.aar"), aarContent)
|
||||
}
|
||||
}
|
|
@ -7,6 +7,9 @@
|
|||
|
||||
package com.facebook.react.tests
|
||||
|
||||
import java.io.*
|
||||
import java.util.zip.ZipEntry
|
||||
import java.util.zip.ZipOutputStream
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.Task
|
||||
import org.gradle.testfixtures.ProjectBuilder
|
||||
|
@ -23,3 +26,18 @@ internal inline fun <reified T : Task> createTestTask(
|
|||
taskName: String = T::class.java.simpleName,
|
||||
crossinline block: (T) -> Unit = {}
|
||||
): T = project.tasks.register(taskName, T::class.java) { block(it) }.get()
|
||||
|
||||
/** A util function to zip a list of files from [contents] inside the zipfile at [destination]. */
|
||||
internal fun zipFiles(destination: File, contents: List<File>) {
|
||||
ZipOutputStream(BufferedOutputStream(FileOutputStream(destination.absolutePath))).use { out ->
|
||||
for (file in contents) {
|
||||
FileInputStream(file).use { fi ->
|
||||
BufferedInputStream(fi).use { origin ->
|
||||
val entry = ZipEntry(file.name)
|
||||
out.putNextEntry(entry)
|
||||
origin.copyTo(out, 1024)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче