Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RJS-2101: "Build optimizations" for iOS and Android #6650

Draft
wants to merge 65 commits into
base: main
Choose a base branch
from

Conversation

kraenhansen
Copy link
Member

@kraenhansen kraenhansen commented May 3, 2024

What, How & Why?

Important

With this change, our SDK is no longer pinned to a specific ABI of JSI and we expect the next release of our SDK (after merging this PR) to be backwards and forwards compatible with many past versions of React Native.

This is my friendly takeover of #6396, by reverting the compilation of Realm Core from source and instead distributing prebuilds via our NPM package:

  • For React Native Apple (npm run prebuild-apple --workspace realm):
    • Prebuild format is an XCFramework of Realm Core
    • Deferred compilation on the developers machine is our binding (between Realm Core and React Native Core & JSI) driven by CocoaPods & XCode.
  • For React Native Android (npm run prebuild-android --workspace realm):
    • Prebuilds format is a CPack install directory (containing CMake config files)
    • Deferred compilation on the developers machine is our binding (between Realm Core and React Native Core & JSI) driven by Gradle calling into CMake.
  • For Node.js we're able to rely on the ABI stability of N-API and we produce prebuilds containing both Realm Core and our binding (between Realm Core and N-API) (npm run prebuild-node --workspace realm).

This also moves all binding related code (prebuilt or not), including that previously in packages/realm/react-native into packages/realm/binding in platform specific directories.

We won't support compiling our prebuilds from from the NPM archive as users still need to git clone our mono-repository to produce a build from source.

It's worth mentioning that this PR introduce an internal CLI incapsulating the complexity of invoking the CMake scripts for Android and Apple platforms. I imagine we could extend this to wrap cmake-js to provide a single cohesive experience for building our prebuilds in the future: This is a replacement for the packages/realm/scripts for Android and iOS that we currently use.


Here's a bit more context on this change and why we choose the approach we did:

As we started implementing out "React Native SDK Build Optimizations" project we realized a few things:

  • Although we are generating 11K lines of C++ from the binding generator, it’s very fast to compile - most likely because it’s a single translation unit.
  • This generated binding layer is the only code dependent on the React Native headers / ABI.
  • We need Cmake to generate the Xcode project to compile Realm Core, which might not be installed on an app developers machine (in the correct version) but we can compile the binding layer without it.
  • If we choose to leave out the binding layer from the prebuilt binary (and we can because of ☝️) we don’t need to produce separate prebuilds for each React Native version.
  • Because of ☝️ we actually don’t have to delay the download of the prebuilt until “pod install” nor build-time. We could actually include it as an xcframework into the archive that we upload to NPM, like we do now. The main drawback of this approach is the download time for users as they “npm install” our package, but that won’t be a regression in DX to what we currently have and it doesn’t seem to be a deal-breaker to anyone as-is.
  • For Android, the situation is slightly more complicated, since Realm Core is dependent on ABI of the C++ Standard Library brought in by the NDK. Since the NDK version is configurable by the developer, this becomes a bit more complicated. Luckily the React Native template app (and Expo) declares a default for this NDK version, which we could rely on for the prebuild we upload to NPM, as long as we take great care to error if developers try using this prebuild with an unexpected NDK version and provide an easy way to build Realm Core from source, for those developers choosing a different NDK than the default.

