BabylonJS / BabylonJS/BabylonReactNative

Proposal: Babylon React Native Build Architecture

Open
#658 11 comments 7 reactions 1 assignee Claimed by @CedricGuillemet View on GitHub
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

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.