From 0c09e76dfb66d234dcdb5ad50d5882eb42afa946 Mon Sep 17 00:00:00 2001 From: Copilot <223556219+Copilot@users.noreply.github.com> Date: Mon, 11 May 2026 11:35:18 +0200 Subject: [PATCH 1/6] Fix hardcoded ARCore AAR path to honor resolutionStrategy.force The -DARCORE_LIBPATH cmake argument was hardcoded to core-1.22.0.aar in Modules/@babylonjs/react-native/android/build.gradle. If a consumer project applies a resolutionStrategy.force on com.google.ar:core (for example to resolve a duplicate-class conflict between core:1.22.0 and installreferrer:2.2 by forcing core:1.26.0), Gradle extracts the AAR into core-1.26.0.aar/jni while the native build still looks for core-1.22.0.aar/jni, failing with: 'libarcore_sdk_c.so missing and no known rule to make it'. Resolve the actual extracted AAR via configurations.extractLibs and rewrite the -DARCORE_LIBPATH cmake argument to match the resolved version, with a graceful fallback to core-1.22.0.aar if resolution fails. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../react-native/android/build.gradle | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/Modules/@babylonjs/react-native/android/build.gradle b/Modules/@babylonjs/react-native/android/build.gradle index 8296eaeff..7fb5763a0 100644 --- a/Modules/@babylonjs/react-native/android/build.gradle +++ b/Modules/@babylonjs/react-native/android/build.gradle @@ -168,6 +168,12 @@ android { cmake { cppFlags "-fexceptions", "-frtti", "-std=c++1y", "-DONANDROID" abiFilters (*reactNativeArchitectures()) + // NOTE: -DARCORE_LIBPATH below points at the default extracted AAR + // (core-1.22.0.aar). The actual resolved ARCore version may be + // overridden by a consumer's resolutionStrategy.force, so the + // argument is rewritten further down in this script (search for + // "arcoreAarFileName") to point at the AAR that Gradle actually + // extracted. arguments "-DANDROID_STL=c++_shared", "-DGRAPHICS_API=${graphics_api}", "-DREACT_NATIVE_VERSION=${REACT_NATIVE_VERSION}", @@ -388,6 +394,39 @@ def nativeBuildDependsOn(dependsOnTask, variant) { buildTasks.forEach { task -> task.dependsOn(dependsOnTask) } } +// Resolve the actual ARCore AAR name. A consumer project may apply a +// resolutionStrategy.force to com.google.ar:core (e.g. to resolve a conflict +// with installreferrer 2.2 that requires com.google.ar:core 1.26+). Gradle +// extracts the AAR into a folder named after the *resolved* artifact +// (core-.aar), so the native build's -DARCORE_LIBPATH argument must +// match that resolved name rather than the hardcoded 1.22.0 declared above. +def arcoreAarFileName = 'core-1.22.0.aar' +try { + def arcoreAar = configurations.extractLibs.resolvedConfiguration.resolvedArtifacts.find { + it.moduleVersion.id.group == 'com.google.ar' && it.name == 'core' + } + if (arcoreAar != null) { + arcoreAarFileName = "${arcoreAar.name}-${arcoreAar.moduleVersion.id.version}.aar" + } +} catch (Exception e) { + logger.warn("BabylonReactNative: Failed to resolve com.google.ar:core artifact (${e.message}); falling back to ${arcoreAarFileName}") +} +logger.warn("BabylonReactNative: ARCORE AAR: ${arcoreAarFileName}") + +def arcoreLibPathArg = "-DARCORE_LIBPATH=${extractedLibDir}/${arcoreAarFileName}/jni".toString() +def cmakeArgsList = android.defaultConfig.externalNativeBuild.cmake.arguments +def arcoreArgUpdated = false +for (int i = 0; i < cmakeArgsList.size(); i++) { + if (cmakeArgsList.get(i).toString().startsWith("-DARCORE_LIBPATH=")) { + cmakeArgsList.set(i, arcoreLibPathArg) + arcoreArgUpdated = true + break + } +} +if (!arcoreArgUpdated) { + cmakeArgsList.add(arcoreLibPathArg) +} + configurations.extractLibs.files.each { file -> copy { from zipTree(file) From ec610da626f62c4851de97878f85b86b8d6be986 Mon Sep 17 00:00:00 2001 From: Copilot <223556219+Copilot@users.noreply.github.com> Date: Mon, 11 May 2026 11:41:42 +0200 Subject: [PATCH 2/6] Allow consumer to override iOS deployment target for generated Xcode project ios/CMakeLists.txt hardcoded the iOS deployment target to 12 in two places: - set(DEPLOYMENT_TARGET "12" CACHE STRING "") (line 12, consumed by the leetal/ios-cmake toolchain to set CMAKE_OSX_DEPLOYMENT_TARGET) - XCODE_ATTRIBUTE_IPHONEOS_DEPLOYMENT_TARGET 12.0 on the BabylonNative target Xcode 26's Clang crashes compiling DeviceImpl_iOS.mm against iOS 12, so projects targeting iOS 16+ had to patch the deployment target from their Podfile post_install hook. Plumb a new BABYLON_IOS_DEPLOYMENT_TARGET environment variable from postinstall.js into the CMake invocation (as -DDEPLOYMENT_TARGET=) and have CMakeLists.txt honour, in order: an explicit -DDEPLOYMENT_TARGET=, the BABYLON_IOS_DEPLOYMENT_TARGET env var, then the historical 12 default. Both DEPLOYMENT_TARGET and XCODE_ATTRIBUTE_IPHONEOS_DEPLOYMENT_TARGET now use the resolved value, so the generated ReactNativeBabylon.xcodeproj matches the consuming app's Podfile platform :ios setting without manual patching. Documented in README.md alongside BABYLON_NO_CMAKE_POSTINSTALL and BABYLON_USE_SYSTEM_CMAKE. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- Modules/@babylonjs/react-native/README.md | 6 ++++++ .../react-native/ios/CMakeLists.txt | 21 +++++++++++++++++-- .../@babylonjs/react-native/postinstall.js | 15 +++++++++++-- 3 files changed, 38 insertions(+), 4 deletions(-) diff --git a/Modules/@babylonjs/react-native/README.md b/Modules/@babylonjs/react-native/README.md index 95a36e612..f2b9e7bb4 100644 --- a/Modules/@babylonjs/react-native/README.md +++ b/Modules/@babylonjs/react-native/README.md @@ -39,6 +39,12 @@ To use the system cmake (e.g. a Homebrew or system install) instead of the cmake export BABYLON_USE_SYSTEM_CMAKE=1 ``` +To override the iOS deployment target used by the generated `ReactNativeBabylon.xcodeproj` (defaults to `12.0`), set this variable before running `npm install` so it matches your app's Podfile `platform :ios` value: +``` +export BABYLON_IOS_DEPLOYMENT_TARGET=16.0 +``` +This avoids Xcode 26 Clang crashing on `DeviceImpl_iOS.mm` when the iOS 12 default is left in place, and removes the need to patch the deployment target from a Podfile `post_install` hook. + ### Plugins selection Plugins can be disabled at build time. They are all enabled by default and disabling is done with environment variables: diff --git a/Modules/@babylonjs/react-native/ios/CMakeLists.txt b/Modules/@babylonjs/react-native/ios/CMakeLists.txt index f23cc4068..a21be553b 100644 --- a/Modules/@babylonjs/react-native/ios/CMakeLists.txt +++ b/Modules/@babylonjs/react-native/ios/CMakeLists.txt @@ -9,7 +9,24 @@ FetchContent_Declare(ios-cmake FetchContent_MakeAvailable(ios-cmake) set(CMAKE_TOOLCHAIN_FILE "${ios-cmake_SOURCE_DIR}/ios.toolchain.cmake" CACHE PATH "") set(PLATFORM "OS64COMBINED" CACHE STRING "") -set(DEPLOYMENT_TARGET "12" CACHE STRING "") + +# Allow the consuming project to override the iOS deployment target used when +# generating the Xcode project. Resolution order: +# 1. -DDEPLOYMENT_TARGET= on the cmake command line (highest priority) +# 2. BABYLON_IOS_DEPLOYMENT_TARGET environment variable (forwarded by +# postinstall.js so consumers can set it before `npm install`) +# 3. 12.0 (historical default) +# Defaulting to 12 is preserved for backwards compatibility, but iOS 12 is +# known to crash Xcode 26's Clang while compiling DeviceImpl_iOS.mm, so +# projects targeting iOS 16+ should override this to match their Podfile. +if(NOT DEFINED DEPLOYMENT_TARGET OR "${DEPLOYMENT_TARGET}" STREQUAL "") + if(DEFINED ENV{BABYLON_IOS_DEPLOYMENT_TARGET} AND NOT "$ENV{BABYLON_IOS_DEPLOYMENT_TARGET}" STREQUAL "") + set(DEPLOYMENT_TARGET "$ENV{BABYLON_IOS_DEPLOYMENT_TARGET}" CACHE STRING "iOS deployment target") + else() + set(DEPLOYMENT_TARGET "12" CACHE STRING "iOS deployment target") + endif() +endif() +message(STATUS "BabylonReactNative iOS DEPLOYMENT_TARGET: ${DEPLOYMENT_TARGET}") set(ENABLE_ARC OFF CACHE STRING "Enables or disables ARC support.") set(ENABLE_PCH OFF CACHE STRING "Enables or disables precompiled headers.") set(CMAKE_XCODE_GENERATE_SCHEME ON) @@ -91,7 +108,7 @@ target_link_libraries(BabylonNative # TODO: For some reason these don't work, so we specify these in the CMake command line args. set_target_properties(BabylonNative PROPERTIES XCODE_ATTRIBUTE_CLANG_ENABLE_OBJC_ARC NO - XCODE_ATTRIBUTE_IPHONEOS_DEPLOYMENT_TARGET 12.0 + XCODE_ATTRIBUTE_IPHONEOS_DEPLOYMENT_TARGET ${DEPLOYMENT_TARGET} XCODE_ATTRIBUTE_ENABLE_BITCODE YES XCODE_GENERATE_SCHEME ON ) diff --git a/Modules/@babylonjs/react-native/postinstall.js b/Modules/@babylonjs/react-native/postinstall.js index a7da65d08..28cbc4ee4 100644 --- a/Modules/@babylonjs/react-native/postinstall.js +++ b/Modules/@babylonjs/react-native/postinstall.js @@ -24,11 +24,22 @@ function getCmakeExecutable() { function iosCMake() { const { spawn } = require('child_process'); - const cmake = spawn(getCmakeExecutable(), [ + const cmakeArgs = [ '-S', path.join(__dirname, 'ios'), '-B', path.join(__dirname, 'Build/iOS'), '-G', 'Xcode', - ], { stdio: 'inherit', cwd: __dirname }); + ]; + + // Allow the consuming project to override the iOS deployment target used + // when generating the Xcode project. The CMakeLists.txt default is 12.0, + // which is known to crash Xcode 26's Clang when compiling DeviceImpl_iOS.mm, + // so projects targeting iOS 16+ should set this to match their Podfile. + const deploymentTarget = process.env.BABYLON_IOS_DEPLOYMENT_TARGET; + if (deploymentTarget && deploymentTarget.trim() !== '') { + cmakeArgs.push(`-DDEPLOYMENT_TARGET=${deploymentTarget.trim()}`); + } + + const cmake = spawn(getCmakeExecutable(), cmakeArgs, { stdio: 'inherit', cwd: __dirname }); cmake.on('exit', code => { if (code !== 0) { From 6034078d0ebd4c97b56ca582d1584ae407b69b77 Mon Sep 17 00:00:00 2001 From: Copilot <223556219+Copilot@users.noreply.github.com> Date: Mon, 11 May 2026 11:47:02 +0200 Subject: [PATCH 3/6] Bump iOS minimum/default deployment target from 12 to 16 iOS 12 is no longer a viable minimum: Xcode 26's Clang crashes while compiling DeviceImpl_iOS.mm against the iOS 12 SDK, so consumers were forced to override the deployment target via Podfile post_install or via the BABYLON_IOS_DEPLOYMENT_TARGET env var introduced in the previous commit. Bump the default everywhere so unmodified consumer projects work out of the box on Xcode 26+: - ios/CMakeLists.txt: DEPLOYMENT_TARGET default 12 -> 16 (still overridable via -DDEPLOYMENT_TARGET= or BABYLON_IOS_DEPLOYMENT_TARGET). - react-native-babylon.podspec: s.platforms ios 12.0 -> 16.0 so CocoaPods enforces the new minimum on consuming apps. - postinstall.js: update comment to reflect the new default. - README.md: update iOS configuration section and the BABYLON_IOS_DEPLOYMENT_TARGET docs. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- Modules/@babylonjs/react-native/README.md | 6 +++--- Modules/@babylonjs/react-native/ios/CMakeLists.txt | 9 ++++----- Modules/@babylonjs/react-native/postinstall.js | 7 ++++--- .../@babylonjs/react-native/react-native-babylon.podspec | 2 +- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/Modules/@babylonjs/react-native/README.md b/Modules/@babylonjs/react-native/README.md index f2b9e7bb4..adca4f33f 100644 --- a/Modules/@babylonjs/react-native/README.md +++ b/Modules/@babylonjs/react-native/README.md @@ -16,7 +16,7 @@ The minimum Android SDK version is 21. This must be set as `minSdkVersion` in th ### iOS Configuration -The minimum deployment target version is 12. This must be set as `iOS Deployment Target` in the consuming project's `project.pbxproj`, and must also be set as `platform` in the consuming project's `Podfile`. +The minimum deployment target version is 16. This must be set as `iOS Deployment Target` in the consuming project's `project.pbxproj`, and must also be set as `platform` in the consuming project's `Podfile`. Make sure `pod install` is called from the ios folder after npm install. #### Workspace @@ -39,11 +39,11 @@ To use the system cmake (e.g. a Homebrew or system install) instead of the cmake export BABYLON_USE_SYSTEM_CMAKE=1 ``` -To override the iOS deployment target used by the generated `ReactNativeBabylon.xcodeproj` (defaults to `12.0`), set this variable before running `npm install` so it matches your app's Podfile `platform :ios` value: +To override the iOS deployment target used by the generated `ReactNativeBabylon.xcodeproj` (defaults to `16.0`), set this variable before running `npm install` so it matches your app's Podfile `platform :ios` value: ``` export BABYLON_IOS_DEPLOYMENT_TARGET=16.0 ``` -This avoids Xcode 26 Clang crashing on `DeviceImpl_iOS.mm` when the iOS 12 default is left in place, and removes the need to patch the deployment target from a Podfile `post_install` hook. +The previous default of iOS 12 caused Xcode 26's Clang to crash while compiling `DeviceImpl_iOS.mm`; the default is now `16.0` and this variable lets you raise it further (or, at your own risk, lower it) without patching the deployment target from a Podfile `post_install` hook. ### Plugins selection diff --git a/Modules/@babylonjs/react-native/ios/CMakeLists.txt b/Modules/@babylonjs/react-native/ios/CMakeLists.txt index a21be553b..7e3b08cd3 100644 --- a/Modules/@babylonjs/react-native/ios/CMakeLists.txt +++ b/Modules/@babylonjs/react-native/ios/CMakeLists.txt @@ -15,15 +15,14 @@ set(PLATFORM "OS64COMBINED" CACHE STRING "") # 1. -DDEPLOYMENT_TARGET= on the cmake command line (highest priority) # 2. BABYLON_IOS_DEPLOYMENT_TARGET environment variable (forwarded by # postinstall.js so consumers can set it before `npm install`) -# 3. 12.0 (historical default) -# Defaulting to 12 is preserved for backwards compatibility, but iOS 12 is -# known to crash Xcode 26's Clang while compiling DeviceImpl_iOS.mm, so -# projects targeting iOS 16+ should override this to match their Podfile. +# 3. 16.0 (default). iOS 12 used to be the default, but it is known to crash +# Xcode 26's Clang while compiling DeviceImpl_iOS.mm; iOS 16 is now the +# supported minimum. if(NOT DEFINED DEPLOYMENT_TARGET OR "${DEPLOYMENT_TARGET}" STREQUAL "") if(DEFINED ENV{BABYLON_IOS_DEPLOYMENT_TARGET} AND NOT "$ENV{BABYLON_IOS_DEPLOYMENT_TARGET}" STREQUAL "") set(DEPLOYMENT_TARGET "$ENV{BABYLON_IOS_DEPLOYMENT_TARGET}" CACHE STRING "iOS deployment target") else() - set(DEPLOYMENT_TARGET "12" CACHE STRING "iOS deployment target") + set(DEPLOYMENT_TARGET "16" CACHE STRING "iOS deployment target") endif() endif() message(STATUS "BabylonReactNative iOS DEPLOYMENT_TARGET: ${DEPLOYMENT_TARGET}") diff --git a/Modules/@babylonjs/react-native/postinstall.js b/Modules/@babylonjs/react-native/postinstall.js index 28cbc4ee4..8c5591f92 100644 --- a/Modules/@babylonjs/react-native/postinstall.js +++ b/Modules/@babylonjs/react-native/postinstall.js @@ -31,9 +31,10 @@ function iosCMake() { ]; // Allow the consuming project to override the iOS deployment target used - // when generating the Xcode project. The CMakeLists.txt default is 12.0, - // which is known to crash Xcode 26's Clang when compiling DeviceImpl_iOS.mm, - // so projects targeting iOS 16+ should set this to match their Podfile. + // when generating the Xcode project. The CMakeLists.txt default is 16.0 + // (iOS 12 used to be the default but is known to crash Xcode 26's Clang + // when compiling DeviceImpl_iOS.mm); set this if you need a different + // minimum to match your Podfile `platform :ios` value. const deploymentTarget = process.env.BABYLON_IOS_DEPLOYMENT_TARGET; if (deploymentTarget && deploymentTarget.trim() !== '') { cmakeArgs.push(`-DDEPLOYMENT_TARGET=${deploymentTarget.trim()}`); diff --git a/Modules/@babylonjs/react-native/react-native-babylon.podspec b/Modules/@babylonjs/react-native/react-native-babylon.podspec index f18ea17fc..c1e80889d 100644 --- a/Modules/@babylonjs/react-native/react-native-babylon.podspec +++ b/Modules/@babylonjs/react-native/react-native-babylon.podspec @@ -54,7 +54,7 @@ Pod::Spec.new do |s| s.license = package["license"] s.authors = package["author"] - s.platforms = { :ios => "12.0" } + s.platforms = { :ios => "16.0" } s.source = { :git => package["repository"]["url"], :tag => s.version } s.source_files = "ios/*.{h,m,mm}" From 2085b4fb7351f271f04a717e804b61c418a2ecb7 Mon Sep 17 00:00:00 2001 From: Copilot <223556219+Copilot@users.noreply.github.com> Date: Mon, 11 May 2026 11:50:46 +0200 Subject: [PATCH 4/6] Make com.google.ar:core version configurable via ext.arcoreVersion MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Both the implementation and xtractLibs dependency declarations hardcoded com.google.ar:core:1.22.0. In practice this is harmless because Gradle's normal conflict resolution and any consumer-side resolutionStrategy.force on com.google.ar:core override the declared version, but it forced every consumer that wants a newer ARCore (e.g. to resolve the duplicate-class conflict between core:1.22 and installreferrer:2.2 requiring core:1.26+) to add a resolutionStrategy.force AND remember to keep the native build's ARCORE_LIBPATH in sync. Expose the ARCore version as a Gradle ext property using the existing safeExtGet helper, defaulting to 1.22.0 for backwards compatibility: ext.arcoreVersion = '1.26.0' // in the consumer's root build.gradle Use the variable in both implementation and xtractLibs, in the cmake ARCORE_LIBPATH default, and in the dynamic-resolution fallback. The dynamic resolution (added previously) still picks up the actually-extracted AAR when a resolutionStrategy.force overrides the declared version, so both override mechanisms continue to work. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../react-native/android/build.gradle | 39 ++++++++++++------- 1 file changed, 25 insertions(+), 14 deletions(-) diff --git a/Modules/@babylonjs/react-native/android/build.gradle b/Modules/@babylonjs/react-native/android/build.gradle index 7fb5763a0..c48e9b645 100644 --- a/Modules/@babylonjs/react-native/android/build.gradle +++ b/Modules/@babylonjs/react-native/android/build.gradle @@ -66,6 +66,15 @@ def graphics_api = safeExtGet('GRAPHICS_API', "OpenGL") def rootBuildDir = "${rootProject.rootDir}/../Build/Android" def extractedLibDir = "${rootBuildDir}/lib" +// ARCore version. Consumers can override by setting ext.arcoreVersion in their +// root build.gradle (e.g. `ext.arcoreVersion = '1.26.0'` to resolve the +// duplicate-class conflict between com.google.ar:core:1.22 and +// com.android.installreferrer:installreferrer:2.2). A consumer's +// resolutionStrategy.force on com.google.ar:core also wins over this value, +// in which case the dynamic ARCORE_LIBPATH resolution below still picks up +// the actually-extracted AAR. +def arcoreVersion = safeExtGet('arcoreVersion', '1.22.0') + def BABYLON_NATIVE_PLUGIN_NATIVECAMERA = System.getenv("BABYLON_NATIVE_PLUGIN_NATIVECAMERA") != "0" def BABYLON_NATIVE_PLUGIN_NATIVEXR = System.getenv("BABYLON_NATIVE_PLUGIN_NATIVEXR") != "0" @@ -168,16 +177,17 @@ android { cmake { cppFlags "-fexceptions", "-frtti", "-std=c++1y", "-DONANDROID" abiFilters (*reactNativeArchitectures()) - // NOTE: -DARCORE_LIBPATH below points at the default extracted AAR - // (core-1.22.0.aar). The actual resolved ARCore version may be - // overridden by a consumer's resolutionStrategy.force, so the - // argument is rewritten further down in this script (search for - // "arcoreAarFileName") to point at the AAR that Gradle actually - // extracted. + // NOTE: -DARCORE_LIBPATH below points at the AAR matching the + // declared `arcoreVersion` (see top of this file). The actual + // resolved ARCore version may differ (consumer + // resolutionStrategy.force, dependency conflict resolution), + // so the argument is rewritten further down in this script + // (search for "arcoreAarFileName") to point at the AAR that + // Gradle actually extracted. arguments "-DANDROID_STL=c++_shared", "-DGRAPHICS_API=${graphics_api}", "-DREACT_NATIVE_VERSION=${REACT_NATIVE_VERSION}", - "-DARCORE_LIBPATH=${extractedLibDir}/core-1.22.0.aar/jni", + "-DARCORE_LIBPATH=${extractedLibDir}/core-${arcoreVersion}.aar/jni", "-DREACTNATIVE_DIR=${rootDir}/../node_modules/react-native/", "-DBABYLON_NATIVE_PLUGIN_NATIVECAMERA=${BABYLON_NATIVE_PLUGIN_NATIVECAMERA ? '1' : '0'}", "-DBABYLON_NATIVE_PLUGIN_NATIVEXR=${BABYLON_NATIVE_PLUGIN_NATIVEXR ? '1' : '0'}", @@ -292,9 +302,9 @@ repositories { dependencies { //noinspection GradleDynamicVersion implementation 'com.facebook.react:react-native:+' // From node_modules - implementation 'com.google.ar:core:1.22.0' + implementation "com.google.ar:core:${arcoreVersion}" - extractLibs 'com.google.ar:core:1.22.0' + extractLibs "com.google.ar:core:${arcoreVersion}" if (REACT_NATIVE_VERSION < 71) { logger.warn("BabylonReactNative: Extracting files from AAR (pre RN 0.71)") @@ -396,11 +406,12 @@ def nativeBuildDependsOn(dependsOnTask, variant) { // Resolve the actual ARCore AAR name. A consumer project may apply a // resolutionStrategy.force to com.google.ar:core (e.g. to resolve a conflict -// with installreferrer 2.2 that requires com.google.ar:core 1.26+). Gradle -// extracts the AAR into a folder named after the *resolved* artifact -// (core-.aar), so the native build's -DARCORE_LIBPATH argument must -// match that resolved name rather than the hardcoded 1.22.0 declared above. -def arcoreAarFileName = 'core-1.22.0.aar' +// with installreferrer 2.2 that requires com.google.ar:core 1.26+) or +// override `ext.arcoreVersion` (see top of this file). Gradle extracts the +// AAR into a folder named after the *resolved* artifact (core-.aar), +// so the native build's -DARCORE_LIBPATH argument must match that resolved +// name rather than the version literal declared in the dependencies block. +def arcoreAarFileName = "core-${arcoreVersion}.aar" try { def arcoreAar = configurations.extractLibs.resolvedConfiguration.resolvedArtifacts.find { it.moduleVersion.id.group == 'com.google.ar' && it.name == 'core' From 8004b3397432d60acf2116812b2d622b3ec38ee4 Mon Sep 17 00:00:00 2001 From: Copilot <223556219+Copilot@users.noreply.github.com> Date: Mon, 11 May 2026 12:01:29 +0200 Subject: [PATCH 5/6] Slim ARCore AAR resolution to match proposed pattern Drop the defensive scaffolding (try/catch, group filter, manual index loop with not-found fallback, status logger.warn) and use List.replaceAll for the cmake-args mutation. Behaviour is unchanged: still resolves the extractLibs configuration after the dependencies block (necessary because the android { } block evaluates cmake.arguments before the dependencies are declared further down in the script) and rewrites -DARCORE_LIBPATH to match the actually-extracted AAR. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../react-native/android/build.gradle | 43 +++++-------------- 1 file changed, 11 insertions(+), 32 deletions(-) diff --git a/Modules/@babylonjs/react-native/android/build.gradle b/Modules/@babylonjs/react-native/android/build.gradle index c48e9b645..52894ac97 100644 --- a/Modules/@babylonjs/react-native/android/build.gradle +++ b/Modules/@babylonjs/react-native/android/build.gradle @@ -404,38 +404,17 @@ def nativeBuildDependsOn(dependsOnTask, variant) { buildTasks.forEach { task -> task.dependsOn(dependsOnTask) } } -// Resolve the actual ARCore AAR name. A consumer project may apply a -// resolutionStrategy.force to com.google.ar:core (e.g. to resolve a conflict -// with installreferrer 2.2 that requires com.google.ar:core 1.26+) or -// override `ext.arcoreVersion` (see top of this file). Gradle extracts the -// AAR into a folder named after the *resolved* artifact (core-.aar), -// so the native build's -DARCORE_LIBPATH argument must match that resolved -// name rather than the version literal declared in the dependencies block. -def arcoreAarFileName = "core-${arcoreVersion}.aar" -try { - def arcoreAar = configurations.extractLibs.resolvedConfiguration.resolvedArtifacts.find { - it.moduleVersion.id.group == 'com.google.ar' && it.name == 'core' - } - if (arcoreAar != null) { - arcoreAarFileName = "${arcoreAar.name}-${arcoreAar.moduleVersion.id.version}.aar" - } -} catch (Exception e) { - logger.warn("BabylonReactNative: Failed to resolve com.google.ar:core artifact (${e.message}); falling back to ${arcoreAarFileName}") -} -logger.warn("BabylonReactNative: ARCORE AAR: ${arcoreAarFileName}") - -def arcoreLibPathArg = "-DARCORE_LIBPATH=${extractedLibDir}/${arcoreAarFileName}/jni".toString() -def cmakeArgsList = android.defaultConfig.externalNativeBuild.cmake.arguments -def arcoreArgUpdated = false -for (int i = 0; i < cmakeArgsList.size(); i++) { - if (cmakeArgsList.get(i).toString().startsWith("-DARCORE_LIBPATH=")) { - cmakeArgsList.set(i, arcoreLibPathArg) - arcoreArgUpdated = true - break - } -} -if (!arcoreArgUpdated) { - cmakeArgsList.add(arcoreLibPathArg) +// Resolve the actual ARCore AAR name. A consumer project may override +// `ext.arcoreVersion` or apply a resolutionStrategy.force to com.google.ar:core +// (e.g. to resolve a conflict with installreferrer 2.2 that requires +// com.google.ar:core 1.26+). Gradle extracts the AAR into a folder named after +// the *resolved* artifact (core-.aar), so the native build's +// -DARCORE_LIBPATH argument must match that resolved name rather than the +// version literal declared in the dependencies block. +def arcoreAar = configurations.extractLibs.resolvedConfiguration.resolvedArtifacts.find { it.name == 'core' } +def arcoreAarName = arcoreAar ? "${arcoreAar.name}-${arcoreAar.moduleVersion.id.version}.aar" : "core-${arcoreVersion}.aar" +android.defaultConfig.externalNativeBuild.cmake.arguments.replaceAll { + it.toString().startsWith('-DARCORE_LIBPATH=') ? "-DARCORE_LIBPATH=${extractedLibDir}/${arcoreAarName}/jni".toString() : it } configurations.extractLibs.files.each { file -> From 8233c213a679dd3554231e73442bb333d769114c Mon Sep 17 00:00:00 2001 From: Cedric Guillemet <1312968+CedricGuillemet@users.noreply.github.com> Date: Mon, 11 May 2026 12:18:09 +0200 Subject: [PATCH 6/6] Bump Playground iOS deployment target to 16.0 The @babylonjs/react-native podspec declares an iOS 16 minimum (matching the CMake-generated framework's default deployment target). The test app's Podfile relied on react-native-test-app's lower default, which caused 'pod install' to reject the local pod with Specs satisfying the react-native-babylon dependency were found, but they required a higher minimum deployment target.' Set the Podfile's platform explicitly to keep CI's Pods install in sync with the pod's minimum. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- Apps/Playground/ios/Podfile | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Apps/Playground/ios/Podfile b/Apps/Playground/ios/Podfile index eac32f246..65dddb0d0 100644 --- a/Apps/Playground/ios/Podfile +++ b/Apps/Playground/ios/Podfile @@ -1,6 +1,10 @@ require_relative '../node_modules/react-native-test-app/test_app' require_relative '../node_modules/react-native-permissions/scripts/setup' +# Match the @babylonjs/react-native pod's iOS 16 minimum (required for Xcode 26 +# builds, where the CMake-generated framework targets iOS 16 by default). +platform :ios, '16.0' + workspace 'Playground.xcworkspace' # react-native-permissions