In the context of the above, if we choose to include prebuild binaries for iOS and Android of Realm Core in the NPM package, which will be ABI independent on the React Native version (except for the caveat of NDK version, which has a default that I'd expect 95+% to leave unchanged) ... do we actually need to support compiling from source when installing the realm package via NPM as the original project scope suggests? I'd expect the need for that to be very rare (as it is right now) and it does come with drawbacks:

  • We'll have to avoid hoisting shared dev-dependencies to the root package of our mono-repo
  • Depending on a decision of forcing developers that wants to use this to have to npm install in their node_modules/realm we might need to include these dev-dependencies as actual dependencies of realm. Which would add to the install time of our package.
  • We'll most likely have to run tests to ensure all relevant dependencies are actually available to build from source when the realm package is installed outside of the mono-repo.
  • We'll have to include all of the Realm Core source-code into the repository, not a huge deal - but it all adds up.

The alternative is to ask developers that want to consume Realm JS and Realm Core from source to perform a checkout of the repository, run the relevant build script and npm pack the SDK package themselves.

☑️ ToDos

  • 📝 Changelog entry
  • Include before / after size of the NPM package.
  • 📝 Compatibility label is updated or copied from previous entry
  • 📝 Update COMPATIBILITY.md
  • 🚦 Tests
  • 📦 Updated internal package version in consuming package.jsons (if updating internal packages)
  • 📱 Check the React Native/other sample apps work if necessary
  • 💥 Breaking label has been applied or is not necessary

@kraenhansen kraenhansen self-assigned this May 3, 2024
@cla-bot cla-bot bot added the cla: yes label May 3, 2024
@kraenhansen kraenhansen force-pushed the kh/build-optimizations-squashed branch 2 times, most recently from e0482ca to 0b3a7e7 Compare May 3, 2024 12:22
@kraenhansen kraenhansen force-pushed the kh/build-optimizations-squashed branch 4 times, most recently from 23d87f0 to 973e0ad Compare May 23, 2024 12:00
commit 17e1661
Author: Andrew Meyer <[email protected]>
Date:   Tue Feb 6 13:18:02 2024 +0000

    Lint the shell script

commit 78b3ae7
Author: Andrew Meyer <[email protected]>
Date:   Mon Feb 5 11:49:56 2024 +0000

    Add all scripts to the package

commit e334dca
Author: Andrew Meyer <[email protected]>
Date:   Sun Feb 4 15:20:20 2024 +0100

    Fix potential release issues

commit fa5a982
Author: Andrew Meyer <[email protected]>
Date:   Sun Feb 4 15:16:21 2024 +0100

    Refactor integration tests jsi dep

commit efab94a
Author: Andrew Meyer <[email protected]>
Date:   Sun Feb 4 15:13:58 2024 +0100

    Revert wireit action change

commit 49d87c6
Author: Andrew Meyer <[email protected]>
Date:   Sun Feb 4 15:11:22 2024 +0100

    Add CHANGELOG entry

commit 1a92fb4
Author: Andrew Meyer <[email protected]>
Date:   Sun Feb 4 13:58:41 2024 +0100

    PR suggestions, etc

    * Rename generate script
    * Various Cleanup
    * Fix up the dependencies for the integration tests

commit 6cd3b15
Author: Andrew Meyer <[email protected]>
Date:   Sun Feb 4 13:47:49 2024 +0100

    Apply suggestions from code review

    Co-authored-by: Kræn Hansen <[email protected]>
    Co-authored-by: Kenneth Geisshirt <[email protected]>
    Co-authored-by: LJ <[email protected]>

commit 89c5c0f
Author: Andrew Meyer <[email protected]>
Date:   Sun Feb 4 13:40:18 2024 +0100

    Refactor Android builds for React Native (#6400)

    * Build Realm Android from Source

    * Derive React Native version from local RN package

    * Implement prefab to handle react native dependencies.  Refactor where possible

    * Refactor CI for Android

    * Fix pack issues

    * Possible ios cache issue

    * Fixed issue where build starts before ts is generated

    * disable wireit cache

    * refactor wireit cache and optimize workflow

    * Cleanup packagin

commit 8e01fbf
Author: Andrew Meyer <[email protected]>
Date:   Wed Jan 31 15:37:16 2024 +0100

    Revert upgrade to upload-artifact

commit 7477a81
Author: Andrew Meyer <[email protected]>
Date:   Wed Jan 31 14:41:10 2024 +0100

    Add cache for pod-install:ci

commit 8379c28
Author: Andrew Meyer <[email protected]>
Date:   Mon Jan 29 14:52:07 2024 +0100

    Attempt to fix CI
    Update node16 actions
    Refactor bundle step into generate artifact step

commit 58d62ff
Author: Andrew Meyer <[email protected]>
Date:   Mon Jan 29 14:47:53 2024 +0100

    PR feedback

commit 91e3a5f
Author: Andrew Meyer <[email protected]>
Date:   Mon Jan 29 14:45:22 2024 +0100

    Apply suggestions from code review

    Co-authored-by: LJ <[email protected]>
    Co-authored-by: Kræn Hansen <[email protected]>

commit cb4df32
Author: Andrew Meyer <[email protected]>
Date:   Mon Jan 29 14:44:31 2024 +0100

    Incorporate PR feedback

commit 43f7670
Author: Andrew Meyer <[email protected]>
Date:   Thu Jan 25 13:34:38 2024 +0100

    Fixes after review

commit c7ccfcf
Author: Andrew Meyer <[email protected]>
Date:   Thu Jan 25 11:05:43 2024 +0100

    Cleanup

commit 9e3d7c0
Author: Andrew Meyer <[email protected]>
Date:   Thu Jan 25 10:52:56 2024 +0100

    Updates from Review

commit 06ef7a9
Author: Andrew Meyer <[email protected]>
Date:   Wed Jan 24 12:45:50 2024 +0100

    Only generate jsi for react native builds

commit 33f29b0
Author: Andrew Meyer <[email protected]>
Date:   Wed Jan 24 12:33:57 2024 +0100

    PR comments and etc

    * Fixed some build issues
    * Reactivate ccache for integration tests builds

commit b67a299
Author: Andrew Meyer <[email protected]>
Date:   Fri Jan 19 14:59:23 2024 +0100

    Final fixes to iOS building from source

commit 0c66006
Author: Andrew Meyer <[email protected]>
Date:   Fri Jan 19 10:41:52 2024 +0100

    More documentation updates

commit 5ac6267
Author: Andrew Meyer <[email protected]>
Date:   Fri Jan 19 09:37:19 2024 +0100

    Prepare for public consumption

    * update the packed contents of the package
    * update relevant documentation

commit de9300f
Author: Andrew Meyer <[email protected]>
Date:   Wed Jan 17 16:39:07 2024 +0100

    Use an BUILD_REALM_CORE env var to build core from source

commit 14d9de6
Author: Andrew Meyer <[email protected]>
Date:   Wed Jan 17 16:24:14 2024 +0100

    Refactor ios builds

    * build from core prebuilds
    * phase script only called when input and outputs have changes
    * reinstalling pods will wipe build files, forcing a rebuild
    * generate input file list so that core can be rebuilt on changes
    * generate dummy libraries so that libraries can be generated
    * create build option which forces core to build from source
    * build from source if prebuild url is not reachable

commit 02ba32d
Author: Andrew Meyer <[email protected]>
Date:   Thu Jan 4 17:56:33 2024 +0100

    Remove xcframework and just use static libraries

commit d370cba
Author: Andrew Meyer <[email protected]>
Date:   Sat Dec 30 11:09:10 2023 +0100

    Make builds for iOS work without downloading prebuilds
@kraenhansen kraenhansen force-pushed the kh/build-optimizations-squashed branch from 973e0ad to 12c3a02 Compare May 23, 2024 12:12
@kraenhansen kraenhansen force-pushed the kh/build-optimizations-squashed branch from 943dabc to 29868fe Compare May 23, 2024 14:50
@kraenhansen kraenhansen changed the title "Build optimizations" for iOS and Android RJS-2101: "Build optimizations" for iOS and Android May 24, 2024
Comment on lines -438 to -443
- uses: actions/setup-java@v3
if: ${{ matrix.variant.os == 'android' }}
with:
distribution: 'zulu' # See 'Supported distributions' for available options
java-version: '17'

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment on lines -123 to -136
- name: Setup Java
if: ${{ matrix.variant.os == 'android' }}
uses: actions/setup-java@v3
with:
distribution: 'zulu' # See 'Supported distributions' for available options
java-version: '11'

- name: Setup Android SDK
if: ${{ matrix.variant.os == 'android' }}
uses: android-actions/setup-android@v2

- name: Install NDK
if: ${{ matrix.variant.os == 'android' }}
run: sdkmanager --install "ndk;${{ env.NDK_VERSION }}"
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These were moved into a separate Android specific prebuild-android job.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

1 participant