-
Notifications
You must be signed in to change notification settings - Fork 68
Description
The Problem
The current build architecture of Babylon React Native is not scalable for multiple (Apple) platforms.
Currently, in the library podspec, we ship a bunch of .a files compiled for iOS.
If we want to support other platforms like macOS we need to compile the static libraries for macOS as well, same thing goes for visionOS.
Here is the podspec of react-native-babylon:
require "json"
package = JSON.parse(File.read(File.join(__dir__, "package.json")))
Pod::Spec.new do |s|
s.name = "react-native-babylon"
s.version = package["version"]
s.summary = package["description"]
s.homepage = package["homepage"]
s.license = package["license"]
s.authors = package["author"]
s.platforms = { :ios => "12.0" }
s.source = { :git => package["repository"]["url"], :tag => s.version }
s.source_files = "ios/**/*.{h,m,mm}"
s.requires_arc = true
s.xcconfig = { 'USER_HEADER_SEARCH_PATHS' => '$(inherited) ${PODS_TARGET_SRCROOT}/shared ${PODS_TARGET_SRCROOT}/../react-native/shared' }
s.vendored_libraries = 'ios/libs/*.a'
s.frameworks = "MetalKit", "ARKit"
s.dependency "React"
endThe Solution
The solution from the Apple ecosystem is to use xcframeworks which are a bundle of .frameworks for multiple platforms. We could create Babylon.xcframework that would contain .frameworks for iOS, macOS and visionOS. On top of that, we could also create a version of the framework without XR support (BabylonBaseKit.xcframework).
Then depending of the build type we could link the correct framework to the project.
This would also fix the issue with linking in the Babylon React Native RNTA example app. Currently, for the example app we generate a new .xcodeproj and add it to the workspace. This solution will work for iOS but not for other platforms, we would need to generate a new .xcodeproj for each platform which is not scalable.
Currently, on post-install we run iosCmake which generates the .xcodeproj:
function iosCMake() {
console.log(chalk.black.bgCyan("Running CMake for iOS..."));
exec("cmake -B ../../Build/iOS -G Xcode", {
cwd: "node_modules/@babylonjs/react-native-iosandroid/ios",
});
}But for additional platforms, we would need to generate a new .xcodeproj for ex for visionOS:
function visionOSCMake() {
console.log(chalk.black.bgCyan("Running CMake for visionOS..."));
exec("cmake -B ../../Build/visionOS -G Xcode VISIONOS=ON", {
cwd: "node_modules/@babylonjs/react-native-iosandroid/ios",
});
}Then we would get duplicated linked projects in the workspace for each platform.
The question is whether linking of the xcodeproj is necessary for your workflow? Do you need to modify the source code of BabylonNative from Babylon React Native? If not we can just link the .xcframework to the project and not the source code.
This is a common practice for libraries that depend on the source code of other libraries.
Another option would be to integrate Babylon Native as a cocoapod which would allow for source code modifications but this would require even bigger changes to the build system.
I think adjusting the CMake scripts of BabylonNative to generate .xcframeworks would be the best solution for now. That would also allow people to use BabylonNative in their projects without the need to link the source code.
Im looking forward to your feedback on this proposal.