Skip to content

Commit 0d36f5e

Browse files
committed
Fix fbjni CMake config for AGP 9.1+
- download and extract fbjni AAR headers for prefab - add fbjni to ReactAndroid's prefab block - update ReactAndroidConfig.cmake to expose fbjni
1 parent bf012fd commit 0d36f5e

1 file changed

Lines changed: 63 additions & 8 deletions

File tree

packages/react-native/ReactAndroid/build.gradle.kts

Lines changed: 63 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ val preparePrefab by
8484
prepareFmt,
8585
prepareFolly,
8686
prepareGlog,
87+
prepareFbjni,
8788
)
8889
dependsOn("generateCodegenArtifactsFromSchema")
8990
// To export to a ReactNativePrefabProcessingEntities.kt once all
@@ -435,6 +436,50 @@ val prepareGlog by
435436
outputDir.set(File(thirdPartyNdkDir, "glog"))
436437
}
437438

439+
val downloadFbjniAarDest = File(downloadsDir, "fbjni-0.7.0.aar")
440+
val downloadFbjniAar by
441+
tasks.registering(Download::class) {
442+
dependsOn(createNativeDepsDirectories)
443+
src("https://repo1.maven.org/maven2/com/facebook/fbjni/fbjni/0.7.0/fbjni-0.7.0.aar")
444+
onlyIfModified(true)
445+
overwrite(false)
446+
retries(5)
447+
quiet(true)
448+
dest(downloadFbjniAarDest)
449+
}
450+
451+
// Extract fbjni headers from AAR for prefab
452+
val prepareFbjni by
453+
tasks.registering {
454+
dependsOn(downloadFbjniAar)
455+
val inputAar = downloadFbjniAarDest
456+
val outputDir = File(prefabHeadersDir, "fbjni")
457+
outputs.dir(outputDir)
458+
doLast {
459+
outputDir.mkdirs()
460+
// Extract only the fbjni headers from the AAR
461+
val zip = java.util.zip.ZipFile(inputAar)
462+
try {
463+
zip.entries().asSequence().filter { it.name.startsWith("prefab/modules/fbjni/include/fbjni/") }
464+
.forEach { entry ->
465+
val destFile = File(outputDir, entry.name.removePrefix("prefab/modules/fbjni/include/"))
466+
destFile.parentFile.mkdirs()
467+
if (entry.isDirectory) {
468+
destFile.mkdirs()
469+
} else {
470+
destFile.outputStream().use { output ->
471+
zip.getInputStream(entry).use { input ->
472+
input.copyTo(output)
473+
}
474+
}
475+
}
476+
}
477+
} finally {
478+
zip.close()
479+
}
480+
}
481+
}
482+
438483
// Tasks used by Fantom to download the Native 3p dependencies used.
439484
val prepareNative3pDependencies by tasks.registering {
440485
dependsOn(
@@ -444,6 +489,7 @@ val prepareNative3pDependencies by tasks.registering {
444489
prepareFmt,
445490
prepareFolly,
446491
prepareGlog,
492+
prepareFbjni,
447493
)
448494
}
449495

@@ -655,6 +701,9 @@ android {
655701
create("jsi") { headers = File(prefabHeadersDir, "jsi").absolutePath }
656702
create("reactnative") { headers = File(prefabHeadersDir, "reactnative").absolutePath }
657703
create("hermestooling") { headers = File(prefabHeadersDir, "hermestooling").absolutePath }
704+
create("fbjni") {
705+
headers = File(prefabHeadersDir, "fbjni").absolutePath
706+
}
658707
}
659708

660709
publishing {
@@ -681,9 +730,9 @@ android {
681730
// Generate CMake config file for find_package support
682731
// This is needed for ReactNative-application.cmake to find ReactAndroid via find_package()
683732
val generateReactAndroidConfig by tasks.registering {
684-
outputs.dir(buildDir.resolve("cmake/ReactAndroid"))
733+
val configDir = buildDir.resolve("cmake/ReactAndroid")
734+
outputs.dir(configDir)
685735
doLast {
686-
val configDir = outputs.files.first()
687736
configDir.mkdirs()
688737
// Convert paths to CMake-style forward slashes to avoid Windows escape sequence issues
689738
val buildDirCmake = buildDir.path.replace("\\", "/")
@@ -713,19 +762,25 @@ android {
713762
INTERFACE_INCLUDE_DIRECTORIES "${buildDirCmake}/prefab-headers/jsi"
714763
)
715764
765+
# The fbjni library - from Gradle dependency's prefab module
766+
add_library(fbjni SHARED IMPORTED)
767+
set_target_properties(fbjni PROPERTIES
768+
IMPORTED_LOCATION "${prefabLibsDir}/fbjni/libs/android.${'$'}{CMAKE_ANDROID_ARCH_ABI}/libfbjni.so"
769+
INTERFACE_INCLUDE_DIRECTORIES "${buildDirCmake}/prefab-headers/fbjni"
770+
)
771+
716772
""".trimIndent()
717773
configDir.resolve("ReactAndroidConfig.cmake").writeText(configContent)
718774
}
719775
}
720776

721777
// Ensure the config file is generated before external native build
722778
// The CMake tasks are created lazily by AGP with names like "configureCMake<Variant>"
723-
// We use withType to find and configure the tasks by name pattern
724-
// Note: tasks.matching is not reliable for lazily created tasks in AGP 9.1+
725-
// Using withType<Task>().configureEach instead
726-
tasks.withType<Task>().configureEach {
727-
if (name.startsWith("configureCMake")) {
728-
dependsOn(generateReactAndroidConfig)
779+
// We use task graph callback to find and configure CMake tasks
780+
// whenTaskAdded registers callbacks for tasks as they are created (handles lazy tasks)
781+
tasks.whenTaskAdded { task ->
782+
if (task.name.startsWith("configureCMake")) {
783+
task.dependsOn(generateReactAndroidConfig)
729784
}
730785
}
731786
}

0 commit comments

Comments
 (0)