BabylonJS / BabylonJS/BabylonReactNative
Proposal: Babylon React Native Build Architecture
- Dominant language
- C++
- Stars
- 432
- Forks
- 72
- Avg merge
- 2d 19h
- Merged PRs (30d)
- 16
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`:
```ruby
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"
end
```
## The 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`:
```js
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:
```js
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.
Contributor guide
Assessment
This issue has not been assessed yet.