From 1abbd0bbdcbf01049c86cf2dc6ff48d06a087fc1 Mon Sep 17 00:00:00 2001 From: William Candillon Date: Wed, 7 Oct 2026 18:46:44 +0200 Subject: [PATCH 1/3] :wrench: --- .github/actions/setup/action.yml | 6 +- .github/workflows/build-dawn.yml | 302 ----- .gitmodules | 4 - .../docs/integrations/react-native-skia.mdx | 10 +- apps/example/ios/Podfile.lock | 6 +- apps/example/package.json | 2 +- externals/dawn | 1 - packages/webgpu/.gitignore | 4 +- packages/webgpu/CONTRIBUTING.md | 72 +- packages/webgpu/Package.swift | 142 +- packages/webgpu/android/CMakeLists.txt | 14 +- packages/webgpu/android/build.gradle | 23 + packages/webgpu/cpp/rnwgpu/SurfaceRegistry.h | 4 +- packages/webgpu/package.json | 10 +- packages/webgpu/react-native-webgpu.podspec | 40 +- packages/webgpu/scripts/apply-dawn-patches.sh | 33 - .../scripts/build/apple.toolchain.cmake | 1179 ----------------- .../webgpu/scripts/build/copy-artifacts.ts | 7 - .../scripts/build/dawn-configuration.ts | 101 -- packages/webgpu/scripts/build/dawn.ts | 173 --- packages/webgpu/scripts/build/util.ts | 92 -- packages/webgpu/scripts/check-dawn.ts | 78 ++ .../tint-looprange-function-variable.patch | 60 - .../webgpu/scripts/generate-package-swift.ts | 90 -- packages/webgpu/scripts/install-dawn.ts | 309 ----- .../webgpu/scripts/package-swift-template.ts | 196 --- .../webgpu/src/__tests__/FeatureNames.spec.ts | 16 +- spm-example/README.md | 5 +- yarn.lock | 18 +- 29 files changed, 312 insertions(+), 2685 deletions(-) delete mode 100644 .github/workflows/build-dawn.yml delete mode 100644 .gitmodules delete mode 160000 externals/dawn delete mode 100755 packages/webgpu/scripts/apply-dawn-patches.sh delete mode 100644 packages/webgpu/scripts/build/apple.toolchain.cmake delete mode 100644 packages/webgpu/scripts/build/copy-artifacts.ts delete mode 100644 packages/webgpu/scripts/build/dawn-configuration.ts delete mode 100644 packages/webgpu/scripts/build/dawn.ts delete mode 100644 packages/webgpu/scripts/build/util.ts create mode 100644 packages/webgpu/scripts/check-dawn.ts delete mode 100644 packages/webgpu/scripts/dawn-patches/tint-looprange-function-variable.patch delete mode 100644 packages/webgpu/scripts/generate-package-swift.ts delete mode 100644 packages/webgpu/scripts/install-dawn.ts delete mode 100644 packages/webgpu/scripts/package-swift-template.ts diff --git a/.github/actions/setup/action.yml b/.github/actions/setup/action.yml index 359d3600db..f5b52dc3d2 100644 --- a/.github/actions/setup/action.yml +++ b/.github/actions/setup/action.yml @@ -26,7 +26,9 @@ runs: fi shell: bash - - name: Install Dawn + # Dawn comes with the react-native-webgpu-dawn dependency; this only checks + # it against the C++ workarounds pinned to a Dawn commit. + - name: Check Dawn working-directory: packages/webgpu shell: bash - run: yarn install-dawn + run: yarn check-dawn diff --git a/.github/workflows/build-dawn.yml b/.github/workflows/build-dawn.yml deleted file mode 100644 index 613f1e2268..0000000000 --- a/.github/workflows/build-dawn.yml +++ /dev/null @@ -1,302 +0,0 @@ -name: Build Dawn - -on: - workflow_dispatch: - inputs: - tag_suffix: - description: 'Optional suffix appended to the release tag (e.g. "a" for dawn-chrome-m154a) when rebuilding the same Dawn commit with new patches' - required: false - default: '' - -concurrency: - group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: true - -jobs: - prepare-release: - runs-on: ubuntu-latest - outputs: - dawn_branch: ${{ steps.dawn_meta.outputs.branch }} - dawn_branch_slug: ${{ steps.dawn_meta.outputs.branch_slug }} - tag_name: ${{ steps.release_meta.outputs.tag_name }} - release_name: ${{ steps.release_meta.outputs.release_name }} - steps: - - name: Checkout repository - uses: actions/checkout@v6.0.2 - - - name: Determine Dawn version metadata - id: dawn_meta - run: | - set -eo pipefail - version=$(node -p "require('./packages/webgpu/package.json').dawn") - commit=$(node -p "require('./packages/webgpu/package.json').dawnCommit") - if [ -z "$version" ] || [ "$version" = "undefined" ]; then - echo "Could not determine Dawn version from package.json ('dawn' field)" >&2 - exit 1 - fi - if [ -z "$commit" ] || [ "$commit" = "undefined" ]; then - echo "Could not determine Dawn commit from package.json ('dawnCommit' field)" >&2 - exit 1 - fi - gitlink=$(git ls-tree HEAD externals/dawn | awk '{print $3}') - if [ "$gitlink" != "$commit" ]; then - echo "Submodule gitlink ($gitlink) does not match package.json dawnCommit ($commit)." >&2 - echo "Update the externals/dawn submodule and the dawnCommit field together." >&2 - exit 1 - fi - slug=${version//\//-} - echo "branch=$version" >> "$GITHUB_OUTPUT" - echo "branch_slug=$slug" >> "$GITHUB_OUTPUT" - - - name: Compute release metadata - id: release_meta - run: | - tag="dawn-${DAWN_VERSION_SLUG}${TAG_SUFFIX}" - echo "tag_name=$tag" >> "$GITHUB_OUTPUT" - echo "release_name=Dawn ${DAWN_VERSION}${TAG_SUFFIX}" >> "$GITHUB_OUTPUT" - env: - DAWN_VERSION: ${{ steps.dawn_meta.outputs.branch }} - DAWN_VERSION_SLUG: ${{ steps.dawn_meta.outputs.branch_slug }} - TAG_SUFFIX: ${{ github.event.inputs.tag_suffix }} - - - name: Create GitHub release - id: create_release - uses: softprops/action-gh-release@v2 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - tag_name: ${{ steps.release_meta.outputs.tag_name }} - name: ${{ steps.release_meta.outputs.release_name }} - body: "Dawn prebuilt binaries for ${{ steps.dawn_meta.outputs.branch }} (Dawn commit pinned in package.json dawnCommit, with the patches in packages/webgpu/scripts/dawn-patches applied)" - draft: false - prerelease: true - generate_release_notes: false - - mobile-android: - needs: prepare-release - strategy: - fail-fast: false - matrix: - include: - - arch: arm64-v8a - cmake_args: -DANDROID_ABI=arm64-v8a -DANDROID_PLATFORM=android-26 - output_dir: externals/dawn/out/android_arm64-v8a - library_path: src/dawn/native/libwebgpu_dawn.so - - arch: armeabi-v7a - cmake_args: -DANDROID_ABI=armeabi-v7a -DANDROID_PLATFORM=android-26 - output_dir: externals/dawn/out/android_armeabi-v7a - library_path: src/dawn/native/libwebgpu_dawn.so - - arch: x86 - cmake_args: -DANDROID_ABI=x86 -DANDROID_PLATFORM=android-26 - output_dir: externals/dawn/out/android_x86 - library_path: src/dawn/native/libwebgpu_dawn.so - - arch: x86_64 - cmake_args: -DANDROID_ABI=x86_64 -DANDROID_PLATFORM=android-26 - output_dir: externals/dawn/out/android_x86_64 - library_path: src/dawn/native/libwebgpu_dawn.so - - name: Build-android-${{ matrix.arch }} - runs-on: ubuntu-latest - steps: - - name: Checkout main repository - uses: actions/checkout@v6.0.2 - with: - submodules: true - - - name: Setup Android NDK - id: setup-ndk - uses: nttld/setup-ndk@v1 - with: - ndk-version: r27d - - - name: Set ANDROID_NDK - run: echo "ANDROID_NDK=${{ steps.setup-ndk.outputs.ndk-path }}" >> $GITHUB_ENV - - - name: Apply Dawn patches - run: bash packages/webgpu/scripts/apply-dawn-patches.sh - - - name: Build android ${{ matrix.arch }} - run: | - cmake -S externals/dawn -B ${{ matrix.output_dir }} -G Ninja \ - -DDAWN_MOBILE_BUILD=android \ - -C externals/dawn/.github/workflows/dawn-ci.cmake \ - -DCMAKE_TOOLCHAIN_FILE=$ANDROID_NDK/build/cmake/android.toolchain.cmake \ - ${{ matrix.cmake_args }} \ - -DANDROID_STL=c++_shared \ - -DCMAKE_BUILD_TYPE=Release \ - -DBUILD_SHARED_LIBS=OFF \ - -DDAWN_BUILD_MONOLITHIC_LIBRARY=SHARED \ - -DDAWN_BUILD_PROTOBUF=OFF \ - -DANDROID_SUPPORT_FLEXIBLE_PAGE_SIZES=ON \ - -DCMAKE_EXE_LINKER_FLAGS="-llog" \ - -DCMAKE_SHARED_LINKER_FLAGS="-llog -Wl,-z,max-page-size=16384" - ninja -C ${{ matrix.output_dir }} - - - name: Strip Android binaries - run: | - $ANDROID_NDK/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-strip ${{ matrix.output_dir }}/${{ matrix.library_path }} - - # Exceptions from the libraries that link Dawn reach JS through Hermes, - # which only matches them against the app's libc++_shared.so. - - name: Check that Dawn uses the shared C++ runtime - run: | - library=${{ matrix.output_dir }}/${{ matrix.library_path }} - if $ANDROID_NDK/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-nm -D --defined-only "$library" | grep -E ' (__cxa_throw|__gxx_personality_v0)$'; then - echo "::error::$library defines its own C++ runtime; build it with -DANDROID_STL=c++_shared" - exit 1 - fi - - - name: Upload build artifacts - uses: actions/upload-artifact@v7 - with: - name: build-android-${{ matrix.arch }} - path: ${{ matrix.output_dir }}/${{ matrix.library_path }} - - - name: Install headers (from arm64-v8a build only) - if: matrix.arch == 'arm64-v8a' - run: | - cmake --install ${{ matrix.output_dir }} --prefix dawn-headers - - - name: Upload headers (from arm64-v8a build only) - if: matrix.arch == 'arm64-v8a' - uses: actions/upload-artifact@v7 - with: - name: dawn-headers - path: dawn-headers/ - - mobile-apple: - needs: prepare-release - strategy: - fail-fast: false - matrix: - include: - - platform: ios - arch: arm64 - cmake_args: -DPLATFORM=OS64 -DDEPLOYMENT_TARGET=14.0 -DENABLE_BITCODE=OFF -DENABLE_ARC=OFF -DENABLE_VISIBILITY=OFF - output_dir: externals/dawn/out/ios_arm64 - library_path: src/dawn/native/libwebgpu_dawn.a - - platform: ios - arch: sim_arm64 - cmake_args: -DPLATFORM=SIMULATORARM64 -DDEPLOYMENT_TARGET=14.0 -DENABLE_BITCODE=OFF -DENABLE_ARC=OFF -DENABLE_VISIBILITY=OFF - output_dir: externals/dawn/out/ios_sim_arm64 - library_path: src/dawn/native/libwebgpu_dawn.a - - platform: ios - arch: sim_x86_64 - cmake_args: -DPLATFORM=SIMULATOR64 -DDEPLOYMENT_TARGET=14.0 -DENABLE_BITCODE=OFF -DENABLE_ARC=OFF -DENABLE_VISIBILITY=OFF - output_dir: externals/dawn/out/ios_sim_x86_64 - library_path: src/dawn/native/libwebgpu_dawn.a - - platform: macos - arch: universal - cmake_args: -DPLATFORM=MAC_UNIVERSAL -DDEPLOYMENT_TARGET=11.0 -DENABLE_BITCODE=OFF -DENABLE_ARC=OFF -DENABLE_VISIBILITY=OFF - output_dir: externals/dawn/out/macos_universal - library_path: src/dawn/native/libwebgpu_dawn.a - - name: Build-${{ matrix.platform }}-${{ matrix.arch }} - runs-on: macos-latest - steps: - - name: Clean previous Dawn workspace - run: | - git submodule deinit -f externals/dawn 2>/dev/null || true - rm -rf externals/dawn - - - name: Checkout main repository - uses: actions/checkout@v6.0.2 - with: - submodules: true - - - name: Apply Dawn patches - run: bash packages/webgpu/scripts/apply-dawn-patches.sh - - - name: Build ${{ matrix.platform }} ${{ matrix.arch }} - run: | - cmake -S externals/dawn -B ${{ matrix.output_dir }} -G Ninja \ - -DDAWN_MOBILE_BUILD=apple \ - -C externals/dawn/.github/workflows/dawn-ci.cmake \ - -DCMAKE_TOOLCHAIN_FILE=${{ github.workspace }}/packages/webgpu/scripts/build/apple.toolchain.cmake \ - ${{ matrix.cmake_args }} \ - -DCMAKE_BUILD_TYPE=Release \ - -DDAWN_BUILD_PROTOBUF=OFF - ninja -C ${{ matrix.output_dir }} - - - name: Upload build artifacts - uses: actions/upload-artifact@v7 - with: - name: build-${{ matrix.platform }}-${{ matrix.arch }} - path: ${{ matrix.output_dir }}/${{ matrix.library_path }} - - package-mobile: - name: Package Mobile Artifacts - runs-on: macos-latest - needs: [prepare-release, mobile-android, mobile-apple] - steps: - - name: Clean previous Dawn workspace - run: | - git submodule deinit -f externals/dawn 2>/dev/null || true - rm -rf externals/dawn - - - name: Checkout main repository - uses: actions/checkout@v6.0.2 - - - name: Download all build artifacts - uses: actions/download-artifact@v8 - with: - pattern: build-* - path: artifacts - - - name: Download headers - uses: actions/download-artifact@v8 - with: - name: dawn-headers - path: dawn-headers - - - name: Create iOS Simulator fat binary - run: | - mkdir -p libs/apple/iphonesimulator - lipo -create \ - artifacts/build-ios-sim_x86_64/libwebgpu_dawn.a \ - artifacts/build-ios-sim_arm64/libwebgpu_dawn.a \ - -output libs/apple/iphonesimulator/libwebgpu_dawn.a - - - name: Create XCFramework - run: | - xcodebuild -create-xcframework \ - -library libs/apple/iphonesimulator/libwebgpu_dawn.a -headers dawn-headers/include \ - -library artifacts/build-ios-arm64/libwebgpu_dawn.a -headers dawn-headers/include \ - -library artifacts/build-macos-universal/libwebgpu_dawn.a -headers dawn-headers/include \ - -output dawn-apple.xcframework - - - name: Package Android libraries - run: | - mkdir -p dawn-android/arm64-v8a - mkdir -p dawn-android/armeabi-v7a - mkdir -p dawn-android/x86 - mkdir -p dawn-android/x86_64 - cp artifacts/build-android-arm64-v8a/libwebgpu_dawn.so dawn-android/arm64-v8a/ - cp artifacts/build-android-armeabi-v7a/libwebgpu_dawn.so dawn-android/armeabi-v7a/ - cp artifacts/build-android-x86/libwebgpu_dawn.so dawn-android/x86/ - cp artifacts/build-android-x86_64/libwebgpu_dawn.so dawn-android/x86_64/ - - - name: Create archives - run: | - TAG="${{ needs.prepare-release.outputs.tag_name }}" - tar -czf dawn-android-${TAG}.tar.gz dawn-android - tar -czf dawn-headers-${TAG}.tar.gz dawn-headers - # Package.swift binaryTarget(url:checksum:) requires a zip archive, not a - # tarball, and `ditto` (unlike `zip`) preserves the xcframework's symlinks - # and resource forks losslessly. - ditto -c -k --sequesterRsrc --keepParent dawn-apple.xcframework dawn-apple-${TAG}.xcframework.zip - swift package compute-checksum dawn-apple-${TAG}.xcframework.zip > dawn-apple-${TAG}.xcframework.zip.checksum.txt - cat dawn-apple-${TAG}.xcframework.zip.checksum.txt - - - name: Upload to GitHub release - uses: softprops/action-gh-release@v2 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - tag_name: ${{ needs.prepare-release.outputs.tag_name }} - files: | - dawn-android-${{ needs.prepare-release.outputs.tag_name }}.tar.gz - dawn-apple-${{ needs.prepare-release.outputs.tag_name }}.xcframework.zip - dawn-apple-${{ needs.prepare-release.outputs.tag_name }}.xcframework.zip.checksum.txt - dawn-headers-${{ needs.prepare-release.outputs.tag_name }}.tar.gz - prerelease: true diff --git a/.gitmodules b/.gitmodules deleted file mode 100644 index 81c45037aa..0000000000 --- a/.gitmodules +++ /dev/null @@ -1,4 +0,0 @@ -[submodule "externals/dawn"] - path = externals/dawn - url = https://dawn.googlesource.com/dawn - branch = main diff --git a/apps/docs/content/docs/integrations/react-native-skia.mdx b/apps/docs/content/docs/integrations/react-native-skia.mdx index fb9d35d397..486d782284 100644 --- a/apps/docs/content/docs/integrations/react-native-skia.mdx +++ b/apps/docs/content/docs/integrations/react-native-skia.mdx @@ -7,30 +7,30 @@ react-native-webgpu and [`react-native-skia`](https://wcandillon.github.io/react Starting with v3, react-native-skia renders with Graphite, on top of Dawn, the same WebGPU implementation react-native-webgpu is built on, and the two packages are designed to share it: -- **One Dawn copy.** Both packages vendor the exact same prebuilt Dawn artifact, pinned to the Dawn revision of the Skia milestone (for example `dawn-chrome-m154`). When both are installed, react-native-skia detects react-native-webgpu at `pod install` time and defers to its copy, so the process contains exactly one Dawn. A build-time guard compares the two packages' Dawn tags and fails the native build on a mismatch instead of letting two incompatible copies coexist. +- **One Dawn copy.** Dawn ships in the `react-native-webgpu-dawn` npm package, built by react-native-skia from the Dawn revision its Skia release pins, and react-native-webgpu depends on it. When both libraries are installed, react-native-skia detects react-native-webgpu at `pod install` time and defers to its copy, so the process contains exactly one Dawn. A build-time guard compares the two packages' Dawn and fails the native build on a mismatch instead of letting two incompatible copies coexist. - **One `wgpu::Instance`.** When react-native-skia is present, react-native-webgpu adopts Skia's instance automatically at startup (discovered at runtime, independent of native-module initialization order). Graphite's device and every device you create through `navigator.gpu` live on the same instance. - **The WebGPU API lives here.** react-native-skia does not install `navigator.gpu` or any WebGPU JS API; react-native-webgpu is the single WebGPU API surface. If you want to write WebGPU code in an app that uses Skia, install react-native-webgpu alongside it. With react-native-skia v2, which keeps the Ganesh backend (and was published as `@shopify/react-native-skia` up to 2.14), there is no coupling at all: any version of either package can be installed together, and they simply don't interact. -Because react-native-skia links react-native-webgpu's Dawn copy, the two packages must be built against the same Dawn tag; this is what makes sharing an instance and importing devices sound. Releases are kept in lockstep, and the native build fails with an explicit message if the tags ever differ, so a mismatch surfaces at build time rather than as undefined behavior at runtime. react-native-skia v2 has no such constraint. +Because react-native-skia links react-native-webgpu's Dawn copy, the two packages must be built against the same Dawn; this is what makes sharing an instance and importing devices sound. Releases are kept in lockstep, and the native build fails with an explicit message if the tags ever differ, so a mismatch surfaces at build time rather than as undefined behavior at runtime. react-native-skia v2 has no such constraint. ## Compatibility -Both packages follow Chrome/Skia milestones: react-native-webgpu pins the Dawn revision from the Skia milestone's `DEPS`, and react-native-skia depends on that milestone's binaries, published as `react-native-skia-graphite-*` `.x.y`. Pick one row and install versions from it. A letter suffix on the Dawn tag (for instance `dawn-chrome-m154a`) is the same Dawn commit rebuilt with additional patches; it still counts as a different tag, so the two packages must agree on the suffix too. +Both packages follow Chrome/Skia milestones: react-native-skia publishes its binaries as `react-native-skia-graphite-*` and the Dawn they were built with as `react-native-webgpu-dawn`, all at `.x.y`, and react-native-webgpu depends on that Dawn package. Pick one row and install versions from it. A letter suffix on the Dawn tag (for instance `dawn-chrome-m154a`) is the same Dawn commit rebuilt with additional patches; it still counts as a different tag, so the two packages must agree on the suffix too. | Milestone | react-native-webgpu | Dawn release tag | react-native-skia | | --- | --- | --- | --- | -| m154a | >= 0.12.1 | `dawn-chrome-m154a` | >= 3.0.6 (Graphite `154.x`) | +| m154a | >= 0.12.1 | `dawn-chrome-m154a` (`react-native-webgpu-dawn` 154.2.0 from 0.13) | >= 3.0.6 (Graphite `154.x`) | | m154 | 0.10.0 to 0.11.2 | `dawn-chrome-m154` | 3.0.0 to 3.0.5 (Graphite `154.x`) | The Graphite previews of v2 (`@shopify/react-native-skia@next`, for instance 2.12.0-next.1) pair with react-native-webgpu the same way. Regular v2 releases are not part of this pairing: they do not link Dawn, so any version works alongside any version of react-native-webgpu. react-native-webgpu 0.6.4 and earlier predate the interop APIs (`importDevice` landed in 0.7.0); install them alongside react-native-skia v2 only. -To check what an installed pair is built against, compare `node -p "require('react-native-webgpu/package.json').dawn"` with the Dawn tag recorded next to the Skia binaries, in `node_modules/react-native-skia-graphite-apple-ios/libs/.dawn-version` (or `react-native-skia-graphite-android`). They have to name the same milestone. +To check what an installed pair is built against, compare `node -p "require('react-native-webgpu/package.json').dawn"` with the Dawn tag recorded next to the Skia binaries, in `node_modules/react-native-skia-graphite-apple-ios/libs/.dawn-version` (or `react-native-skia-graphite-android`). They have to name the same milestone. The installed Dawn itself is `node -p "require('react-native-webgpu-dawn/package.json').dawn.commit"`. ## Rendering with Skia's device diff --git a/apps/example/ios/Podfile.lock b/apps/example/ios/Podfile.lock index efa671b1bb..1cfd5aaab2 100644 --- a/apps/example/ios/Podfile.lock +++ b/apps/example/ios/Podfile.lock @@ -1894,7 +1894,7 @@ PODS: - ReactCommon/turbomodule/core - SocketRocket - Yoga - - react-native-skia (3.0.6): + - react-native-skia (3.0.8): - boost - DoubleConversion - fast_float @@ -3073,8 +3073,8 @@ SPEC CHECKSUMS: React-Mapbuffer: 9d2434a42701d6144ca18f0ca1c4507808ca7696 React-microtasksnativemodule: 75b6604b667d297292345302cc5bfb6b6aeccc1b react-native-safe-area-context: 6cf08f4151132f9cf2adb948dc6c4ac387f8d30f - react-native-skia: cadb959c5a83a341dcc1545592cc1a6dfc5b886d - react-native-webgpu: fcba69b760e8971acc7ebb04041a9a04694c049f + react-native-skia: fb8b5745ecb70a0593d9d758fa9811c9056fb42d + react-native-webgpu: df22c141df8e9d6028d47498a343893310525b22 React-NativeModulesApple: 879fbdc5dcff7136abceb7880fe8a2022a1bd7c3 React-oscompat: 93b5535ea7f7dff46aaee4f78309a70979bdde9d React-perflogger: 5536d2df3d18fe0920263466f7b46a56351c0510 diff --git a/apps/example/package.json b/apps/example/package.json index 644382bab8..a8d5100a49 100644 --- a/apps/example/package.json +++ b/apps/example/package.json @@ -37,7 +37,7 @@ "react-native-nitro-modules": "0.35.7", "react-native-reanimated": "4.3.1", "react-native-safe-area-context": "^5.4.0", - "react-native-skia": "3.0.6", + "react-native-skia": "3.0.8", "react-native-vision-camera": "5.0.10", "react-native-vision-camera-worklets": "5.0.10", "react-native-web": "^0.21.2", diff --git a/externals/dawn b/externals/dawn deleted file mode 160000 index 3d786993a7..0000000000 --- a/externals/dawn +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 3d786993a7ded64c4ebb4884b9b079db9ad0e580 diff --git a/packages/webgpu/.gitignore b/packages/webgpu/.gitignore index 586aae074e..027f26596a 100644 --- a/packages/webgpu/.gitignore +++ b/packages/webgpu/.gitignore @@ -1,4 +1,3 @@ -!scripts/build # OSX # .DS_Store @@ -74,3 +73,6 @@ lib/ # compiled Expo config plugin plugin/build/ + +# Dawn xcframework copied in from react-native-webgpu-dawn at pod install +libs/ diff --git a/packages/webgpu/CONTRIBUTING.md b/packages/webgpu/CONTRIBUTING.md index 7ba9d305de..c6392c98e1 100644 --- a/packages/webgpu/CONTRIBUTING.md +++ b/packages/webgpu/CONTRIBUTING.md @@ -3,12 +3,11 @@ ## Development workflow ```sh -git submodule update --init yarn -cd packages/webgpu && yarn install-dawn # prebuilt Dawn binaries -# or: yarn build-dawn # build Dawn from source ``` +Dawn, the WebGPU implementation, comes with the `react-native-webgpu-dawn` dependency of `packages/webgpu`: the Android shared libraries, the Apple xcframework and the headers. Nothing to download or build. + Example app (from `apps/example/`): `yarn start` · `yarn ios` · `yarn android` From the repo root: `yarn lint` · `yarn tsc` · `yarn build:docs` @@ -17,7 +16,7 @@ Tests (from `packages/webgpu/`): `yarn test:ref` (Chrome reference) · `yarn tes `yarn test` needs the example app open on its "Tests" screen and connected to Metro first: start Metro with `CI=true yarn start` (from `apps/example/`) — `initialRouteName` in `apps/example/src/App.tsx` is `"Tests"` when `process.env.CI === "true"`, inlined at bundle time via the `transform-inline-environment-variables` babel plugin — then launch the app (`yarn ios` / `yarn android`, or install+launch an existing build). The screen shows "Connecting to localhost..." once it's ready; `yarn test` then picks it up automatically. If a run fails mid-suite, reload the app (`curl -X POST http://localhost:8081/reload`) before the next run — a broken `GPUDevice` from the failed run makes unrelated later tests fail too. The app and the test server talk over port 4242 by default; set `E2E_PORT` for both Metro (it is inlined into the bundle, so start Metro with `--reset-cache` after changing it) and `yarn test` to use another one, as CI does to keep clear of the other projects sharing its runner. -Other `packages/webgpu` scripts: `yarn clean-dawn` · `yarn build-dawn` +Other `packages/webgpu` scripts: `yarn check-dawn` (checks the installed Dawn against the C++ workarounds pinned to a Dawn commit; CI runs it after `yarn install`) ## Expo config plugin @@ -25,47 +24,29 @@ The Expo config plugin lives in `plugin/src` and is compiled to `plugin/build` b ## Upgrading Dawn -The Dawn version tracks the one shipped by `react-native-skia`: the pin is the exact Dawn commit from the Skia milestone's DEPS file (`third_party/externals/dawn` in Skia's DEPS). It is recorded in two places that must stay in sync: - -- the `externals/dawn` submodule gitlink (the commit the submodule points at) -- `packages/webgpu/package.json` → `"dawn"` (a human-readable label, e.g. `chrome-m152`; Skia milestones mirror Chrome milestones) and `"dawnCommit"` (the exact commit hash) - -The **Build Dawn** workflow verifies the gitlink matches `dawnCommit` and fails otherwise. - -`yarn install-dawn` downloads **prebuilt** binaries from a GitHub release on this repo tagged `dawn-` (e.g. `dawn-chrome-m152`). `yarn build-dawn` builds the same binaries from the submodule source instead. - -Steps to bump to a new Dawn version (new Skia milestone `m`): - -1. **Find the Dawn commit** in the Skia milestone's `DEPS` file (`third_party/externals/dawn` entry). +Dawn ships in the `react-native-webgpu-dawn` npm package, which react-native-skia builds and publishes together with its own Skia Graphite binaries (the **Build and publish binaries** workflow of [wcandillon/react-native-skia](https://github.com/wcandillon/react-native-skia), see its `packages/skia/CONTRIBUTING.md`). It is built from the Dawn commit the Skia release pins in its DEPS, with the patches that release needs, so the two libraries always link the same Dawn. The package records that commit in its `package.json` (`dawn.commit`) and its version follows the Skia one (`154.2.0` for Skia `m154_8037_58b`). -2. **Point the submodule at that commit** and update `package.json` (`"dawn": "chrome-m"`, `"dawnCommit": ""`): +`packages/webgpu/package.json` pins it exactly (`dependencies`), and keeps the `dawn` label (`chrome-m154a`) that react-native-skia 3.0.x compares against its own Dawn at `pod install` time; it goes away once react-native-skia depends on the package too. - ```sh - cd externals/dawn && git fetch origin && git checkout && cd ../.. - ``` +Steps to bump to a new Dawn (new Skia milestone `m`): -3. **Publish prebuilt binaries.** Trigger the **Build Dawn** workflow (`.github/workflows/build-dawn.yml`, `workflow_dispatch`). It builds Android + Apple from the submodule and creates the `dawn-chrome-m` release with the headers, the Android `.so`s, and the Apple `.xcframework`. (To build locally instead, run `yarn build-dawn`; this requires the Android NDK and Xcode toolchains.) +1. **Wait for the binaries.** react-native-skia publishes `react-native-webgpu-dawn` at the new version. -4. **Pull the new binaries** once the release exists: +2. **Bump the dependency** in `packages/webgpu/package.json` and run `yarn`. - ```sh - cd packages/webgpu && yarn install-dawn - ``` +3. **Review the workarounds.** `yarn check-dawn` fails when the Dawn commit changed while a workaround in `scripts/check-dawn.ts` is still pinned to the previous one: check whether the new Dawn carries the upstream fix, then drop the workaround or move its pin. -5. **Map the new feature names.** A milestone usually adds `wgpu::FeatureName` values. Add them to `RNWGPU_FOR_EACH_FEATURE_NAME` in `cpp/rnwgpu/api/GPUFeatures.h`, which is the single list both conversion directions are generated from; `src/__tests__/FeatureNames.spec.ts` diffs it against the installed `webgpu_cpp.h` and fails when one is missing. +4. **Map the new feature names.** A milestone usually adds `wgpu::FeatureName` values. Add them to `RNWGPU_FOR_EACH_FEATURE_NAME` in `cpp/rnwgpu/api/GPUFeatures.h`, which is the single list both conversion directions are generated from; `src/__tests__/FeatureNames.spec.ts` diffs it against the installed `webgpu_cpp.h` and fails when one is missing. -6. **Update the compatibility table** in `apps/docs/content/docs/integrations/react-native-skia.mdx` with the new milestone row, so users can pair react-native-webgpu and `react-native-skia` versions. +5. **Update the compatibility table** in `apps/docs/content/docs/integrations/react-native-skia.mdx` with the new milestone row, so users can pair react-native-webgpu and `react-native-skia` versions. -7. **Build both platforms.** A milestone can also change Dawn's C++ API surface, not just add features — e.g. `chrome-m154` turned `SharedTextureMemory::BeginAccess`/`EndAccess`, `Adapter::GetLimits`, `Device::GetLimits`, and `SharedTextureMemory::GetProperties` from a bool-ish return into `wgpu::Status` (no implicit bool conversion), breaking every `if (!result)` / `if (result)` call site in `cpp/rnwgpu/api/*.cpp`. Building iOS and Android is the way these surface; fix by comparing explicitly (`result == wgpu::Status::Success`). +6. **Build both platforms.** A milestone can also change Dawn's C++ API surface, not just add features — e.g. `chrome-m154` turned `SharedTextureMemory::BeginAccess`/`EndAccess`, `Adapter::GetLimits`, `Device::GetLimits`, and `SharedTextureMemory::GetProperties` from a bool-ish return into `wgpu::Status` (no implicit bool conversion), breaking every `if (!result)` / `if (result)` call site in `cpp/rnwgpu/api/*.cpp`. Building iOS and Android is the way these surface; fix by comparing explicitly (`result == wgpu::Status::Success`). -8. **Verify and commit.** Build and run the example app (see "Development workflow" above for reaching the Tests screen), then commit the submodule bump together with the updated `package.json`. +7. **Verify and commit.** Build and run the example app (see "Development workflow" above for reaching the Tests screen), then commit the dependency bump. ## Swift Package Manager (preview) CocoaPods stays the default. `Package.swift` is additive: SwiftPM ignores the -podspec, and CocoaPods ignores `Package.swift`. The manifest is generated from -`scripts/package-swift-template.ts` by `yarn generate-package-swift` -(`--local` points the Dawn binary target at `libs/apple/` instead of the -release zip); edit the template, never the output. +podspec, and CocoaPods ignores `Package.swift`. SwiftPM support requires **React Native 0.87 or newer**; earlier releases ship no `scripts/spm`. `apps/example` is on an older version, so it cannot exercise @@ -102,18 +83,19 @@ ships, `.iOS(.v15)` is the only value that links. #### Dawn -The `WebGPUDawn` binary target downloads the release zip named by the `dawn` -field in `package.json`; the checksum is fetched from the release's -`.checksum.txt` at generation time. A Graphite build of react-native-skia -installed alongside must link the same Dawn tag, which the manifest checks at -evaluation time. It reads the tag from -`react-native-skia-graphite-apple-ios/libs/.dawn-version` and -`react-native-skia-graphite-apple-macos/libs/.dawn-version` (v3 and above, -hoisted or nested under `react-native-skia/node_modules`) and from -`@shopify/react-native-skia/libs/.dawn-version` (the v2 Graphite previews), -and fails on any marker that differs. SwiftPM caches manifest evaluations, so -after changing either package's Dawn reset the package caches if the check does -not re-run. +The manifest depends on the `react-native-webgpu-dawn` package by path (a +sibling in `node_modules`, or this monorepo's root) and links its +`libwebgpu_dawn.xcframework`, whose slices embed the `webgpu/` and `dawn/` +headers, so no header search path is needed for them. A Graphite build of +react-native-skia installed alongside must link the same Dawn, which the +manifest checks at evaluation time: a react-native-skia that depends on +`react-native-webgpu-dawn` must pin the same version, and the 3.0.x line, which +vendors its own Dawn, must record this package's `dawn` tag at +`react-native-skia-graphite-apple-ios/libs/.dawn-version` (hoisted or nested +under `react-native-skia/node_modules`, also checked for macOS and for the v2 +Graphite previews at `@shopify/react-native-skia/libs/.dawn-version`). SwiftPM +caches manifest evaluations, so after changing either package's Dawn reset the +package caches if the check does not re-run. After changing which binaries a checkout uses, delete `ios/.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved`: diff --git a/packages/webgpu/Package.swift b/packages/webgpu/Package.swift index f531b832d6..c3506c0ef6 100644 --- a/packages/webgpu/Package.swift +++ b/packages/webgpu/Package.swift @@ -1,6 +1,4 @@ // swift-tools-version: 6.0 -// Generated by scripts/generate-package-swift.ts — do not edit by hand. -// Re-run that script after a new Dawn release to update the URL/checksum below. // // SwiftPM manifest for react-native-webgpu. iOS only. // Additive: the CocoaPods podspec remains the supported default. @@ -21,49 +19,94 @@ let packageRoot = URL(fileURLWithPath: Context.packageDirectory) let sibling = { (relative: String) -> String in URL(fileURLWithPath: "\(packageRoot)/\(relative)").standardized.path } +// A node package next to this one: a sibling in the consumer's node_modules, +// or under this monorepo's root. +let nodePackage = { (name: String) -> String? in + ["../\(name)", "../../node_modules/\(name)"] + .map(sibling) + .first { FileManager.default.fileExists(atPath: "\($0)/package.json") } +} +let readJSON = { (path: String) -> [String: Any]? in + guard let data = FileManager.default.contents(atPath: path) else { return nil } + return try? JSONSerialization.jsonObject(with: data) as? [String: Any] +} + +// Dawn, the WebGPU implementation, comes from the react-native-webgpu-dawn npm +// package this package depends on: an xcframework with the `webgpu/` and +// `dawn/` headers embedded in every slice, which SwiftPM exposes to dependents +// without any search path. react-native-skia's Graphite backend links the +// same package, so an app installing both contains exactly one Dawn. +guard let dawnPath = nodePackage("react-native-webgpu-dawn") else { + // Reached when the dependency was skipped at install time, which SwiftPM + // would otherwise report as an unresolvable dependency path. + fatalError( + """ + react-native-webgpu-dawn was not found next to react-native-webgpu. It ships \ + the Dawn binaries this package links against. Reinstall dependencies. + """) +} +let ownPackage = readJSON("\(packageRoot)/package.json") ?? [:] +let dawnVersion = + (readJSON("\(dawnPath)/package.json")?["version"] as? String) ?? "unknown" // Skia Graphite and WebGPU must link the exact same Dawn, or the pair links // fine and crashes at runtime. react-native-skia's podspec enforces this at -// `pod install` time by comparing its libs/.dawn-version against this -// package's `dawn` field. A Swift package has no install hook, so the same -// check runs here, at manifest evaluation. SwiftPM caches evaluations, so -// after changing either package's Dawn version reset the package caches -// (File > Packages > Reset Package Caches) if this does not re-run. -let dawnReleaseTag = "dawn-chrome-m154a" -// Only Graphite builds of react-native-skia carry this marker (Ganesh builds -// do not link Dawn and impose no constraint). From v3 the Skia binaries ship -// in react-native-skia-graphite-apple-ios, which records the tag at -// libs/.dawn-version; react-native-skia's podspec copies it into its own -// libs/ at `pod install`, which never runs here. The v2 Graphite previews -// (e.g. @shopify/react-native-skia@2.12.0-next.1) keep it in their own libs/. -// The graphite packages are normally hoisted next to this package, but may -// be nested under react-native-skia when the package manager cannot hoist -// them. Every marker found is checked. -let skiaDawnMarkers = [ - "react-native-skia-graphite-apple-ios/libs/.dawn-version", - "react-native-skia-graphite-apple-macos/libs/.dawn-version", - "react-native-skia/node_modules/react-native-skia-graphite-apple-ios/libs/.dawn-version", - "react-native-skia/node_modules/react-native-skia-graphite-apple-macos/libs/.dawn-version", - "@shopify/react-native-skia/libs/.dawn-version", -].flatMap { marker in - [ - sibling("../\(marker)"), // consumer: sibling in node_modules - sibling("../../node_modules/\(marker)"), // this monorepo - ] -} -for marker in skiaDawnMarkers { - guard let data = FileManager.default.contents(atPath: marker), - let skiaDawn = String(data: data, encoding: .utf8)? - .trimmingCharacters(in: .whitespacesAndNewlines) - else { continue } - if skiaDawn != dawnReleaseTag { +// `pod install` time; a Swift package has no install hook, so the same check +// runs here, at manifest evaluation. SwiftPM caches evaluations, so after +// changing either package's Dawn reset the package caches (File > Packages > +// Reset Package Caches) if this does not re-run. +// +// A react-native-skia that depends on react-native-webgpu-dawn itself must pin +// the same version as this package. Older Graphite builds (react-native-skia +// 3.0.x) vendor their own Dawn and record its release tag at +// libs/.dawn-version in their binary packages; this package's `dawn` field +// names the release that Dawn is interchangeable with. +if let skiaPath = nodePackage("react-native-skia"), + let skiaPackage = readJSON("\(skiaPath)/package.json"), + let skiaDawn = (skiaPackage["dependencies"] as? [String: String])?["react-native-webgpu-dawn"] +{ + if skiaDawn != dawnVersion { fatalError( """ - react-native-webgpu: Dawn version mismatch. This package links \(dawnReleaseTag) \ - but the react-native-skia Graphite binaries (\(marker)) link \(skiaDawn). \ - Align the two packages so the app contains exactly one Dawn. + react-native-webgpu: Dawn version mismatch. This package links \ + react-native-webgpu-dawn \(dawnVersion) but react-native-skia depends on \ + \(skiaDawn). Align the two packages so the app contains exactly one Dawn. """) } +} else { + let dawnReleaseTag = + "dawn-\((ownPackage["dawn"] as? String ?? "").replacingOccurrences(of: "/", with: "-"))" + // The graphite packages are normally hoisted next to this package, but may + // be nested under react-native-skia when the package manager cannot hoist + // them. The v2 Graphite previews (e.g. @shopify/react-native-skia@2.12.0-next.1) + // keep the marker in their own libs/. Every marker found is checked. + let skiaDawnMarkers = [ + "react-native-skia-graphite-apple-ios/libs/.dawn-version", + "react-native-skia-graphite-apple-macos/libs/.dawn-version", + "react-native-skia/node_modules/react-native-skia-graphite-apple-ios/libs/.dawn-version", + "react-native-skia/node_modules/react-native-skia-graphite-apple-macos/libs/.dawn-version", + "@shopify/react-native-skia/libs/.dawn-version", + ].flatMap { marker in + [ + sibling("../\(marker)"), // consumer: sibling in node_modules + sibling("../../node_modules/\(marker)"), // this monorepo + ] + } + for marker in skiaDawnMarkers { + guard let data = FileManager.default.contents(atPath: marker), + let skiaDawn = String(data: data, encoding: .utf8)? + .trimmingCharacters(in: .whitespacesAndNewlines) + else { continue } + if skiaDawn != dawnReleaseTag { + fatalError( + """ + react-native-webgpu: Dawn version mismatch. This package links \ + react-native-webgpu-dawn \(dawnVersion) (\(dawnReleaseTag)) but the \ + react-native-skia Graphite binaries (\(marker)) link \(skiaDawn). Align \ + the two packages so the app contains exactly one Dawn. + """) + } + } } // Unlike a native Xcode target, SwiftPM doesn't generate an implicit @@ -71,15 +114,10 @@ for marker in skiaDawnMarkers { // including file's own directory. The sources use bare cross-directory // includes (e.g. apple/WebGPUModule.h includes "RNWebGPUManager.h" from // cpp/rnwgpu), so every directory that's the target of one of those bare -// includes has to be listed explicitly here. +// includes has to be listed explicitly here. The "webgpu/..." and "dawn/..." +// includes resolve through the Dawn xcframework's embedded headers. let internalHeaderDirs = [ "apple", - // "cpp" itself resolves the "webgpu/..." and "dawn/..." namespaced - // includes. Those two directories are only present locally when built via - // `yarn install-dawn` (without the xcframework's embedded headers); a - // remote binaryTarget's xcframework embeds them instead (see - // build-dawn.yml's `-headers` flag), so "cpp" not containing them there - // is fine — the xcframework's own headers cover it. "cpp", "cpp/jsi", "cpp/rnwgpu", @@ -102,16 +140,9 @@ let package = Package( dependencies: [ .package(name: "React-GeneratedCode", path: "../../../ios"), .package(name: "ReactNative", path: "../../../../xcframeworks"), + .package(path: dawnPath), ], targets: [ - // Dawn's compiled WebGPU implementation. The xcframework embeds the - // `webgpu/` and `dawn/` C headers per-slice (built via `-headers` in - // build-dawn.yml), so SPM exposes them to dependents automatically. - .binaryTarget( - name: "WebGPUDawn", - url: "https://github.com/wcandillon/react-native-webgpu/releases/download/dawn-chrome-m154a/dawn-apple-dawn-chrome-m154a.xcframework.zip", - checksum: "ec06936cca08bca5177e41d78a1b190a22d62980e11df8a4c4ca5868de17c36c" - ), .target( name: "ReactNativeWebGPU", dependencies: [ @@ -120,13 +151,12 @@ let package = Package( .product(name: "ReactNativeDependenciesHeaders", package: "ReactNative"), // RNWgpuViewSpec, generated by the app's codegen run. .product(name: "ReactAppHeaders", package: "React-GeneratedCode"), - "WebGPUDawn", + .product(name: "react-native-webgpu-dawn", package: "react-native-webgpu-dawn"), ], // apple/ and cpp/ have no common ancestor below the package root, and // .headerSearchPath cannot escape the target path. path: ".", - // Explicit, so SwiftPM never walks node_modules, lib, android, or the - // headers-only cpp/webgpu and cpp/dawn trees. + // Explicit, so SwiftPM never walks node_modules, lib or android. sources: ["apple", "cpp/jsi", "cpp/rnwgpu"], // SwiftPM requires a public headers directory inside the target and // defaults to "include", which this package does not have. diff --git a/packages/webgpu/android/CMakeLists.txt b/packages/webgpu/android/CMakeLists.txt index 3b81f79a55..f6992ce553 100644 --- a/packages/webgpu/android/CMakeLists.txt +++ b/packages/webgpu/android/CMakeLists.txt @@ -7,8 +7,6 @@ set (CMAKE_CXX_STANDARD_REQUIRED True) set (PACKAGE_NAME "react-native-webgpu") -#link_directories(../libs/android/${ANDROID_ABI}/) - if(CMAKE_BUILD_TYPE STREQUAL "Debug") add_definitions(-DDEBUG=1) endif() @@ -19,7 +17,15 @@ else() add_definitions(-DRNF_ENABLE_LOGS=0) endif() -set (WEBGPU_LIBS_PATH "${CMAKE_CURRENT_SOURCE_DIR}/../libs/android/${ANDROID_ABI}") +# Dawn comes from the react-native-webgpu-dawn npm package (DAWN_DIR is passed +# by build.gradle): the shared library per ABI and the headers. +if(NOT DAWN_DIR) + message(FATAL_ERROR "react-native-webgpu: DAWN_DIR is not set (the react-native-webgpu-dawn package directory)") +endif() +set (WEBGPU_LIBS_PATH "${DAWN_DIR}/libs/android/${ANDROID_ABI}") +if(NOT EXISTS "${WEBGPU_LIBS_PATH}/libwebgpu_dawn.so") + message(FATAL_ERROR "react-native-webgpu: libwebgpu_dawn.so not found at ${WEBGPU_LIBS_PATH}. Reinstall dependencies (yarn install / npm install).") +endif() find_package(ReactAndroid REQUIRED CONFIG) find_package(fbjni REQUIRED CONFIG) @@ -72,8 +78,8 @@ target_include_directories( ../cpp/rnwgpu/api ../cpp/rnwgpu/api/descriptors ../cpp/jsi - ../cpp/webgpu ../cpp/platform + "${DAWN_DIR}/include" ${libfbjni_include_DIRS} ) diff --git a/packages/webgpu/android/build.gradle b/packages/webgpu/android/build.gradle index 043ab862a0..e49edbebd8 100644 --- a/packages/webgpu/android/build.gradle +++ b/packages/webgpu/android/build.gradle @@ -45,6 +45,28 @@ static def findNodeModules(baseDir) { def nodeModules = findNodeModules(projectDir) +// Resolve a node package directory using Node's own module resolution +// (mirrors `require.resolve(pkg/package.json)`). +static def resolveNodePackage(packageName, baseDir) { + def script = "process.stdout.write(require('path').dirname(require.resolve('${packageName}/package.json')))" + def proc = ["node", "-e", script].execute(null, baseDir) + proc.waitFor() + if (proc.exitValue() != 0) { + throw new GradleException( + "react-native-webgpu: Could not resolve the '${packageName}' package. " + + "Make sure dependencies are installed (yarn install / npm install).\n" + proc.err.text + ) + } + return proc.text.trim() +} + +// Dawn, the WebGPU implementation, ships in the react-native-webgpu-dawn npm +// package this package depends on: libs/android//libwebgpu_dawn.so and +// the headers under include/. react-native-skia's Graphite backend links the +// same package, so an app installing both contains exactly one Dawn. +def dawnDir = resolveNodePackage('react-native-webgpu-dawn', projectDir) +logger.warn("react-native-webgpu: Dawn from ${dawnDir}") + def getExtOrDefault(name) { return rootProject.ext.has(name) ? rootProject.ext.get(name) : project.properties["Wgpu_" + name] } @@ -75,6 +97,7 @@ android { abiFilters (*reactNativeArchitectures()) arguments '-DANDROID_STL=c++_shared', "-DNODE_MODULES_DIR=${nodeModules}", + "-DDAWN_DIR=${dawnDir}", "-DANDROID_SUPPORT_FLEXIBLE_PAGE_SIZES=ON" } } diff --git a/packages/webgpu/cpp/rnwgpu/SurfaceRegistry.h b/packages/webgpu/cpp/rnwgpu/SurfaceRegistry.h index 7c74169e93..9fa77b2620 100644 --- a/packages/webgpu/cpp/rnwgpu/SurfaceRegistry.h +++ b/packages/webgpu/cpp/rnwgpu/SurfaceRegistry.h @@ -401,8 +401,8 @@ class SurfaceInfo { // not touch the device, and this must not change behaviour there. // // Remove once the pinned Dawn contains the upstream fix; the check in - // scripts/install-dawn.ts fails the install when the Dawn pin changes so - // that decision is not forgotten. + // scripts/check-dawn.ts fails when the Dawn the react-native-webgpu-dawn + // package was built from changes, so that decision is not forgotten. void releaseSurfaceForDevice(const wgpu::Device &device) { #if defined(__ANDROID__) std::unique_lock lock(_mutex); diff --git a/packages/webgpu/package.json b/packages/webgpu/package.json index eeceec76a4..10fec0c1de 100644 --- a/packages/webgpu/package.json +++ b/packages/webgpu/package.json @@ -18,7 +18,6 @@ "android/src/**", "cpp/**/*.{h,cpp}", "apple/**", - "libs/**", "*.podspec", "Package.swift", "react-native.config.js", @@ -26,7 +25,6 @@ "plugin/build/**" ], "dawn": "chrome-m154a", - "dawnCommit": "3d786993a7ded64c4ebb4884b9b079db9ad0e580", "scripts": { "test": "NODE_OPTIONS='--experimental-require-module' jest -i", "test:ref": "REFERENCE=true NODE_OPTIONS='--experimental-require-module' jest -i", @@ -37,15 +35,12 @@ "build": "bob build && yarn build:plugin", "build:plugin": "tsc -p plugin/tsconfig.build.json", "release": "semantic-release", - "build-dawn": "tsx scripts/build/dawn.ts", - "clean-dawn": "rimraf ./libs && rimraf ../../externals/dawn/out", "clang-format": "yarn clang-format-ios && yarn clang-format-android && yarn clang-format-common", "clang-format-ios": "find apple/ -iname \"*.h\" -o -iname \"*.mm\" -o -iname \"*.cpp\" | xargs clang-format -i", "clang-format-android": "find android/cpp/ -iname \"*.h\" -o -iname \"*.m\" -o -iname \"*.cpp\" | xargs clang-format -i", "clang-format-common": "find cpp/rnwgpu -iname \"*.h\" -o -iname \"*.m\" -o -iname \"*.cpp\" | xargs clang-format -i", "cpplint": "cpplint --linelength=230 --filter=-legal/copyright,-whitespace/indent,-whitespace/comments,-whitespace/ending_newline,-build/include_order,-runtime/references,-readability/todo,-whitespace/blank_line,-whitespace/todo,-runtime/int,-build/c++11,-whitespace/parens --exclude=example --exclude=android/.cxx --exclude=cpp/webgpu --exclude=cpp/dawn --exclude=ios --exclude=android/build --exclude=node_modules --recursive .", - "install-dawn": "tsx scripts/install-dawn.ts", - "generate-package-swift": "tsx scripts/generate-package-swift.ts" + "check-dawn": "tsx scripts/check-dawn.ts" }, "keywords": [ "react-native", @@ -114,6 +109,9 @@ "ws": "^8.18.0", "yargs": "^17.7.2" }, + "dependencies": { + "react-native-webgpu-dawn": "154.2.0" + }, "peerDependencies": { "react": "*", "react-native": ">=0.81.0", diff --git a/packages/webgpu/react-native-webgpu.podspec b/packages/webgpu/react-native-webgpu.podspec index 48e51b464d..867f6395f1 100644 --- a/packages/webgpu/react-native-webgpu.podspec +++ b/packages/webgpu/react-native-webgpu.podspec @@ -1,8 +1,44 @@ require "json" +require "fileutils" package = JSON.parse(File.read(File.join(__dir__, "package.json"))) folly_compiler_flags = '-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1 -Wno-comma -Wno-shorten-64-to-32' +# Resolve a node package directory using Node's own module resolution +# (mirrors `require.resolve(pkg/package.json)`). A lambda rather than a `def`: +# CocoaPods evaluates the podspec inside the `Pod` module, where top-level +# methods are not reachable at the call site. +resolve_node_package = lambda do |name, base_dir| + script = "process.stdout.write(require('path').dirname(require.resolve('#{name}/package.json')))" + dir = Dir.chdir(base_dir) { `node -e "#{script}" 2>/dev/null`.strip } + dir.empty? ? nil : dir +end + +# Dawn, the WebGPU implementation, ships in the react-native-webgpu-dawn npm +# package this package depends on (react-native-skia's Graphite backend links +# the same one, so an app installing both contains exactly one Dawn). Its +# headers are used in place, but CocoaPods only vendors frameworks from inside +# the pod, so the xcframework is copied into libs/apple at `pod install` time. +# The copy is stamped with the package version and skipped when it already +# matches, which keeps CocoaPods' cache intact across installs. +dawn_dir = resolve_node_package.call('react-native-webgpu-dawn', __dir__) +if dawn_dir.nil? + raise "react-native-webgpu: the react-native-webgpu-dawn package was not found. " \ + "It ships the Dawn binaries this package links against; make sure " \ + "dependencies are installed (yarn install / npm install), then run `pod install` again." +end +dawn_version = JSON.parse(File.read(File.join(dawn_dir, 'package.json')))['version'].to_s +dawn_include = File.join(dawn_dir, 'include') +dawn_libs = File.join(__dir__, 'libs', 'apple') +dawn_marker = File.join(dawn_libs, '.version') +unless File.exist?(dawn_marker) && File.read(dawn_marker).strip == dawn_version + Pod::UI.puts "react-native-webgpu: installing Dawn (react-native-webgpu-dawn #{dawn_version})" + FileUtils.rm_rf(dawn_libs) + FileUtils.mkdir_p(dawn_libs) + FileUtils.cp_r(File.join(dawn_dir, 'libs', 'apple', 'libwebgpu_dawn.xcframework'), dawn_libs) + File.write(dawn_marker, dawn_version) +end + Pod::Spec.new do |s| s.name = "react-native-webgpu" s.version = package["version"] @@ -50,7 +86,7 @@ Pod::Spec.new do |s| end s.pod_target_xcconfig = { - 'HEADER_SEARCH_PATHS' => '$(PODS_TARGET_SRCROOT)/cpp', + 'HEADER_SEARCH_PATHS' => "$(PODS_TARGET_SRCROOT)/cpp \"#{dawn_include}\"", # Xcode's all-target headermaps let same-named headers leak across pods # (e.g. @shopify/react-native-skia keeps a jsi/ helper layer with # identical relative header paths). Resolve includes strictly through our @@ -66,7 +102,7 @@ Pod::Spec.new do |s| s.dependency "React-Core" s.compiler_flags = folly_compiler_flags s.pod_target_xcconfig = { - "HEADER_SEARCH_PATHS" => "\"$(PODS_ROOT)/boost\" \"$(PODS_TARGET_SRCROOT)/cpp\"", + "HEADER_SEARCH_PATHS" => "\"$(PODS_ROOT)/boost\" \"$(PODS_TARGET_SRCROOT)/cpp\" \"#{dawn_include}\"", "OTHER_CPLUSPLUSFLAGS" => "-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1", "CLANG_CXX_LANGUAGE_STANDARD" => "c++20" } diff --git a/packages/webgpu/scripts/apply-dawn-patches.sh b/packages/webgpu/scripts/apply-dawn-patches.sh deleted file mode 100755 index 84c232586f..0000000000 --- a/packages/webgpu/scripts/apply-dawn-patches.sh +++ /dev/null @@ -1,33 +0,0 @@ -#!/usr/bin/env bash -# Applies the patches in scripts/dawn-patches to the Dawn checkout before -# it is built: locally from `yarn build-dawn` (scripts/build/dawn.ts) and in CI -# from .github/workflows/build-dawn.yml. Each patch is an upstream change that -# the pinned Dawn commit does not carry yet; drop a patch once a Dawn bump -# includes it (this script then reports it as already present). -# -# Usage: apply-dawn-patches.sh [dawn-checkout] (default: externals/dawn) -set -euo pipefail - -script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -patches_dir="$script_dir/dawn-patches" -dawn_dir="${1:-$script_dir/../../../externals/dawn}" - -if [ ! -d "$dawn_dir/src/tint" ]; then - echo "❌ Dawn checkout not found at $dawn_dir (is the externals/dawn submodule checked out?)" >&2 - exit 1 -fi - -for patch in "$patches_dir"/*.patch; do - name="$(basename "$patch")" - if git -C "$dawn_dir" apply --check "$patch" 2>/dev/null; then - git -C "$dawn_dir" apply "$patch" - echo "🩹 Applied $name" - elif git -C "$dawn_dir" apply --reverse --check "$patch" 2>/dev/null; then - echo "✅ $name is already in the Dawn checkout (applied earlier, or the pinned Dawn carries it and the patch can be dropped)" - else - echo "❌ $name does not apply to $dawn_dir:" >&2 - git -C "$dawn_dir" apply --check "$patch" >&2 || true - echo " The patched code changed upstream. Check whether the pinned Dawn already carries an equivalent change and drop or refresh the patch." >&2 - exit 1 - fi -done diff --git a/packages/webgpu/scripts/build/apple.toolchain.cmake b/packages/webgpu/scripts/build/apple.toolchain.cmake deleted file mode 100644 index 0562c20023..0000000000 --- a/packages/webgpu/scripts/build/apple.toolchain.cmake +++ /dev/null @@ -1,1179 +0,0 @@ -# This file is part of the ios-cmake project. It was retrieved from -# https://github.com/leetal/ios-cmake.git, which is a fork of -# https://github.com/gerstrong/ios-cmake.git, which is a fork of -# https://github.com/cristeab/ios-cmake.git, which is a fork of -# https://code.google.com/p/ios-cmake/. Which in turn is based off of -# the Platform/Darwin.cmake and Platform/UnixPaths.cmake files which -# are included with CMake 2.8.4 -# -# The ios-cmake project is licensed under the new BSD license. -# -# Copyright (c) 2014, Bogdan Cristea and LTE Engineering Software, -# Kitware, Inc., Insight Software Consortium. All rights reserved. -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions -# are met: -# 1. Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# -# 2. Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# -# 3. Neither the name of the copyright holder nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -# POSSIBILITY OF SUCH DAMAGE. -# -# This file is based on the Platform/Darwin.cmake and -# Platform/UnixPaths.cmake files which are included with CMake 2.8.4 -# It has been altered for iOS development. -# -# Updated by Alex Stewart (alexs.mac@gmail.com) -# -# ***************************************************************************** -# Now maintained by Alexander Widerberg (widerbergaren [at] gmail.com) -# under the BSD-3-Clause license -# https://github.com/leetal/ios-cmake -# ***************************************************************************** -# -# INFORMATION / HELP -# -############################################################################### -# OPTIONS # -############################################################################### -# -# PLATFORM: (default "OS64") -# OS = Build for iPhoneOS. -# OS64 = Build for arm64 iphoneOS. -# OS64COMBINED = Build for arm64 x86_64 iphoneOS + iphoneOS Simulator. Combined into FAT STATIC lib (only supported on 3.14+ of CMake with "-G Xcode" argument in combination with the "cmake --install" CMake build step) -# SIMULATOR = Build for x86 i386 iphoneOS Simulator. -# SIMULATOR64 = Build for x86_64 iphoneOS Simulator. -# SIMULATORARM64 = Build for arm64 iphoneOS Simulator. -# SIMULATOR64COMBINED = Build for arm64 x86_64 iphoneOS Simulator. Combined into FAT STATIC lib (supported on 3.14+ of CMakewith "-G Xcode" argument ONLY) -# TVOS = Build for arm64 tvOS. -# TVOSCOMBINED = Build for arm64 x86_64 tvOS + tvOS Simulator. Combined into FAT STATIC lib (only supported on 3.14+ of CMake with "-G Xcode" argument in combination with the "cmake --install" CMake build step) -# SIMULATOR_TVOS = Build for x86_64 tvOS Simulator. -# SIMULATORARM64_TVOS = Build for arm64 tvOS Simulator. -# VISIONOSCOMBINED = Build for arm64 visionOS + visionOS Simulator. Combined into FAT STATIC lib (only supported on 3.14+ of CMake with "-G Xcode" argument in combination with the "cmake --install" CMake build step) -# VISIONOS = Build for arm64 visionOS. -# SIMULATOR_VISIONOS = Build for arm64 visionOS Simulator. -# WATCHOS = Build for armv7k arm64_32 for watchOS. -# WATCHOSCOMBINED = Build for armv7k arm64_32 x86_64 watchOS + watchOS Simulator. Combined into FAT STATIC lib (only supported on 3.14+ of CMake with "-G Xcode" argument in combination with the "cmake --install" CMake build step) -# SIMULATOR_WATCHOS = Build for x86_64 for watchOS Simulator. -# SIMULATORARM64_WATCHOS = Build for arm64 for watchOS Simulator. -# SIMULATOR_WATCHOSCOMBINED = Build for arm64 x86_64 for watchOS Simulator. Combined into FAT STATIC lib (supported on 3.14+ of CMakewith "-G Xcode" argument ONLY) -# MAC = Build for x86_64 macOS. -# MAC_ARM64 = Build for Apple Silicon macOS. -# MAC_UNIVERSAL = Combined build for x86_64 and Apple Silicon on macOS. -# MAC_CATALYST = Build for x86_64 macOS with Catalyst support (iOS toolchain on macOS). -# Note: The build argument "MACOSX_DEPLOYMENT_TARGET" can be used to control min-version of macOS -# MAC_CATALYST_ARM64 = Build for Apple Silicon macOS with Catalyst support (iOS toolchain on macOS). -# Note: The build argument "MACOSX_DEPLOYMENT_TARGET" can be used to control min-version of macOS -# MAC_CATALYST_UNIVERSAL = Combined build for x86_64 and Apple Silicon on Catalyst. -# -# CMAKE_OSX_SYSROOT: Path to the SDK to use. By default this is -# automatically determined from PLATFORM and xcodebuild, but -# can also be manually specified (although this should not be required). -# -# CMAKE_DEVELOPER_ROOT: Path to the Developer directory for the platform -# being compiled for. By default, this is automatically determined from -# CMAKE_OSX_SYSROOT, but can also be manually specified (although this should -# not be required). -# -# DEPLOYMENT_TARGET: Minimum SDK version to target. Default 6.0 on watchOS, 13.0 on tvOS+iOS/iPadOS, 11.0 on macOS, 1.0 on visionOS -# -# NAMED_LANGUAGE_SUPPORT: -# ON (default) = Will require "enable_language(OBJC) and/or enable_language(OBJCXX)" for full OBJC|OBJCXX support -# OFF = Will embed the OBJC and OBJCXX flags into the CMAKE_C_FLAGS and CMAKE_CXX_FLAGS (legacy behavior, CMake version < 3.16) -# -# ENABLE_BITCODE: (ON|OFF) Enables or disables bitcode support. Default OFF -# -# ENABLE_ARC: (ON|OFF) Enables or disables ARC support. Default ON (ARC enabled by default) -# -# ENABLE_VISIBILITY: (ON|OFF) Enables or disables symbol visibility support. Default OFF (visibility hidden by default) -# -# ENABLE_STRICT_TRY_COMPILE: (ON|OFF) Enables or disables strict try_compile() on all Check* directives (will run linker -# to actually check if linking is possible). Default OFF (will set CMAKE_TRY_COMPILE_TARGET_TYPE to STATIC_LIBRARY) -# -# ARCHS: (armv7 armv7s armv7k arm64 arm64_32 i386 x86_64) If specified, will override the default architectures for the given PLATFORM -# OS = armv7 armv7s arm64 (if applicable) -# OS64 = arm64 (if applicable) -# SIMULATOR = i386 -# SIMULATOR64 = x86_64 -# SIMULATORARM64 = arm64 -# TVOS = arm64 -# SIMULATOR_TVOS = x86_64 (i386 has since long been deprecated) -# SIMULATORARM64_TVOS = arm64 -# WATCHOS = armv7k arm64_32 (if applicable) -# SIMULATOR_WATCHOS = x86_64 (i386 has since long been deprecated) -# SIMULATORARM64_WATCHOS = arm64 -# MAC = x86_64 -# MAC_ARM64 = arm64 -# MAC_UNIVERSAL = x86_64 arm64 -# MAC_CATALYST = x86_64 -# MAC_CATALYST_ARM64 = arm64 -# MAC_CATALYST_UNIVERSAL = x86_64 arm64 -# -# NOTE: When manually specifying ARCHS, put a semi-colon between the entries. E.g., -DARCHS="armv7;arm64" -# -############################################################################### -# END OPTIONS # -############################################################################### -# -# This toolchain defines the following properties (available via get_property()) for use externally: -# -# PLATFORM: The currently targeted platform. -# XCODE_VERSION: Version number (not including Build version) of Xcode detected. -# SDK_VERSION: Version of SDK being used. -# OSX_ARCHITECTURES: Architectures being compiled for (generated from PLATFORM). -# APPLE_TARGET_TRIPLE: Used by autoconf build systems. NOTE: If "ARCHS" is overridden, this will *NOT* be set! -# -# This toolchain defines the following macros for use externally: -# -# set_xcode_property (TARGET XCODE_PROPERTY XCODE_VALUE XCODE_VARIANT) -# A convenience macro for setting xcode specific properties on targets. -# Available variants are: All, Release, RelWithDebInfo, Debug, MinSizeRel -# example: set_xcode_property (myioslib IPHONEOS_DEPLOYMENT_TARGET "3.1" "all"). -# -# find_host_package (PROGRAM ARGS) -# A macro used to find executable programs on the host system, not within the -# environment. Thanks to the android-cmake project for providing the -# command. -# - -cmake_minimum_required(VERSION 3.8.0) - -# CMake invokes the toolchain file twice during the first build, but only once during subsequent rebuilds. -# NOTE: To improve single-library build-times, provide the flag "OS_SINGLE_BUILD" as a build argument. -if(DEFINED OS_SINGLE_BUILD AND DEFINED ENV{_IOS_TOOLCHAIN_HAS_RUN}) - return() -endif() -set(ENV{_IOS_TOOLCHAIN_HAS_RUN} true) - -# List of supported platform values -list(APPEND _supported_platforms - "OS" "OS64" "OS64COMBINED" "SIMULATOR" "SIMULATOR64" "SIMULATORARM64" "SIMULATOR64COMBINED" - "TVOS" "TVOSCOMBINED" "SIMULATOR_TVOS" "SIMULATORARM64_TVOS" - "WATCHOS" "WATCHOSCOMBINED" "SIMULATOR_WATCHOS" "SIMULATORARM64_WATCHOS" "SIMULATOR_WATCHOSCOMBINED" - "MAC" "MAC_ARM64" "MAC_UNIVERSAL" - "VISIONOS" "SIMULATOR_VISIONOS" "VISIONOSCOMBINED" - "MAC_CATALYST" "MAC_CATALYST_ARM64" "MAC_CATALYST_UNIVERSAL") - -# Cache what generator is used -set(USED_CMAKE_GENERATOR "${CMAKE_GENERATOR}") - -# Check if using a CMake version capable of building combined FAT builds (simulator and target slices combined in one static lib) -if(${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.14") - set(MODERN_CMAKE YES) -endif() - -# Get the Xcode version being used. -# Problem: CMake runs toolchain files multiple times, but can't read cache variables on some runs. -# Workaround: On the first run (in which cache variables are always accessible), set an intermediary environment variable. -# -# NOTE: This pattern is used in many places in this toolchain to speed up checks of all sorts -if(DEFINED XCODE_VERSION_INT) - # Environment variables are always preserved. - set(ENV{_XCODE_VERSION_INT} "${XCODE_VERSION_INT}") -elseif(DEFINED ENV{_XCODE_VERSION_INT}) - set(XCODE_VERSION_INT "$ENV{_XCODE_VERSION_INT}") -elseif(NOT DEFINED XCODE_VERSION_INT) - find_program(XCODEBUILD_EXECUTABLE xcodebuild) - if(NOT XCODEBUILD_EXECUTABLE) - message(FATAL_ERROR "xcodebuild not found. Please install either the standalone commandline tools or Xcode.") - endif() - execute_process(COMMAND ${XCODEBUILD_EXECUTABLE} -version - OUTPUT_VARIABLE XCODE_VERSION_INT - ERROR_QUIET - OUTPUT_STRIP_TRAILING_WHITESPACE) - string(REGEX MATCH "Xcode [0-9\\.]+" XCODE_VERSION_INT "${XCODE_VERSION_INT}") - string(REGEX REPLACE "Xcode ([0-9\\.]+)" "\\1" XCODE_VERSION_INT "${XCODE_VERSION_INT}") - set(XCODE_VERSION_INT "${XCODE_VERSION_INT}" CACHE INTERNAL "") -endif() - -# Assuming that xcode 12.0 is installed you most probably have ios sdk 14.0 or later installed (tested on Big Sur) -# if you don't set a deployment target it will be set the way you only get 64-bit builds -#if(NOT DEFINED DEPLOYMENT_TARGET AND XCODE_VERSION_INT VERSION_GREATER 12.0) -# Temporarily fix the arm64 issues in CMake install-combined by excluding arm64 for simulator builds (needed for Apple Silicon...) -# set(CMAKE_XCODE_ATTRIBUTE_EXCLUDED_ARCHS[sdk=iphonesimulator*] "arm64") -#endif() - -# Check if the platform variable is set -if(DEFINED PLATFORM) - # Environment variables are always preserved. - set(ENV{_PLATFORM} "${PLATFORM}") -elseif(DEFINED ENV{_PLATFORM}) - set(PLATFORM "$ENV{_PLATFORM}") -elseif(NOT DEFINED PLATFORM) - message(FATAL_ERROR "PLATFORM argument not set. Bailing configure since I don't know what target you want to build for!") -endif () - -if(PLATFORM MATCHES ".*COMBINED" AND NOT CMAKE_GENERATOR MATCHES "Xcode") - message(FATAL_ERROR "The combined builds support requires Xcode to be used as a generator via '-G Xcode' command-line argument in CMake") -endif() - -# Safeguard that the platform value is set and is one of the supported values -list(FIND _supported_platforms ${PLATFORM} contains_PLATFORM) -if("${contains_PLATFORM}" EQUAL "-1") - string(REPLACE ";" "\n * " _supported_platforms_formatted "${_supported_platforms}") - message(FATAL_ERROR " Invalid PLATFORM specified! Current value: ${PLATFORM}.\n" - " Supported PLATFORM values: \n * ${_supported_platforms_formatted}") -endif() - -# Check if Apple Silicon is supported -if(PLATFORM MATCHES "^(MAC_ARM64)$|^(MAC_CATALYST_ARM64)$|^(MAC_UNIVERSAL)$|^(MAC_CATALYST_UNIVERSAL)$" AND ${CMAKE_VERSION} VERSION_LESS "3.19.5") - message(FATAL_ERROR "Apple Silicon builds requires a minimum of CMake 3.19.5") -endif() - -# Touch the toolchain variable to suppress the "unused variable" warning. -# This happens if CMake is invoked with the same command line the second time. -if(CMAKE_TOOLCHAIN_FILE) -endif() - -# Fix for PThread library not in path -set(CMAKE_THREAD_LIBS_INIT "-lpthread") -set(CMAKE_HAVE_THREADS_LIBRARY 1) -set(CMAKE_USE_WIN32_THREADS_INIT 0) -set(CMAKE_USE_PTHREADS_INIT 1) - -# Specify named language support defaults. -if(NOT DEFINED NAMED_LANGUAGE_SUPPORT AND ${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.16") - set(NAMED_LANGUAGE_SUPPORT ON) - message(STATUS "[DEFAULTS] Using explicit named language support! E.g., enable_language(CXX) is needed in the project files.") -elseif(NOT DEFINED NAMED_LANGUAGE_SUPPORT AND ${CMAKE_VERSION} VERSION_LESS "3.16") - set(NAMED_LANGUAGE_SUPPORT OFF) - message(STATUS "[DEFAULTS] Disabling explicit named language support. Falling back to legacy behavior.") -elseif(DEFINED NAMED_LANGUAGE_SUPPORT AND ${CMAKE_VERSION} VERSION_LESS "3.16") - message(FATAL_ERROR "CMake named language support for OBJC and OBJCXX was added in CMake 3.16.") -endif() -set(NAMED_LANGUAGE_SUPPORT_INT ${NAMED_LANGUAGE_SUPPORT} CACHE BOOL - "Whether or not to enable explicit named language support" FORCE) - -# Specify the minimum version of the deployment target. -if(NOT DEFINED DEPLOYMENT_TARGET) - if (PLATFORM MATCHES "WATCHOS") - # Unless specified, SDK version 6.0 is used by default as minimum target version (watchOS). - set(DEPLOYMENT_TARGET "6.0") - elseif(PLATFORM STREQUAL "MAC") - # Unless specified, SDK version 11.0 (Big Sur) is used by default as the minimum target version (macOS on x86). - set(DEPLOYMENT_TARGET "11.0") - elseif(PLATFORM STREQUAL "VISIONOS" OR PLATFORM STREQUAL "SIMULATOR_VISIONOS" OR PLATFORM STREQUAL "VISIONOSCOMBINED") - # Unless specified, SDK version 1.0 is used by default as minimum target version (visionOS). - set(DEPLOYMENT_TARGET "1.0") - elseif(PLATFORM STREQUAL "MAC_ARM64") - # Unless specified, SDK version 11.0 (Big Sur) is used by default as the minimum target version (macOS on arm). - set(DEPLOYMENT_TARGET "11.0") - elseif(PLATFORM STREQUAL "MAC_UNIVERSAL") - # Unless specified, SDK version 11.0 (Big Sur) is used by default as minimum target version for universal builds. - set(DEPLOYMENT_TARGET "11.0") - elseif(PLATFORM STREQUAL "MAC_CATALYST" OR PLATFORM STREQUAL "MAC_CATALYST_ARM64" OR PLATFORM STREQUAL "MAC_CATALYST_UNIVERSAL") - # Unless specified, SDK version 13.1 is used by default as the minimum target version (mac catalyst minimum requirement). - set(DEPLOYMENT_TARGET "13.1") - else() - # Unless specified, SDK version 13.0 is used by default as the minimum target version (iOS, tvOS). - set(DEPLOYMENT_TARGET "13.0") - endif() - message(STATUS "[DEFAULTS] Using the default min-version since DEPLOYMENT_TARGET not provided!") -elseif(DEFINED DEPLOYMENT_TARGET AND PLATFORM MATCHES "^MAC_CATALYST" AND ${DEPLOYMENT_TARGET} VERSION_LESS "13.1") - message(FATAL_ERROR "Mac Catalyst builds requires a minimum deployment target of 13.1!") -endif() - -# Store the DEPLOYMENT_TARGET in the cache -set(DEPLOYMENT_TARGET "${DEPLOYMENT_TARGET}" CACHE INTERNAL "") - -# Handle the case where we are targeting iOS and a version above 10.3.4 (32-bit support dropped officially) -if(PLATFORM STREQUAL "OS" AND DEPLOYMENT_TARGET VERSION_GREATER_EQUAL 10.3.4) - set(PLATFORM "OS64") - message(STATUS "Targeting minimum SDK version ${DEPLOYMENT_TARGET}. Dropping 32-bit support.") -elseif(PLATFORM STREQUAL "SIMULATOR" AND DEPLOYMENT_TARGET VERSION_GREATER_EQUAL 10.3.4) - set(PLATFORM "SIMULATOR64") - message(STATUS "Targeting minimum SDK version ${DEPLOYMENT_TARGET}. Dropping 32-bit support.") -endif() - -set(PLATFORM_INT "${PLATFORM}") - -if(DEFINED ARCHS) - string(REPLACE ";" "-" ARCHS_SPLIT "${ARCHS}") -endif() - -# Determine the platform name and architectures for use in xcodebuild commands -# from the specified PLATFORM_INT name. -if(PLATFORM_INT STREQUAL "OS") - set(SDK_NAME iphoneos) - if(NOT ARCHS) - set(ARCHS armv7 armv7s arm64) - set(APPLE_TARGET_TRIPLE_INT arm-apple-ios${DEPLOYMENT_TARGET}) - else() - set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-ios${DEPLOYMENT_TARGET}) - endif() -elseif(PLATFORM_INT STREQUAL "OS64") - set(SDK_NAME iphoneos) - if(NOT ARCHS) - if (XCODE_VERSION_INT VERSION_GREATER 10.0) - set(ARCHS arm64) # FIXME: Add arm64e when Apple has fixed the integration issues with it, libarclite_iphoneos.a is currently missing bitcode markers for example - else() - set(ARCHS arm64) - endif() - set(APPLE_TARGET_TRIPLE_INT arm64-apple-ios${DEPLOYMENT_TARGET}) - else() - set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-ios${DEPLOYMENT_TARGET}) - endif() -elseif(PLATFORM_INT STREQUAL "OS64COMBINED") - set(SDK_NAME iphoneos) - if(MODERN_CMAKE) - if(NOT ARCHS) - if (XCODE_VERSION_INT VERSION_GREATER 12.0) - set(ARCHS arm64 x86_64) - set(CMAKE_XCODE_ATTRIBUTE_ARCHS[sdk=iphoneos*] "arm64") - set(CMAKE_XCODE_ATTRIBUTE_ARCHS[sdk=iphonesimulator*] "x86_64 arm64") - set(CMAKE_XCODE_ATTRIBUTE_VALID_ARCHS[sdk=iphoneos*] "arm64") - set(CMAKE_XCODE_ATTRIBUTE_VALID_ARCHS[sdk=iphonesimulator*] "x86_64 arm64") - else() - set(ARCHS arm64 x86_64) - set(CMAKE_XCODE_ATTRIBUTE_ARCHS[sdk=iphoneos*] "arm64") - set(CMAKE_XCODE_ATTRIBUTE_ARCHS[sdk=iphonesimulator*] "x86_64") - set(CMAKE_XCODE_ATTRIBUTE_VALID_ARCHS[sdk=iphoneos*] "arm64") - set(CMAKE_XCODE_ATTRIBUTE_VALID_ARCHS[sdk=iphonesimulator*] "x86_64") - endif() - set(APPLE_TARGET_TRIPLE_INT arm64-x86_64-apple-ios${DEPLOYMENT_TARGET}) - else() - set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-ios${DEPLOYMENT_TARGET}) - endif() - else() - message(FATAL_ERROR "Please make sure that you are running CMake 3.14+ to make the OS64COMBINED setting work") - endif() -elseif(PLATFORM_INT STREQUAL "SIMULATOR64COMBINED") - set(SDK_NAME iphonesimulator) - if(MODERN_CMAKE) - if(NOT ARCHS) - if (XCODE_VERSION_INT VERSION_GREATER 12.0) - set(ARCHS arm64 x86_64) # FIXME: Add arm64e when Apple have fixed the integration issues with it, libarclite_iphoneos.a is currently missing bitcode markers for example - set(CMAKE_XCODE_ATTRIBUTE_ARCHS[sdk=iphoneos*] "") - set(CMAKE_XCODE_ATTRIBUTE_ARCHS[sdk=iphonesimulator*] "x86_64 arm64") - set(CMAKE_XCODE_ATTRIBUTE_VALID_ARCHS[sdk=iphoneos*] "") - set(CMAKE_XCODE_ATTRIBUTE_VALID_ARCHS[sdk=iphonesimulator*] "x86_64 arm64") - else() - set(ARCHS arm64 x86_64) - set(CMAKE_XCODE_ATTRIBUTE_ARCHS[sdk=iphoneos*] "") - set(CMAKE_XCODE_ATTRIBUTE_ARCHS[sdk=iphonesimulator*] "x86_64") - set(CMAKE_XCODE_ATTRIBUTE_VALID_ARCHS[sdk=iphoneos*] "") - set(CMAKE_XCODE_ATTRIBUTE_VALID_ARCHS[sdk=iphonesimulator*] "x86_64") - endif() - set(APPLE_TARGET_TRIPLE_INT aarch64-x86_64-apple-ios${DEPLOYMENT_TARGET}-simulator) - else() - set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-ios${DEPLOYMENT_TARGET}-simulator) - endif() - else() - message(FATAL_ERROR "Please make sure that you are running CMake 3.14+ to make the SIMULATOR64COMBINED setting work") - endif() -elseif(PLATFORM_INT STREQUAL "SIMULATOR") - set(SDK_NAME iphonesimulator) - if(NOT ARCHS) - set(ARCHS i386) - set(APPLE_TARGET_TRIPLE_INT i386-apple-ios${DEPLOYMENT_TARGET}-simulator) - else() - set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-ios${DEPLOYMENT_TARGET}-simulator) - endif() - message(DEPRECATION "SIMULATOR IS DEPRECATED. Consider using SIMULATOR64 instead.") -elseif(PLATFORM_INT STREQUAL "SIMULATOR64") - set(SDK_NAME iphonesimulator) - if(NOT ARCHS) - set(ARCHS x86_64) - set(APPLE_TARGET_TRIPLE_INT x86_64-apple-ios${DEPLOYMENT_TARGET}-simulator) - else() - set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-ios${DEPLOYMENT_TARGET}-simulator) - endif() -elseif(PLATFORM_INT STREQUAL "SIMULATORARM64") - set(SDK_NAME iphonesimulator) - if(NOT ARCHS) - set(ARCHS arm64) - set(APPLE_TARGET_TRIPLE_INT arm64-apple-ios${DEPLOYMENT_TARGET}-simulator) - else() - set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-ios${DEPLOYMENT_TARGET}-simulator) - endif() -elseif(PLATFORM_INT STREQUAL "TVOS") - set(SDK_NAME appletvos) - if(NOT ARCHS) - set(ARCHS arm64) - set(APPLE_TARGET_TRIPLE_INT arm64-apple-tvos${DEPLOYMENT_TARGET}) - else() - set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-tvos${DEPLOYMENT_TARGET}) - endif() -elseif (PLATFORM_INT STREQUAL "TVOSCOMBINED") - set(SDK_NAME appletvos) - if(MODERN_CMAKE) - if(NOT ARCHS) - set(ARCHS arm64 x86_64) - set(APPLE_TARGET_TRIPLE_INT arm64-x86_64-apple-tvos${DEPLOYMENT_TARGET}) - set(CMAKE_XCODE_ATTRIBUTE_ARCHS[sdk=appletvos*] "arm64") - set(CMAKE_XCODE_ATTRIBUTE_ARCHS[sdk=appletvsimulator*] "x86_64 arm64") - set(CMAKE_XCODE_ATTRIBUTE_VALID_ARCHS[sdk=appletvos*] "arm64") - set(CMAKE_XCODE_ATTRIBUTE_VALID_ARCHS[sdk=appletvsimulator*] "x86_64 arm64") - else() - set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-tvos${DEPLOYMENT_TARGET}) - endif() - else() - message(FATAL_ERROR "Please make sure that you are running CMake 3.14+ to make the TVOSCOMBINED setting work") - endif() -elseif(PLATFORM_INT STREQUAL "SIMULATOR_TVOS") - set(SDK_NAME appletvsimulator) - if(NOT ARCHS) - set(ARCHS x86_64) - set(APPLE_TARGET_TRIPLE_INT x86_64-apple-tvos${DEPLOYMENT_TARGET}-simulator) - else() - set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-tvos${DEPLOYMENT_TARGET}-simulator) - endif() -elseif(PLATFORM_INT STREQUAL "SIMULATORARM64_TVOS") - set(SDK_NAME appletvsimulator) - if(NOT ARCHS) - set(ARCHS arm64) - set(APPLE_TARGET_TRIPLE_INT arm64-apple-tvos${DEPLOYMENT_TARGET}-simulator) - else() - set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-tvos${DEPLOYMENT_TARGET}-simulator) - endif() -elseif(PLATFORM_INT STREQUAL "WATCHOS") - set(SDK_NAME watchos) - if(NOT ARCHS) - if (XCODE_VERSION_INT VERSION_GREATER 10.0) - set(ARCHS armv7k arm64_32) - set(APPLE_TARGET_TRIPLE_INT arm64_32-apple-watchos${DEPLOYMENT_TARGET}) - else() - set(ARCHS armv7k) - set(APPLE_TARGET_TRIPLE_INT arm-apple-watchos${DEPLOYMENT_TARGET}) - endif() - else() - set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-watchos${DEPLOYMENT_TARGET}) - endif() -elseif(PLATFORM_INT STREQUAL "WATCHOSCOMBINED") - set(SDK_NAME watchos) - if(MODERN_CMAKE) - if(NOT ARCHS) - if (XCODE_VERSION_INT VERSION_GREATER 10.0) - set(ARCHS armv7k arm64_32 x86_64) - set(APPLE_TARGET_TRIPLE_INT arm64_32-x86_64-apple-watchos${DEPLOYMENT_TARGET}) - set(CMAKE_XCODE_ATTRIBUTE_ARCHS[sdk=watchos*] "armv7k arm64_32") - set(CMAKE_XCODE_ATTRIBUTE_ARCHS[sdk=watchsimulator*] "x86_64") - set(CMAKE_XCODE_ATTRIBUTE_VALID_ARCHS[sdk=watchos*] "armv7k arm64_32") - set(CMAKE_XCODE_ATTRIBUTE_VALID_ARCHS[sdk=watchsimulator*] "x86_64") - else() - set(ARCHS armv7k i386) - set(APPLE_TARGET_TRIPLE_INT arm-i386-apple-watchos${DEPLOYMENT_TARGET}) - set(CMAKE_XCODE_ATTRIBUTE_ARCHS[sdk=watchos*] "armv7k") - set(CMAKE_XCODE_ATTRIBUTE_ARCHS[sdk=watchsimulator*] "i386") - set(CMAKE_XCODE_ATTRIBUTE_VALID_ARCHS[sdk=watchos*] "armv7k") - set(CMAKE_XCODE_ATTRIBUTE_VALID_ARCHS[sdk=watchsimulator*] "i386") - endif() - else() - set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-watchos${DEPLOYMENT_TARGET}) - endif() - else() - message(FATAL_ERROR "Please make sure that you are running CMake 3.14+ to make the WATCHOSCOMBINED setting work") - endif() -elseif(PLATFORM_INT STREQUAL "SIMULATOR_WATCHOS") - set(SDK_NAME watchsimulator) - if(NOT ARCHS) - if (XCODE_VERSION_INT VERSION_GREATER 10.0) - set(ARCHS x86_64) - set(APPLE_TARGET_TRIPLE_INT x86_64-apple-watchos${DEPLOYMENT_TARGET}-simulator) - else() - set(ARCHS i386) - set(APPLE_TARGET_TRIPLE_INT i386-apple-watchos${DEPLOYMENT_TARGET}-simulator) - endif() - else() - set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-watchos${DEPLOYMENT_TARGET}-simulator) - endif() -elseif(PLATFORM_INT STREQUAL "SIMULATORARM64_WATCHOS") - set(SDK_NAME watchsimulator) - if(NOT ARCHS) - set(ARCHS arm64) - set(APPLE_TARGET_TRIPLE_INT arm64-apple-watchos${DEPLOYMENT_TARGET}-simulator) - else() - set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-watchos${DEPLOYMENT_TARGET}-simulator) - endif() -elseif(PLATFORM_INT STREQUAL "SIMULATOR_WATCHOSCOMBINED") - set(SDK_NAME watchsimulator) - if(MODERN_CMAKE) - if(NOT ARCHS) - if (XCODE_VERSION_INT VERSION_GREATER 12.0) - set(ARCHS arm64 x86_64) - set(CMAKE_XCODE_ATTRIBUTE_ARCHS[sdk=watchos*] "") - set(CMAKE_XCODE_ATTRIBUTE_ARCHS[sdk=watchsimulator*] "arm64 x86_64") - set(CMAKE_XCODE_ATTRIBUTE_VALID_ARCHS[sdk=watchos*] "") - set(CMAKE_XCODE_ATTRIBUTE_VALID_ARCHS[sdk=watchsimulator*] "arm64 x86_64") - set(APPLE_TARGET_TRIPLE_INT arm64_x86_64-apple-watchos${DEPLOYMENT_TARGET}-simulator) - else() - set(ARCHS arm64 i386) - set(CMAKE_XCODE_ATTRIBUTE_ARCHS[sdk=watchos*] "") - set(CMAKE_XCODE_ATTRIBUTE_ARCHS[sdk=watchsimulator*] "i386") - set(CMAKE_XCODE_ATTRIBUTE_VALID_ARCHS[sdk=watchos*] "") - set(CMAKE_XCODE_ATTRIBUTE_VALID_ARCHS[sdk=watchsimulator*] "i386") - set(APPLE_TARGET_TRIPLE_INT arm64_i386-apple-watchos${DEPLOYMENT_TARGET}-simulator) - endif() - else() - set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-watchos${DEPLOYMENT_TARGET}-simulator) - endif() - else() - message(FATAL_ERROR "Please make sure that you are running CMake 3.14+ to make the SIMULATOR_WATCHOSCOMBINED setting work") - endif() -elseif(PLATFORM_INT STREQUAL "SIMULATOR_VISIONOS") - set(SDK_NAME xrsimulator) - if(NOT ARCHS) - set(ARCHS arm64) - set(APPLE_TARGET_TRIPLE_INT arm64-apple-xros${DEPLOYMENT_TARGET}-simulator) - else() - set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-xros${DEPLOYMENT_TARGET}-simulator) - endif() -elseif(PLATFORM_INT STREQUAL "VISIONOS") - set(SDK_NAME xros) - if(NOT ARCHS) - set(ARCHS arm64) - set(APPLE_TARGET_TRIPLE_INT arm64-apple-xros${DEPLOYMENT_TARGET}) - else() - set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-xros${DEPLOYMENT_TARGET}) - endif() -elseif(PLATFORM_INT STREQUAL "VISIONOSCOMBINED") - set(SDK_NAME xros) - if(MODERN_CMAKE) - if(NOT ARCHS) - set(ARCHS arm64) - set(APPLE_TARGET_TRIPLE_INT arm64-apple-xros${DEPLOYMENT_TARGET}) - set(CMAKE_XCODE_ATTRIBUTE_ARCHS[sdk=xros*] "arm64") - set(CMAKE_XCODE_ATTRIBUTE_ARCHS[sdk=xrsimulator*] "arm64") - else() - set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-xros${DEPLOYMENT_TARGET}) - endif() - else() - message(FATAL_ERROR "Please make sure that you are running CMake 3.14+ to make the VISIONOSCOMBINED setting work") - endif() -elseif(PLATFORM_INT STREQUAL "MAC" OR PLATFORM_INT STREQUAL "MAC_CATALYST") - set(SDK_NAME macosx) - if(NOT ARCHS) - set(ARCHS x86_64) - endif() - string(REPLACE ";" "-" ARCHS_SPLIT "${ARCHS}") - if(PLATFORM_INT STREQUAL "MAC") - set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-macosx${DEPLOYMENT_TARGET}) - elseif(PLATFORM_INT STREQUAL "MAC_CATALYST") - set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-ios${DEPLOYMENT_TARGET}-macabi) - endif() -elseif(PLATFORM_INT MATCHES "^(MAC_ARM64)$|^(MAC_CATALYST_ARM64)$") - set(SDK_NAME macosx) - if(NOT ARCHS) - set(ARCHS arm64) - endif() - string(REPLACE ";" "-" ARCHS_SPLIT "${ARCHS}") - if(PLATFORM_INT STREQUAL "MAC_ARM64") - set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-macosx${DEPLOYMENT_TARGET}) - elseif(PLATFORM_INT STREQUAL "MAC_CATALYST_ARM64") - set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-ios${DEPLOYMENT_TARGET}-macabi) - endif() -elseif(PLATFORM_INT STREQUAL "MAC_UNIVERSAL") - set(SDK_NAME macosx) - if(NOT ARCHS) - set(ARCHS "x86_64;arm64") - endif() - # For universal builds, don't set target triple - let CMake handle it - # string(REPLACE ";" "-" ARCHS_SPLIT "${ARCHS}") - # set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-macosx${DEPLOYMENT_TARGET}) -elseif(PLATFORM_INT STREQUAL "MAC_CATALYST_UNIVERSAL") - set(SDK_NAME macosx) - if(NOT ARCHS) - set(ARCHS "x86_64;arm64") - endif() - string(REPLACE ";" "-" ARCHS_SPLIT "${ARCHS}") - set(APPLE_TARGET_TRIPLE_INT apple-ios${DEPLOYMENT_TARGET}-macabi) -else() - message(FATAL_ERROR "Invalid PLATFORM: ${PLATFORM_INT}") -endif() - -string(REPLACE ";" " " ARCHS_SPACED "${ARCHS}") - -if(MODERN_CMAKE AND PLATFORM_INT MATCHES ".*COMBINED" AND NOT CMAKE_GENERATOR MATCHES "Xcode") - message(FATAL_ERROR "The COMBINED options only work with Xcode generator, -G Xcode") -endif() - -if(CMAKE_GENERATOR MATCHES "Xcode" AND PLATFORM_INT MATCHES "^MAC_CATALYST") - set(CMAKE_XCODE_ATTRIBUTE_CLANG_CXX_LIBRARY "libc++") - set(CMAKE_XCODE_ATTRIBUTE_SUPPORTED_PLATFORMS "macosx") - set(CMAKE_XCODE_ATTRIBUTE_SUPPORTS_MACCATALYST "YES") - if(NOT DEFINED MACOSX_DEPLOYMENT_TARGET) - set(CMAKE_XCODE_ATTRIBUTE_MACOSX_DEPLOYMENT_TARGET "10.15") - else() - set(CMAKE_XCODE_ATTRIBUTE_MACOSX_DEPLOYMENT_TARGET "${MACOSX_DEPLOYMENT_TARGET}") - endif() -elseif(CMAKE_GENERATOR MATCHES "Xcode") - set(CMAKE_XCODE_ATTRIBUTE_CLANG_CXX_LIBRARY "libc++") - set(CMAKE_XCODE_ATTRIBUTE_IPHONEOS_DEPLOYMENT_TARGET "${DEPLOYMENT_TARGET}") - if(NOT PLATFORM_INT MATCHES ".*COMBINED") - set(CMAKE_XCODE_ATTRIBUTE_ARCHS[sdk=${SDK_NAME}*] "${ARCHS_SPACED}") - set(CMAKE_XCODE_ATTRIBUTE_VALID_ARCHS[sdk=${SDK_NAME}*] "${ARCHS_SPACED}") - endif() -endif() - -# If the user did not specify the SDK root to use, then query xcodebuild for it. -if(DEFINED CMAKE_OSX_SYSROOT_INT) - # Environment variables are always preserved. - set(ENV{_CMAKE_OSX_SYSROOT_INT} "${CMAKE_OSX_SYSROOT_INT}") -elseif(DEFINED ENV{_CMAKE_OSX_SYSROOT_INT}) - set(CMAKE_OSX_SYSROOT_INT "$ENV{_CMAKE_OSX_SYSROOT_INT}") -elseif(NOT DEFINED CMAKE_OSX_SYSROOT_INT) - execute_process(COMMAND ${XCODEBUILD_EXECUTABLE} -version -sdk ${SDK_NAME} Path - OUTPUT_VARIABLE CMAKE_OSX_SYSROOT_INT - ERROR_QUIET - OUTPUT_STRIP_TRAILING_WHITESPACE) -endif() - -if (NOT DEFINED CMAKE_OSX_SYSROOT_INT AND NOT DEFINED CMAKE_OSX_SYSROOT) - message(SEND_ERROR "Please make sure that Xcode is installed and that the toolchain" - "is pointing to the correct path. Please run:" - "sudo xcode-select -s /Applications/Xcode.app/Contents/Developer" - "and see if that fixes the problem for you.") - message(FATAL_ERROR "Invalid CMAKE_OSX_SYSROOT: ${CMAKE_OSX_SYSROOT} " - "does not exist.") -elseif(DEFINED CMAKE_OSX_SYSROOT_INT) - set(CMAKE_OSX_SYSROOT_INT "${CMAKE_OSX_SYSROOT_INT}" CACHE INTERNAL "") - # Specify the location or name of the platform SDK to be used in CMAKE_OSX_SYSROOT. - set(CMAKE_OSX_SYSROOT "${CMAKE_OSX_SYSROOT_INT}" CACHE INTERNAL "") -endif() - -# Use bitcode or not -if(NOT DEFINED ENABLE_BITCODE) - message(STATUS "[DEFAULTS] Disabling bitcode support by default. ENABLE_BITCODE not provided for override!") - set(ENABLE_BITCODE OFF) -endif() -set(ENABLE_BITCODE_INT ${ENABLE_BITCODE} CACHE BOOL - "Whether or not to enable bitcode" FORCE) -# Use ARC or not -if(NOT DEFINED ENABLE_ARC) - # Unless specified, enable ARC support by default - set(ENABLE_ARC ON) - message(STATUS "[DEFAULTS] Enabling ARC support by default. ENABLE_ARC not provided!") -endif() -set(ENABLE_ARC_INT ${ENABLE_ARC} CACHE BOOL "Whether or not to enable ARC" FORCE) -# Use hidden visibility or not -if(NOT DEFINED ENABLE_VISIBILITY) - # Unless specified, disable symbols visibility by default - set(ENABLE_VISIBILITY OFF) - message(STATUS "[DEFAULTS] Hiding symbols visibility by default. ENABLE_VISIBILITY not provided!") -endif() -set(ENABLE_VISIBILITY_INT ${ENABLE_VISIBILITY} CACHE BOOL "Whether or not to hide symbols from the dynamic linker (-fvisibility=hidden)" FORCE) -# Set strict compiler checks or not -if(NOT DEFINED ENABLE_STRICT_TRY_COMPILE) - # Unless specified, disable strict try_compile() - set(ENABLE_STRICT_TRY_COMPILE OFF) - message(STATUS "[DEFAULTS] Using NON-strict compiler checks by default. ENABLE_STRICT_TRY_COMPILE not provided!") -endif() -set(ENABLE_STRICT_TRY_COMPILE_INT ${ENABLE_STRICT_TRY_COMPILE} CACHE BOOL - "Whether or not to use strict compiler checks" FORCE) - -# Get the SDK version information. -if(DEFINED SDK_VERSION) - # Environment variables are always preserved. - set(ENV{_SDK_VERSION} "${SDK_VERSION}") -elseif(DEFINED ENV{_SDK_VERSION}) - set(SDK_VERSION "$ENV{_SDK_VERSION}") -elseif(NOT DEFINED SDK_VERSION) - execute_process(COMMAND ${XCODEBUILD_EXECUTABLE} -sdk ${CMAKE_OSX_SYSROOT_INT} -version SDKVersion - OUTPUT_VARIABLE SDK_VERSION - ERROR_QUIET - OUTPUT_STRIP_TRAILING_WHITESPACE) -endif() - -# Find the Developer root for the specific iOS platform being compiled for -# from CMAKE_OSX_SYSROOT. Should be ../../ from SDK specified in -# CMAKE_OSX_SYSROOT. There does not appear to be a direct way to obtain -# this information from xcrun or xcodebuild. -if (NOT DEFINED CMAKE_DEVELOPER_ROOT AND NOT CMAKE_GENERATOR MATCHES "Xcode") - get_filename_component(PLATFORM_SDK_DIR ${CMAKE_OSX_SYSROOT_INT} PATH) - get_filename_component(CMAKE_DEVELOPER_ROOT ${PLATFORM_SDK_DIR} PATH) - if (NOT EXISTS "${CMAKE_DEVELOPER_ROOT}") - message(FATAL_ERROR "Invalid CMAKE_DEVELOPER_ROOT: ${CMAKE_DEVELOPER_ROOT} does not exist.") - endif() -endif() - -# Find the C & C++ compilers for the specified SDK. -if(DEFINED CMAKE_C_COMPILER) - # Environment variables are always preserved. - set(ENV{_CMAKE_C_COMPILER} "${CMAKE_C_COMPILER}") -elseif(DEFINED ENV{_CMAKE_C_COMPILER}) - set(CMAKE_C_COMPILER "$ENV{_CMAKE_C_COMPILER}") - set(CMAKE_ASM_COMPILER ${CMAKE_C_COMPILER}) -elseif(NOT DEFINED CMAKE_C_COMPILER) - execute_process(COMMAND xcrun -sdk ${CMAKE_OSX_SYSROOT_INT} -find clang - OUTPUT_VARIABLE CMAKE_C_COMPILER - ERROR_QUIET - OUTPUT_STRIP_TRAILING_WHITESPACE) - set(CMAKE_ASM_COMPILER ${CMAKE_C_COMPILER}) -endif() -if(DEFINED CMAKE_CXX_COMPILER) - # Environment variables are always preserved. - set(ENV{_CMAKE_CXX_COMPILER} "${CMAKE_CXX_COMPILER}") -elseif(DEFINED ENV{_CMAKE_CXX_COMPILER}) - set(CMAKE_CXX_COMPILER "$ENV{_CMAKE_CXX_COMPILER}") -elseif(NOT DEFINED CMAKE_CXX_COMPILER) - execute_process(COMMAND xcrun -sdk ${CMAKE_OSX_SYSROOT_INT} -find clang++ - OUTPUT_VARIABLE CMAKE_CXX_COMPILER - ERROR_QUIET - OUTPUT_STRIP_TRAILING_WHITESPACE) -endif() -# Find (Apple's) libtool. -if(DEFINED BUILD_LIBTOOL) - # Environment variables are always preserved. - set(ENV{_BUILD_LIBTOOL} "${BUILD_LIBTOOL}") -elseif(DEFINED ENV{_BUILD_LIBTOOL}) - set(BUILD_LIBTOOL "$ENV{_BUILD_LIBTOOL}") -elseif(NOT DEFINED BUILD_LIBTOOL) - execute_process(COMMAND xcrun -sdk ${CMAKE_OSX_SYSROOT_INT} -find libtool - OUTPUT_VARIABLE BUILD_LIBTOOL - ERROR_QUIET - OUTPUT_STRIP_TRAILING_WHITESPACE) -endif() -# Find the toolchain's provided install_name_tool if none is found on the host -if(DEFINED CMAKE_INSTALL_NAME_TOOL) - # Environment variables are always preserved. - set(ENV{_CMAKE_INSTALL_NAME_TOOL} "${CMAKE_INSTALL_NAME_TOOL}") -elseif(DEFINED ENV{_CMAKE_INSTALL_NAME_TOOL}) - set(CMAKE_INSTALL_NAME_TOOL "$ENV{_CMAKE_INSTALL_NAME_TOOL}") -elseif(NOT DEFINED CMAKE_INSTALL_NAME_TOOL) - execute_process(COMMAND xcrun -sdk ${CMAKE_OSX_SYSROOT_INT} -find install_name_tool - OUTPUT_VARIABLE CMAKE_INSTALL_NAME_TOOL_INT - ERROR_QUIET - OUTPUT_STRIP_TRAILING_WHITESPACE) - set(CMAKE_INSTALL_NAME_TOOL ${CMAKE_INSTALL_NAME_TOOL_INT} CACHE INTERNAL "") -endif() - -# Configure libtool to be used instead of ar + ranlib to build static libraries. -# This is required on Xcode 7+, but should also work on previous versions of -# Xcode. -get_property(languages GLOBAL PROPERTY ENABLED_LANGUAGES) -foreach(lang ${languages}) - set(CMAKE_${lang}_CREATE_STATIC_LIBRARY "${BUILD_LIBTOOL} -static -o " CACHE INTERNAL "") -endforeach() - -# CMake 3.14+ support building for iOS, watchOS, and tvOS out of the box. -if(MODERN_CMAKE) - if(SDK_NAME MATCHES "iphone") - set(CMAKE_SYSTEM_NAME iOS) - elseif(SDK_NAME MATCHES "xros") - set(CMAKE_SYSTEM_NAME visionOS) - elseif(SDK_NAME MATCHES "xrsimulator") - set(CMAKE_SYSTEM_NAME visionOS) - elseif(SDK_NAME MATCHES "macosx") - set(CMAKE_SYSTEM_NAME Darwin) - elseif(SDK_NAME MATCHES "appletv") - set(CMAKE_SYSTEM_NAME tvOS) - elseif(SDK_NAME MATCHES "watch") - set(CMAKE_SYSTEM_NAME watchOS) - endif() - # Provide flags for a combined FAT library build on newer CMake versions - if(PLATFORM_INT MATCHES ".*COMBINED") - set(CMAKE_IOS_INSTALL_COMBINED YES) - if(CMAKE_GENERATOR MATCHES "Xcode") - # Set the SDKROOT Xcode properties to a Xcode-friendly value (the SDK_NAME, E.g, iphoneos) - # This way, Xcode will automatically switch between the simulator and device SDK when building. - set(CMAKE_XCODE_ATTRIBUTE_SDKROOT "${SDK_NAME}") - # Force to not build just one ARCH, but all! - set(CMAKE_XCODE_ATTRIBUTE_ONLY_ACTIVE_ARCH "NO") - endif() - endif() -elseif(NOT DEFINED CMAKE_SYSTEM_NAME AND ${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.10") - # Legacy code path prior to CMake 3.14 or fallback if no CMAKE_SYSTEM_NAME specified - set(CMAKE_SYSTEM_NAME iOS) -elseif(NOT DEFINED CMAKE_SYSTEM_NAME) - # Legacy code path before CMake 3.14 or fallback if no CMAKE_SYSTEM_NAME specified - set(CMAKE_SYSTEM_NAME Darwin) -endif() -# Standard settings. -set(CMAKE_SYSTEM_VERSION ${SDK_VERSION} CACHE INTERNAL "") -set(UNIX ON CACHE BOOL "") -set(APPLE ON CACHE BOOL "") -if(PLATFORM STREQUAL "MAC" OR PLATFORM STREQUAL "MAC_ARM64" OR PLATFORM STREQUAL "MAC_UNIVERSAL") - set(IOS OFF CACHE BOOL "") - set(MACOS ON CACHE BOOL "") -elseif(PLATFORM STREQUAL "MAC_CATALYST" OR PLATFORM STREQUAL "MAC_CATALYST_ARM64" OR PLATFORM STREQUAL "MAC_CATALYST_UNIVERSAL") - set(IOS ON CACHE BOOL "") - set(MACOS ON CACHE BOOL "") -elseif(PLATFORM STREQUAL "VISIONOS" OR PLATFORM STREQUAL "SIMULATOR_VISIONOS" OR PLATFORM STREQUAL "VISIONOSCOMBINED") - set(IOS OFF CACHE BOOL "") - set(VISIONOS ON CACHE BOOL "") -else() - set(IOS ON CACHE BOOL "") -endif() -# Set the architectures for which to build. -set(CMAKE_OSX_ARCHITECTURES ${ARCHS} CACHE INTERNAL "") -# Change the type of target generated for try_compile() so it'll work when cross-compiling, weak compiler checks -if(NOT ENABLE_STRICT_TRY_COMPILE_INT) - set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY) -endif() -# All iOS/Darwin specific settings - some may be redundant. -if (NOT DEFINED CMAKE_MACOSX_BUNDLE) - set(CMAKE_MACOSX_BUNDLE YES) -endif() -set(CMAKE_XCODE_ATTRIBUTE_CODE_SIGNING_REQUIRED "NO") -set(CMAKE_XCODE_ATTRIBUTE_CODE_SIGNING_ALLOWED "NO") -set(CMAKE_SHARED_LIBRARY_PREFIX "lib") -set(CMAKE_SHARED_LIBRARY_SUFFIX ".dylib") -set(CMAKE_EXTRA_SHARED_LIBRARY_SUFFIXES ".tbd" ".so") -set(CMAKE_SHARED_MODULE_PREFIX "lib") -set(CMAKE_SHARED_MODULE_SUFFIX ".so") -set(CMAKE_C_COMPILER_ABI ELF) -set(CMAKE_CXX_COMPILER_ABI ELF) -set(CMAKE_C_HAS_ISYSROOT 1) -set(CMAKE_CXX_HAS_ISYSROOT 1) -set(CMAKE_MODULE_EXISTS 1) -set(CMAKE_DL_LIBS "") -set(CMAKE_C_OSX_COMPATIBILITY_VERSION_FLAG "-compatibility_version ") -set(CMAKE_C_OSX_CURRENT_VERSION_FLAG "-current_version ") -set(CMAKE_CXX_OSX_COMPATIBILITY_VERSION_FLAG "${CMAKE_C_OSX_COMPATIBILITY_VERSION_FLAG}") -set(CMAKE_CXX_OSX_CURRENT_VERSION_FLAG "${CMAKE_C_OSX_CURRENT_VERSION_FLAG}") -set(CMAKE_CXX_STANDARD 20) -set(CMAKE_CXX_STANDARD_REQUIRED True) - -if(ARCHS MATCHES "((^|;|, )(arm64|arm64e|x86_64))+") - set(CMAKE_C_SIZEOF_DATA_PTR 8) - set(CMAKE_CXX_SIZEOF_DATA_PTR 8) - if(ARCHS MATCHES "((^|;|, )(arm64|arm64e))+") - set(CMAKE_SYSTEM_PROCESSOR "aarch64") - else() - set(CMAKE_SYSTEM_PROCESSOR "x86_64") - endif() -else() - set(CMAKE_C_SIZEOF_DATA_PTR 4) - set(CMAKE_CXX_SIZEOF_DATA_PTR 4) - set(CMAKE_SYSTEM_PROCESSOR "arm") -endif() - -# Note that only Xcode 7+ supports the newer more specific: -# -m${SDK_NAME}-version-min flags, older versions of Xcode use: -# -m(ios/ios-simulator)-version-min instead. -if(${CMAKE_VERSION} VERSION_LESS "3.11") - if(PLATFORM_INT STREQUAL "OS" OR PLATFORM_INT STREQUAL "OS64") - if(XCODE_VERSION_INT VERSION_LESS 7.0) - set(SDK_NAME_VERSION_FLAGS - "-mios-version-min=${DEPLOYMENT_TARGET}") - else() - # Xcode 7.0+ uses flags we can build directly from SDK_NAME. - set(SDK_NAME_VERSION_FLAGS - "-m${SDK_NAME}-version-min=${DEPLOYMENT_TARGET}") - endif() - elseif(PLATFORM_INT STREQUAL "TVOS") - set(SDK_NAME_VERSION_FLAGS - "-mtvos-version-min=${DEPLOYMENT_TARGET}") - elseif(PLATFORM_INT STREQUAL "SIMULATOR_TVOS") - set(SDK_NAME_VERSION_FLAGS - "-mtvos-simulator-version-min=${DEPLOYMENT_TARGET}") -elseif(PLATFORM_INT STREQUAL "SIMULATORARM64_TVOS") - set(SDK_NAME_VERSION_FLAGS - "-mtvos-simulator-version-min=${DEPLOYMENT_TARGET}") - elseif(PLATFORM_INT STREQUAL "WATCHOS") - set(SDK_NAME_VERSION_FLAGS - "-mwatchos-version-min=${DEPLOYMENT_TARGET}") - elseif(PLATFORM_INT STREQUAL "SIMULATOR_WATCHOS") - set(SDK_NAME_VERSION_FLAGS - "-mwatchos-simulator-version-min=${DEPLOYMENT_TARGET}") - elseif(PLATFORM_INT STREQUAL "SIMULATORARM64_WATCHOS") - set(SDK_NAME_VERSION_FLAGS - "-mwatchos-simulator-version-min=${DEPLOYMENT_TARGET}") - elseif(PLATFORM_INT STREQUAL "MAC") - set(SDK_NAME_VERSION_FLAGS - "-mmacosx-version-min=${DEPLOYMENT_TARGET}") - else() - # SIMULATOR or SIMULATOR64 both use -mios-simulator-version-min. - set(SDK_NAME_VERSION_FLAGS - "-mios-simulator-version-min=${DEPLOYMENT_TARGET}") - endif() -elseif(NOT PLATFORM_INT MATCHES "^MAC_CATALYST") - # Newer versions of CMake sets the version min flags correctly, skip this for Mac Catalyst targets - set(CMAKE_OSX_DEPLOYMENT_TARGET ${DEPLOYMENT_TARGET} CACHE INTERNAL "Minimum OS X deployment version") -endif() - -if(DEFINED APPLE_TARGET_TRIPLE_INT) - set(APPLE_TARGET_TRIPLE ${APPLE_TARGET_TRIPLE_INT} CACHE INTERNAL "") - set(CMAKE_C_COMPILER_TARGET ${APPLE_TARGET_TRIPLE}) - set(CMAKE_CXX_COMPILER_TARGET ${APPLE_TARGET_TRIPLE}) - set(CMAKE_ASM_COMPILER_TARGET ${APPLE_TARGET_TRIPLE}) -endif() - -if(PLATFORM_INT MATCHES "^MAC_CATALYST") - set(C_TARGET_FLAGS "-isystem ${CMAKE_OSX_SYSROOT_INT}/System/iOSSupport/usr/include -iframework ${CMAKE_OSX_SYSROOT_INT}/System/iOSSupport/System/Library/Frameworks") -endif() - -if(ENABLE_BITCODE_INT) - set(BITCODE "-fembed-bitcode") - set(CMAKE_XCODE_ATTRIBUTE_BITCODE_GENERATION_MODE "bitcode") - set(CMAKE_XCODE_ATTRIBUTE_ENABLE_BITCODE "YES") -else() - set(BITCODE "") - set(CMAKE_XCODE_ATTRIBUTE_ENABLE_BITCODE "NO") -endif() - -if(ENABLE_ARC_INT) - set(FOBJC_ARC "-fobjc-arc") - set(CMAKE_XCODE_ATTRIBUTE_CLANG_ENABLE_OBJC_ARC "YES") -else() - set(FOBJC_ARC "-fno-objc-arc") - set(CMAKE_XCODE_ATTRIBUTE_CLANG_ENABLE_OBJC_ARC "NO") -endif() - -if(NAMED_LANGUAGE_SUPPORT_INT) - set(OBJC_VARS "-fobjc-abi-version=2 -DOBJC_OLD_DISPATCH_PROTOTYPES=0") - set(OBJC_LEGACY_VARS "") -else() - set(OBJC_VARS "") - set(OBJC_LEGACY_VARS "-fobjc-abi-version=2 -DOBJC_OLD_DISPATCH_PROTOTYPES=0") -endif() - -if(NOT ENABLE_VISIBILITY_INT) - foreach(lang ${languages}) - set(CMAKE_${lang}_VISIBILITY_PRESET "hidden" CACHE INTERNAL "") - endforeach() - set(CMAKE_XCODE_ATTRIBUTE_GCC_SYMBOLS_PRIVATE_EXTERN "YES") - set(VISIBILITY "-fvisibility=hidden -fvisibility-inlines-hidden") -else() - foreach(lang ${languages}) - set(CMAKE_${lang}_VISIBILITY_PRESET "default" CACHE INTERNAL "") - endforeach() - set(CMAKE_XCODE_ATTRIBUTE_GCC_SYMBOLS_PRIVATE_EXTERN "NO") - set(VISIBILITY "-fvisibility=default") -endif() - -if(DEFINED APPLE_TARGET_TRIPLE) - set(APPLE_TARGET_TRIPLE_FLAG "-target ${APPLE_TARGET_TRIPLE}") -endif() - -#Check if Xcode generator is used since that will handle these flags automagically -if(CMAKE_GENERATOR MATCHES "Xcode") - message(STATUS "Not setting any manual command-line buildflags, since Xcode is selected as the generator. Modifying the Xcode build-settings directly instead.") -else() - set(CMAKE_C_FLAGS "${C_TARGET_FLAGS} ${APPLE_TARGET_TRIPLE_FLAG} ${SDK_NAME_VERSION_FLAGS} ${OBJC_LEGACY_VARS} ${BITCODE} ${VISIBILITY} ${CMAKE_C_FLAGS}" CACHE INTERNAL - "Flags used by the compiler during all C build types.") - set(CMAKE_C_FLAGS_DEBUG "-O0 -g ${CMAKE_C_FLAGS_DEBUG}") - set(CMAKE_C_FLAGS_MINSIZEREL "-DNDEBUG -Os ${CMAKE_C_FLAGS_MINSIZEREL}") - set(CMAKE_C_FLAGS_RELWITHDEBINFO "-DNDEBUG -O2 -g ${CMAKE_C_FLAGS_RELWITHDEBINFO}") - set(CMAKE_C_FLAGS_RELEASE "-DNDEBUG -O3 ${CMAKE_C_FLAGS_RELEASE}") - set(CMAKE_CXX_FLAGS "${C_TARGET_FLAGS} ${APPLE_TARGET_TRIPLE_FLAG} ${SDK_NAME_VERSION_FLAGS} ${OBJC_LEGACY_VARS} ${BITCODE} ${VISIBILITY} ${CMAKE_CXX_FLAGS}" CACHE INTERNAL - "Flags used by the compiler during all CXX build types.") - set(CMAKE_CXX_FLAGS_DEBUG "-O0 -g ${CMAKE_CXX_FLAGS_DEBUG}") - set(CMAKE_CXX_FLAGS_MINSIZEREL "-DNDEBUG -Os ${CMAKE_CXX_FLAGS_MINSIZEREL}") - set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-DNDEBUG -O2 -g ${CMAKE_CXX_FLAGS_RELWITHDEBINFO}") - set(CMAKE_CXX_FLAGS_RELEASE "-DNDEBUG -O3 ${CMAKE_CXX_FLAGS_RELEASE}") - if(NAMED_LANGUAGE_SUPPORT_INT) - set(CMAKE_OBJC_FLAGS "${C_TARGET_FLAGS} ${APPLE_TARGET_TRIPLE_FLAG} ${SDK_NAME_VERSION_FLAGS} ${BITCODE} ${VISIBILITY} ${FOBJC_ARC} ${OBJC_VARS} ${CMAKE_OBJC_FLAGS}" CACHE INTERNAL - "Flags used by the compiler during all OBJC build types.") - set(CMAKE_OBJC_FLAGS_DEBUG "-O0 -g ${CMAKE_OBJC_FLAGS_DEBUG}") - set(CMAKE_OBJC_FLAGS_MINSIZEREL "-DNDEBUG -Os ${CMAKE_OBJC_FLAGS_MINSIZEREL}") - set(CMAKE_OBJC_FLAGS_RELWITHDEBINFO "-DNDEBUG -O2 -g ${CMAKE_OBJC_FLAGS_RELWITHDEBINFO}") - set(CMAKE_OBJC_FLAGS_RELEASE "-DNDEBUG -O3 ${CMAKE_OBJC_FLAGS_RELEASE}") - set(CMAKE_OBJCXX_FLAGS "${C_TARGET_FLAGS} ${APPLE_TARGET_TRIPLE_FLAG} ${SDK_NAME_VERSION_FLAGS} ${BITCODE} ${VISIBILITY} ${FOBJC_ARC} ${OBJC_VARS} ${CMAKE_OBJCXX_FLAGS}" CACHE INTERNAL - "Flags used by the compiler during all OBJCXX build types.") - set(CMAKE_OBJCXX_FLAGS_DEBUG "-O0 -g ${CMAKE_OBJCXX_FLAGS_DEBUG}") - set(CMAKE_OBJCXX_FLAGS_MINSIZEREL "-DNDEBUG -Os ${CMAKE_OBJCXX_FLAGS_MINSIZEREL}") - set(CMAKE_OBJCXX_FLAGS_RELWITHDEBINFO "-DNDEBUG -O2 -g ${CMAKE_OBJCXX_FLAGS_RELWITHDEBINFO}") - set(CMAKE_OBJCXX_FLAGS_RELEASE "-DNDEBUG -O3 ${CMAKE_OBJCXX_FLAGS_RELEASE}") - endif() - set(CMAKE_C_LINK_FLAGS "${C_TARGET_FLAGS} ${SDK_NAME_VERSION_FLAGS} -Wl,-search_paths_first ${CMAKE_C_LINK_FLAGS}" CACHE INTERNAL - "Flags used by the compiler for all C link types.") - set(CMAKE_CXX_LINK_FLAGS "${C_TARGET_FLAGS} ${SDK_NAME_VERSION_FLAGS} -Wl,-search_paths_first ${CMAKE_CXX_LINK_FLAGS}" CACHE INTERNAL - "Flags used by the compiler for all CXX link types.") - if(NAMED_LANGUAGE_SUPPORT_INT) - set(CMAKE_OBJC_LINK_FLAGS "${C_TARGET_FLAGS} ${SDK_NAME_VERSION_FLAGS} -Wl,-search_paths_first ${CMAKE_OBJC_LINK_FLAGS}" CACHE INTERNAL - "Flags used by the compiler for all OBJC link types.") - set(CMAKE_OBJCXX_LINK_FLAGS "${C_TARGET_FLAGS} ${SDK_NAME_VERSION_FLAGS} -Wl,-search_paths_first ${CMAKE_OBJCXX_LINK_FLAGS}" CACHE INTERNAL - "Flags used by the compiler for all OBJCXX link types.") - endif() - set(CMAKE_ASM_FLAGS "${CMAKE_C_FLAGS} -x assembler-with-cpp" CACHE INTERNAL - "Flags used by the compiler for all ASM build types.") -endif() - -## Print status messages to inform of the current state -message(STATUS "Configuring ${SDK_NAME} build for platform: ${PLATFORM_INT}, architecture(s): ${ARCHS}") -message(STATUS "Using SDK: ${CMAKE_OSX_SYSROOT_INT}") -message(STATUS "Using C compiler: ${CMAKE_C_COMPILER}") -message(STATUS "Using CXX compiler: ${CMAKE_CXX_COMPILER}") -message(STATUS "Using libtool: ${BUILD_LIBTOOL}") -message(STATUS "Using install name tool: ${CMAKE_INSTALL_NAME_TOOL}") -if(DEFINED APPLE_TARGET_TRIPLE) - message(STATUS "Autoconf target triple: ${APPLE_TARGET_TRIPLE}") -endif() -message(STATUS "Using minimum deployment version: ${DEPLOYMENT_TARGET}" - " (SDK version: ${SDK_VERSION})") -if(MODERN_CMAKE) - message(STATUS "Merging integrated CMake 3.14+ iOS,tvOS,watchOS,macOS toolchain(s) with this toolchain!") - if(PLATFORM_INT MATCHES ".*COMBINED") - message(STATUS "Will combine built (static) artifacts into FAT lib...") - endif() -endif() -if(CMAKE_GENERATOR MATCHES "Xcode") - message(STATUS "Using Xcode version: ${XCODE_VERSION_INT}") -endif() -message(STATUS "CMake version: ${CMAKE_VERSION}") -if(DEFINED SDK_NAME_VERSION_FLAGS) - message(STATUS "Using version flags: ${SDK_NAME_VERSION_FLAGS}") -endif() -message(STATUS "Using a data_ptr size of: ${CMAKE_CXX_SIZEOF_DATA_PTR}") -if(ENABLE_BITCODE_INT) - message(STATUS "Bitcode: Enabled") -else() - message(STATUS "Bitcode: Disabled") -endif() - -if(ENABLE_ARC_INT) - message(STATUS "ARC: Enabled") -else() - message(STATUS "ARC: Disabled") -endif() - -if(ENABLE_VISIBILITY_INT) - message(STATUS "Hiding symbols: Disabled") -else() - message(STATUS "Hiding symbols: Enabled") -endif() - -# Set global properties -set_property(GLOBAL PROPERTY PLATFORM "${PLATFORM}") -set_property(GLOBAL PROPERTY APPLE_TARGET_TRIPLE "${APPLE_TARGET_TRIPLE_INT}") -set_property(GLOBAL PROPERTY SDK_VERSION "${SDK_VERSION}") -set_property(GLOBAL PROPERTY XCODE_VERSION "${XCODE_VERSION_INT}") -set_property(GLOBAL PROPERTY OSX_ARCHITECTURES "${CMAKE_OSX_ARCHITECTURES}") - -# Export configurable variables for the try_compile() command. -set(CMAKE_TRY_COMPILE_PLATFORM_VARIABLES - PLATFORM - XCODE_VERSION_INT - SDK_VERSION - NAMED_LANGUAGE_SUPPORT - DEPLOYMENT_TARGET - CMAKE_DEVELOPER_ROOT - CMAKE_OSX_SYSROOT_INT - ENABLE_BITCODE - ENABLE_ARC - CMAKE_ASM_COMPILER - CMAKE_C_COMPILER - CMAKE_C_COMPILER_TARGET - CMAKE_CXX_COMPILER - CMAKE_CXX_COMPILER_TARGET - BUILD_LIBTOOL - CMAKE_INSTALL_NAME_TOOL - CMAKE_C_FLAGS - CMAKE_C_DEBUG - CMAKE_C_MINSIZEREL - CMAKE_C_RELWITHDEBINFO - CMAKE_C_RELEASE - CMAKE_CXX_FLAGS - CMAKE_CXX_FLAGS_DEBUG - CMAKE_CXX_FLAGS_MINSIZEREL - CMAKE_CXX_FLAGS_RELWITHDEBINFO - CMAKE_CXX_FLAGS_RELEASE - CMAKE_C_LINK_FLAGS - CMAKE_CXX_LINK_FLAGS - CMAKE_ASM_FLAGS -) - -if(NAMED_LANGUAGE_SUPPORT_INT) - list(APPEND CMAKE_TRY_COMPILE_PLATFORM_VARIABLES - CMAKE_OBJC_FLAGS - CMAKE_OBJC_DEBUG - CMAKE_OBJC_MINSIZEREL - CMAKE_OBJC_RELWITHDEBINFO - CMAKE_OBJC_RELEASE - CMAKE_OBJCXX_FLAGS - CMAKE_OBJCXX_DEBUG - CMAKE_OBJCXX_MINSIZEREL - CMAKE_OBJCXX_RELWITHDEBINFO - CMAKE_OBJCXX_RELEASE - CMAKE_OBJC_LINK_FLAGS - CMAKE_OBJCXX_LINK_FLAGS - ) -endif() - -set(CMAKE_PLATFORM_HAS_INSTALLNAME 1) -set(CMAKE_SHARED_LINKER_FLAGS "-rpath @executable_path/Frameworks -rpath @loader_path/Frameworks") -set(CMAKE_SHARED_LIBRARY_CREATE_C_FLAGS "-dynamiclib -Wl,-headerpad_max_install_names") -set(CMAKE_SHARED_MODULE_CREATE_C_FLAGS "-bundle -Wl,-headerpad_max_install_names") -set(CMAKE_SHARED_MODULE_LOADER_C_FLAG "-Wl,-bundle_loader,") -set(CMAKE_SHARED_MODULE_LOADER_CXX_FLAG "-Wl,-bundle_loader,") -set(CMAKE_FIND_LIBRARY_SUFFIXES ".tbd" ".dylib" ".so" ".a") -set(CMAKE_SHARED_LIBRARY_SONAME_C_FLAG "-install_name") - -# Set the find root to the SDK developer roots. -# Note: CMAKE_FIND_ROOT_PATH is only useful when cross-compiling. Thus, do not set on macOS builds. -if(NOT PLATFORM_INT MATCHES "^MAC.*$") - list(APPEND CMAKE_FIND_ROOT_PATH "${CMAKE_OSX_SYSROOT_INT}" CACHE INTERNAL "") - set(CMAKE_IGNORE_PATH "/System/Library/Frameworks;/usr/local/lib;/opt/homebrew" CACHE INTERNAL "") -endif() - -# Default to searching for frameworks first. -IF(NOT DEFINED CMAKE_FIND_FRAMEWORK) - set(CMAKE_FIND_FRAMEWORK FIRST) -ENDIF(NOT DEFINED CMAKE_FIND_FRAMEWORK) - -# Set up the default search directories for frameworks. -if(PLATFORM_INT MATCHES "^MAC_CATALYST") - set(CMAKE_FRAMEWORK_PATH - ${CMAKE_DEVELOPER_ROOT}/Library/PrivateFrameworks - ${CMAKE_OSX_SYSROOT_INT}/System/Library/Frameworks - ${CMAKE_OSX_SYSROOT_INT}/System/iOSSupport/System/Library/Frameworks - ${CMAKE_FRAMEWORK_PATH} CACHE INTERNAL "") -else() - set(CMAKE_FRAMEWORK_PATH - ${CMAKE_DEVELOPER_ROOT}/Library/PrivateFrameworks - ${CMAKE_OSX_SYSROOT_INT}/System/Library/Frameworks - ${CMAKE_FRAMEWORK_PATH} CACHE INTERNAL "") -endif() - -# By default, search both the specified iOS SDK and the remainder of the host filesystem. -if(NOT CMAKE_FIND_ROOT_PATH_MODE_PROGRAM) - set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM BOTH CACHE INTERNAL "") -endif() -if(NOT CMAKE_FIND_ROOT_PATH_MODE_LIBRARY) - set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY BOTH CACHE INTERNAL "") -endif() -if(NOT CMAKE_FIND_ROOT_PATH_MODE_INCLUDE) - set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE BOTH CACHE INTERNAL "") -endif() -if(NOT CMAKE_FIND_ROOT_PATH_MODE_PACKAGE) - set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE BOTH CACHE INTERNAL "") -endif() - -# -# Some helper-macros below to simplify and beautify the CMakeFile -# - -# This little macro lets you set any Xcode specific property. -macro(set_xcode_property TARGET XCODE_PROPERTY XCODE_VALUE XCODE_RELVERSION) - set(XCODE_RELVERSION_I "${XCODE_RELVERSION}") - if(XCODE_RELVERSION_I STREQUAL "All") - set_property(TARGET ${TARGET} PROPERTY XCODE_ATTRIBUTE_${XCODE_PROPERTY} "${XCODE_VALUE}") - else() - set_property(TARGET ${TARGET} PROPERTY XCODE_ATTRIBUTE_${XCODE_PROPERTY}[variant=${XCODE_RELVERSION_I}] "${XCODE_VALUE}") - endif() -endmacro(set_xcode_property) - -# This macro lets you find executable programs on the host system. -macro(find_host_package) - set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) - set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY NEVER) - set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE NEVER) - set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE NEVER) - set(_TOOLCHAIN_IOS ${IOS}) - set(IOS OFF) - find_package(${ARGN}) - set(IOS ${_TOOLCHAIN_IOS}) - set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM BOTH) - set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY BOTH) - set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE BOTH) - set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE BOTH) -endmacro(find_host_package) diff --git a/packages/webgpu/scripts/build/copy-artifacts.ts b/packages/webgpu/scripts/build/copy-artifacts.ts deleted file mode 100644 index fd1f6a61e4..0000000000 --- a/packages/webgpu/scripts/build/copy-artifacts.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { checkBuildArtifacts } from "./dawn-configuration"; -import { $ } from "./util"; - -$("cp -R ../../artifacts/libs ."); -$("cp -R ../../artifacts/cpp/webgpu cpp"); -$("cp -R ../../artifacts/cpp/dawn cpp"); -checkBuildArtifacts(); diff --git a/packages/webgpu/scripts/build/dawn-configuration.ts b/packages/webgpu/scripts/build/dawn-configuration.ts deleted file mode 100644 index 002fa0a75f..0000000000 --- a/packages/webgpu/scripts/build/dawn-configuration.ts +++ /dev/null @@ -1,101 +0,0 @@ -import { execSync } from "child_process"; - -import { $, checkFileExists, runAsync } from "./util"; - -export const libs = ["libwebgpu_dawn"] as const; - -export const projectRoot = "packages/webgpu"; - -export const platforms = [ - "arm64", - "x86_64", - "x86", - "armeabi-v7a", - "arm64-v8a", - "universal", -] as const; - -export type OS = "apple" | "android"; -export type Platform = (typeof platforms)[number]; - -const serializeCMakeArgs = (args: Record) => { - return Object.keys(args) - .map((key) => `-D${key}=${args[key]}`) - .join(" "); -}; - -export const build = async ( - label: string, - args: Record, - debugLabel: string, -) => { - console.log(`🔨 Building ${label}`); - $(`mkdir -p externals/dawn/out/${label}`); - process.chdir(`externals/dawn/out/${label}`); - const cmd = `cmake ../.. -G Ninja ${serializeCMakeArgs(args)}`; - await runAsync(cmd, debugLabel); - await runAsync("ninja", debugLabel); - process.chdir("../../../.."); -}; - -// The NDK keeps its host tools in one directory per host; the macOS one is -// named after x86_64 and holds universal binaries. -const ndkHostTags: Partial> = { - darwin: "darwin-x86_64", - linux: "linux-x86_64", -}; - -const androidNdkBin = () => { - const hostTag = ndkHostTags[process.platform]; - if (hostTag === undefined) { - throw new Error(`No NDK host tools for ${process.platform}`); - } - return `$ANDROID_NDK/toolchains/llvm/prebuilt/${hostTag}/bin`; -}; - -// Exceptions from the libraries that link Dawn reach JS through Hermes, which -// only matches them against the app's libc++_shared.so. -const assertSharedCxxRuntime = (libPath: string) => { - const runtimeSymbols = execSync( - `${androidNdkBin()}/llvm-nm -D --defined-only ${libPath}`, - { maxBuffer: Infinity }, - ) - .toString() - .split("\n") - .filter((line) => / (__cxa_throw|__gxx_personality_v0)$/.test(line)); - if (runtimeSymbols.length > 0) { - throw new Error( - `${libPath} defines its own C++ runtime; build it with ANDROID_STL=c++_shared`, - ); - } -}; - -export const copyLib = (os: OS, platform: Platform, sdk?: string) => { - const suffix = `${platform}${sdk ? `_${sdk}` : ""}`; - const out = `${os}_${suffix}`; - const dstPath = `${projectRoot}/libs/${os}/${suffix}/`; - const libPath = `externals/dawn/out/${out}/src/dawn/native/libwebgpu_dawn.${os === "android" ? "so" : "a"}`; - $(`mkdir -p ${dstPath}`); - if (os === "android") { - console.log("Strip debug symbols from libwebgpu_dawn.so..."); - $(`${androidNdkBin()}/llvm-strip ${libPath}`); - assertSharedCxxRuntime(libPath); - } - console.log(`Copying ${libPath} to ${dstPath}`); - $(`cp ${libPath} ${dstPath}`); -}; - -export const checkBuildArtifacts = () => { - console.log("Check build artifacts..."); - platforms - .filter((arch) => arch !== "arm64" && arch !== "universal") - .forEach((platform) => { - libs.forEach((lib) => { - checkFileExists(`libs/android/${platform}/${lib}.so`); - }); - }); - libs.forEach((lib) => { - checkFileExists(`libs/apple/${lib}.xcframework`); - }); - //checkFileExists("libs/dawn.json"); -}; diff --git a/packages/webgpu/scripts/build/dawn.ts b/packages/webgpu/scripts/build/dawn.ts deleted file mode 100644 index 2a16fdf38a..0000000000 --- a/packages/webgpu/scripts/build/dawn.ts +++ /dev/null @@ -1,173 +0,0 @@ -/* eslint-disable camelcase */ - -import { chdir, exit } from "process"; -import { execSync } from "child_process"; - -import type { Platform } from "./dawn-configuration"; -import { $, checkDuplicateHeaders, mapKeys } from "./util"; -import { - build, - checkBuildArtifacts, - copyLib, - libs, - projectRoot, -} from "./dawn-configuration"; - -const commonArgs = { - CMAKE_BUILD_TYPE: "Release", - BUILD_SAMPLES: "OFF", - TINT_BUILD_TESTS: "OFF", - TINT_BUILD_CMD_TOOLS: "OFF", - TINT_BUILD_IR_BINARY: "OFF", - DAWN_BUILD_SAMPLES: "OFF", - DAWN_USE_GLFW: "OFF", - DAWN_FETCH_DEPENDENCIES: "ON", - DAWN_ENABLE_DESKTOP_GL: "OFF", - DAWN_ENABLE_OPENGLES: "OFF", - BUILD_SHARED_LIBS: "OFF", -}; - -const PLATFORM_MAP: Record = { - arm64_iphoneos: "OS64", - arm64_iphonesimulator: "SIMULATORARM64", - x86_64_iphonesimulator: "SIMULATOR64", - arm64_xros: "VISIONOS", - arm64_xrsimulator: "SIMULATOR_VISIONOS", - x86_64_xrsimulator: "SIMULATOR64_VISIONOS", - universal_macosx: "MAC_UNIVERSAL", -}; - -const android = { - platforms: ["arm64-v8a", "armeabi-v7a", "x86", "x86_64"] as Platform[], - args: { - CMAKE_TOOLCHAIN_FILE: "$ANDROID_NDK/build/cmake/android.toolchain.cmake", - ANDROID_PLATFORM: "android-26", - ANDROID_STL: "c++_shared", - DAWN_BUILD_MONOLITHIC_LIBRARY: "SHARED", - CMAKE_EXE_LINKER_FLAGS: "-llog", - CMAKE_SHARED_LINKER_FLAGS: "-llog -Wl,-z,max-page-size=16384", - ANDROID_SUPPORT_FLEXIBLE_PAGE_SIZES: "ON", - ...commonArgs, - }, -}; - -const apple = { - matrix: { - arm64: ["iphoneos", "iphonesimulator", "xros", "xrsimulator"], - x86_64: ["iphonesimulator"], - universal: ["macosx"], - }, - args: { - CMAKE_TOOLCHAIN_FILE: `${__dirname}/apple.toolchain.cmake`, - DAWN_BUILD_MONOLITHIC_LIBRARY: "STATIC", - // -DPLATFORM=OS64 -DDEPLOYMENT_TARGET=13.0 -DENABLE_BITCODE=OFF -DENABLE_ARC=OFF -DENABLE_VISIBILITY=OFF - ...commonArgs, - }, -}; - -// TODO: should be: -// cmake --install ${{ output_dir }} --prefix dawn-headers -// and the associated postProcess from install-dawn -export const copyHeaders = () => { - console.log("📗 Copy headers"); - [ - `rm -rf ${projectRoot}/cpp/webgpu`, - `rm -rf ${projectRoot}/cpp/dawn`, - `cp -a externals/dawn/out/android_arm64-v8a/gen/include/webgpu ${projectRoot}/cpp`, - `cp -a externals/dawn/out/android_arm64-v8a/gen/include/dawn ${projectRoot}/cpp`, - `cp -a externals/dawn/include/webgpu/. ${projectRoot}/cpp/webgpu`, - `cp -a externals/dawn/include/dawn/. ${projectRoot}/cpp/dawn`, - `sed -i '' 's/#include "dawn\\/webgpu.h"/#include "webgpu\\/webgpu.h"/' ${projectRoot}/cpp/dawn/dawn_proc_table.h`, - `cp ${projectRoot}/cpp/dawn/webgpu.h ${projectRoot}/cpp/webgpu/webgpu.h`, - `cp ${projectRoot}/cpp/dawn/webgpu_cpp.h ${projectRoot}/cpp/webgpu/webgpu_cpp.h`, - `rm -rf ${projectRoot}/cpp/dawn/webgpu.h`, - `rm -rf ${projectRoot}/cpp/dawn/webgpu_cpp.h`, - `rm -rf ${projectRoot}/cpp/dawn/wire`, - `rm -rf ${projectRoot}/cpp/webgpu/webgpu_cpp_print.h`, - `cp externals/dawn/src/dawn/dawn.json ${projectRoot}/libs`, - ].map((cmd) => $(cmd)); - - // Check for duplicate header names and issue warnings - checkDuplicateHeaders(`${projectRoot}/cpp`); -}; - -(async () => { - process.chdir("../.."); - - // Apply the upstream Dawn changes the pinned commit does not carry yet - // (scripts/dawn-patches, see scripts/apply-dawn-patches.sh) - try { - execSync(`${projectRoot}/scripts/apply-dawn-patches.sh`, { - stdio: "inherit", - }); - } catch (e) { - exit(1); - } - - // Build Android - for (const platform of android.platforms) { - console.log(`Build Android: ${platform}`); - await build( - `android_${platform}`, - { - ANDROID_ABI: platform, - ...android.args, - }, - `🤖 ${platform}`, - ); - copyLib("android", platform); - } - - // Build Apple - for (const platform of mapKeys(apple.matrix)) { - console.log(`Build Apple: ${platform}`); - for (const sdk of apple.matrix[platform]) { - await build( - `apple_${platform}_${sdk}`, - { - PLATFORM: PLATFORM_MAP[`${platform}_${sdk}`], - ...apple.args, - }, - `🍏 ${platform} ${sdk}`, - ); - copyLib("apple", platform, sdk); - } - } - - $(`mkdir -p ${projectRoot}/libs/apple/iphonesimulator`); - libs.forEach((lib) => { - console.log(`📱 Building fat binary for iphone simulator: ${lib}`); - $( - `lipo -create ${projectRoot}/libs/apple/x86_64_iphonesimulator/${lib}.a ${projectRoot}/libs/apple/arm64_iphonesimulator/${lib}.a -output ${projectRoot}/libs/apple/iphonesimulator/${lib}.a`, - ); - }); - - libs.forEach((lib) => { - console.log(`📱 Building ${lib} (XCFramework) for iOS, visionOS and macOS`); - - $(`rm -rf ${projectRoot}/libs/apple/${lib}.xcframework`); - $( - "xcodebuild -create-xcframework " + - `-library ${projectRoot}/libs/apple/iphonesimulator/${lib}.a ` + - `-library ${projectRoot}/libs/apple/arm64_iphoneos/${lib}.a ` + - `-library ${projectRoot}/libs/apple/arm64_xros/${lib}.a ` + - `-library ${projectRoot}/libs/apple/arm64_xrsimulator/${lib}.a ` + - `-library ${projectRoot}/libs/apple/universal_macosx/${lib}.a ` + - ` -output ${projectRoot}/libs/apple/${lib}.xcframework `, - ); - - // Remove intermediate libraries - $( - "rm -rf " + - `${projectRoot}/libs/apple/iphonesimulator` + - `${projectRoot}/libs/apple/arm64_iphoneos` + - `${projectRoot}/libs/apple/arm64_xros` + - `${projectRoot}/libs/apple/arm64_xrsimulator` + - `${projectRoot}/libs/apple/universal_macosx`, - ); - }); - - copyHeaders(); - chdir(projectRoot); - checkBuildArtifacts(); -})(); diff --git a/packages/webgpu/scripts/build/util.ts b/packages/webgpu/scripts/build/util.ts deleted file mode 100644 index a14a29c617..0000000000 --- a/packages/webgpu/scripts/build/util.ts +++ /dev/null @@ -1,92 +0,0 @@ -import { spawn, execSync } from "child_process"; -import { existsSync } from "fs"; -import { exit } from "process"; - -export const runAsync = (command: string, label: string): Promise => { - return new Promise((resolve, reject) => { - const [cmd, ...args] = command.split(" "); - console.log({ cmd, args }); - const childProcess = spawn(cmd, args, { - shell: true, - }); - - childProcess.stdout.on("data", (data) => { - process.stdout.write(`${label} ${data}`); - }); - - childProcess.stderr.on("data", (data) => { - console.error(`${label} ${data}`); - }); - - childProcess.on("close", (code) => { - if (code === 0) { - resolve(); - } else { - reject(new Error(`${label} exited with code ${code}`)); - } - }); - - childProcess.on("error", (error) => { - reject(new Error(`${label} ${error.message}`)); - }); - }); -}; - -export const mapKeys = (obj: T) => - Object.keys(obj) as (keyof T)[]; - -export const checkFileExists = (filePath: string) => { - const exists = existsSync(filePath); - if (!exists) { - console.log(""); - console.log("Failed:"); - console.log(filePath + " not found. (" + filePath + ")"); - console.log(""); - exit(1); - } else { - console.log("✅ " + filePath); - } -}; - -export const $ = (command: string) => { - try { - return execSync(command); - } catch (e) { - exit(1); - } -}; - -export const checkDuplicateHeaders = (cppPath: string) => { - // Check for duplicate header names and issue warnings - const duplicateHeaders = $( - `find ${cppPath} -name '*.h' -type f | sed 's/.*\\///' | sort | uniq -d`, - ).toString(); - if (duplicateHeaders.trim()) { - console.warn("⚠️ WARNING: Found duplicate header names:"); - let hasConflicts = false; - - duplicateHeaders - .split("\n") - .filter(Boolean) - .forEach((filename: string) => { - const fullPaths = $( - `find ${cppPath} -name "${filename}" -type f`, - ).toString(); - const paths = fullPaths.split("\n").filter(Boolean); - - console.warn(` ${filename}:`); - paths.forEach((filePath: string) => { - console.warn(` ${filePath}`); - }); - - hasConflicts = true; - }); - - if (hasConflicts) { - console.error( - "❌ ERROR: Duplicate headers found that will cause iOS build conflicts!", - ); - exit(1); - } - } -}; diff --git a/packages/webgpu/scripts/check-dawn.ts b/packages/webgpu/scripts/check-dawn.ts new file mode 100644 index 0000000000..2a79a92f04 --- /dev/null +++ b/packages/webgpu/scripts/check-dawn.ts @@ -0,0 +1,78 @@ +#!/usr/bin/env tsx + +// Dawn ships in the react-native-webgpu-dawn package, built by react-native-skia +// from the Dawn commit its Skia release pins. This checks the installed one +// against the C++ workarounds below, which exist for Dawn bugs that an upstream +// fix makes obsolete. Each entry names the Dawn commit it was validated against. +// Bumping the dependency to a package built from another commit fails here +// until whoever does the bump checks whether the upstream fix is included: if +// it is, delete the marked code and the entry; if it is not, update `commit` +// (and re-verify the diagnostic screen). +// +// Runs from `yarn check-dawn`, in CI right after `yarn install`. + +import { existsSync, readFileSync } from "fs"; +import { dirname, join } from "path"; + +const dawnPackageJson = + require.resolve("react-native-webgpu-dawn/package.json"); +const dawnPackage = JSON.parse(readFileSync(dawnPackageJson, "utf-8")); +const installedCommit: string | undefined = dawnPackage.dawn?.commit; +if (!installedCommit) { + console.error( + `❌ ${dawnPackageJson} does not record the Dawn commit it was built from (dawn.commit)`, + ); + process.exit(1); +} + +const dawnWorkarounds = [ + { + marker: "DAWN_WORKAROUND_DEVICE_DESTROY_BEFORE_SURFACE_RELEASE", + commit: "3d786993a7ded64c4ebb4884b9b079db9ad0e580", + files: ["cpp/rnwgpu/SurfaceRegistry.h", "cpp/rnwgpu/api/GPUDevice.cpp"], + // Android: device.destroy() before the native view is dropped crashed in + // SwapChain::DetachFromSurfaceImpl (Vulkan FencedDeleter of the dead + // device). Verify with the "Device Destroy Before Detach" diagnostic in + // the example app. + upstream: "Dawn CL pending (see the workaround comment in the files)", + }, +]; + +const root = join(__dirname, ".."); +let failed = false; +for (const workaround of dawnWorkarounds) { + const present = workaround.files.filter((file) => { + const path = join(root, file); + return ( + existsSync(path) && + readFileSync(path, "utf-8").includes(workaround.marker) + ); + }); + if (present.length === 0) { + console.error( + `❌ Workaround ${workaround.marker} is gone from the sources; remove its entry from scripts/check-dawn.ts`, + ); + failed = true; + } else if (present.length !== workaround.files.length) { + const missing = workaround.files.filter((file) => !present.includes(file)); + console.error( + `❌ Workaround ${workaround.marker} is only partially applied: missing from ${missing.join(", ")}`, + ); + failed = true; + } else if (installedCommit !== workaround.commit) { + console.error( + `❌ Dawn changed (${workaround.commit.slice(0, 10)} -> ${installedCommit.slice(0, 10)}, react-native-webgpu-dawn ${dawnPackage.version}) but ${workaround.marker} is still in ${present.join(", ")}`, + ); + console.error( + ` Check whether this Dawn contains the upstream fix (${workaround.upstream}). If it does, remove the marked code and this entry; if not, update the commit in scripts/check-dawn.ts`, + ); + failed = true; + } +} +if (failed) { + process.exit(1); +} + +console.log( + `✅ react-native-webgpu-dawn ${dawnPackage.version} (Dawn ${installedCommit.slice(0, 10)}) at ${dirname(dawnPackageJson)}`, +); diff --git a/packages/webgpu/scripts/dawn-patches/tint-looprange-function-variable.patch b/packages/webgpu/scripts/dawn-patches/tint-looprange-function-variable.patch deleted file mode 100644 index bf68cc175f..0000000000 --- a/packages/webgpu/scripts/dawn-patches/tint-looprange-function-variable.patch +++ /dev/null @@ -1,60 +0,0 @@ -[tint] Use a function variable for the LoopRange loop index - -Backport of https://github.com/google/dawn/pull/87 (Gerrit change 348435), -not yet in the Dawn commit pinned by package.json (dawnCommit). - -Builder::LoopRange held the loop index in a block parameter of the loop body, -which the SPIR-V writer emits as an OpPhi. On a Pixel 8 (Mali-G715, driver -r54p3, Android 17) with the Vulkan backend, shaders that execute such a loop -hang the GPU and the device is lost a few seconds later. LoopRange is used on -the SPIR-V path by ZeroInitWorkgroupMemory, PreservePadding, Std140, -DecomposeAccess (whole array loads, which is how Skia Graphite's gradient -shaders read their color stops) and ForkExplicitLayoutTypes. - -Hold the index in a function variable declared in the loop initializer -instead. This is the shape a WGSL `for` loop lowers to, which that driver -executes correctly. - -Drop this patch once the pinned Dawn carries the change: apply-dawn-patches.sh -skips it when it is already present and fails when it no longer applies. - ---- ---- a/src/tint/lang/core/ir/builder.h -+++ b/src/tint/lang/core/ir/builder.h -@@ -2076,15 +2076,21 @@ class Builder { - auto* end_value = Value(std::forward(end)); - auto* step_value = Value(std::forward(step)); - -+ // The loop index is held in a function variable rather than in a block parameter of the -+ // loop body. A block parameter becomes an OpPhi in SPIR-V, and loops with that shape hang -+ // the GPU on some Mali drivers (see https://crbug.com/568850691). - auto* loop = Loop(); -- auto* idx = BlockParam("idx", start_value->Type()); -- loop->Body()->SetParams({idx}); -+ ir::Var* idx_var = nullptr; - Append(loop->Initializer(), [&] { - // Start the loop with `idx = start`. -- NextIteration(loop, start_value); -+ idx_var = Var("idx", ir.Types().ptr(core::AddressSpace::kFunction, start_value->Type(), -+ core::Access::kReadWrite)); -+ idx_var->SetInitializer(start_value); -+ NextIteration(loop); - }); - Append(loop->Body(), [&] { - // Loop until `idx == end`. -+ auto* idx = Load(idx_var)->Result(); - auto* breakif = If(GreaterThanEqual(idx, end_value)); - Append(breakif->True(), [&] { // - ExitLoop(loop); -@@ -2096,8 +2102,9 @@ class Builder { - }); - Append(loop->Continuing(), [&] { - // Update the index with `idx += step` and go to the next iteration. -- auto* new_idx = Add(idx, step_value); -- NextIteration(loop, new_idx); -+ auto* idx = Load(idx_var)->Result(); -+ Store(idx_var, Add(idx, step_value)); -+ NextIteration(loop); - }); - } - diff --git a/packages/webgpu/scripts/generate-package-swift.ts b/packages/webgpu/scripts/generate-package-swift.ts deleted file mode 100644 index e378d623e7..0000000000 --- a/packages/webgpu/scripts/generate-package-swift.ts +++ /dev/null @@ -1,90 +0,0 @@ -#!/usr/bin/env tsx - -// Regenerates packages/webgpu/Package.swift for the Dawn release pinned in -// package.json ("dawn" field). Run this after build-dawn.yml has published a -// dawn-apple-.xcframework.zip release asset. Writes the file locally; -// commit and push it yourself. -// -// Pass --local to point the WebGPUDawn binary target at the xcframework -// already sitting in libs/apple/ (from `yarn install-dawn` or a local Dawn -// build) instead of downloading the release — useful for iterating on the -// package/example locally without a network round trip. - -import { execSync } from "child_process"; -import { mkdtempSync, readFileSync, rmSync, writeFileSync } from "fs"; -import { tmpdir } from "os"; -import { join } from "path"; - -import { - renderPackageSwift, - type WebGPUDawnBinaryTarget, -} from "./package-swift-template"; - -const packageJsonPath = join(__dirname, "..", "package.json"); -const packageJson = JSON.parse(readFileSync(packageJsonPath, "utf-8")); -const dawnVersion = packageJson.dawn; - -if (!dawnVersion) { - console.error("No 'dawn' field found in package.json"); - process.exit(1); -} - -const releaseTag = `dawn-${dawnVersion.replace("/", "-")}`; -const zipName = `dawn-apple-${releaseTag}.xcframework.zip`; -const zipUrl = `https://github.com/wcandillon/react-native-webgpu/releases/download/${releaseTag}/${zipName}`; -const checksumUrl = `${zipUrl}.checksum.txt`; - -const fetchChecksum = (): string => { - // Prefer the checksum file build-dawn.yml computes and uploads alongside - // the zip — avoids re-downloading the (large) xcframework locally. - try { - const checksum = execSync(`curl -sfL "${checksumUrl}"`, { - encoding: "utf-8", - }).trim(); - if (checksum) { - console.log(`Using published checksum from ${checksumUrl}`); - return checksum; - } - } catch { - console.log( - "Published checksum file not found, computing from the zip instead...", - ); - } - - const tmpDir = mkdtempSync(join(tmpdir(), "rnwgpu-package-swift-")); - const zipPath = join(tmpDir, zipName); - try { - execSync(`curl -fL -o "${zipPath}" "${zipUrl}"`, { stdio: "inherit" }); - return execSync(`swift package compute-checksum "${zipPath}"`, { - encoding: "utf-8", - }).trim(); - } finally { - rmSync(tmpDir, { recursive: true, force: true }); - } -}; - -const useLocal = process.argv.includes("--local"); - -console.log( - useLocal - ? "Generating Package.swift against the local xcframework in libs/apple/..." - : `Generating Package.swift for ${releaseTag}...`, -); - -const target: WebGPUDawnBinaryTarget = useLocal - ? { kind: "local", path: "libs/apple/libwebgpu_dawn.xcframework" } - : { kind: "remote", url: zipUrl, checksum: fetchChecksum() }; - -const outputPath = join(__dirname, "..", "Package.swift"); -writeFileSync( - outputPath, - renderPackageSwift({ target, dawnReleaseTag: releaseTag }), -); - -console.log(`Wrote ${outputPath}`); -if (target.kind === "remote") { - console.log(` url: ${target.url}`); - console.log(` checksum: ${target.checksum}`); -} else { - console.log(` path: ${target.path}`); -} diff --git a/packages/webgpu/scripts/install-dawn.ts b/packages/webgpu/scripts/install-dawn.ts deleted file mode 100644 index 7e362f3cfe..0000000000 --- a/packages/webgpu/scripts/install-dawn.ts +++ /dev/null @@ -1,309 +0,0 @@ -#!/usr/bin/env tsx - -import { execSync } from "child_process"; -import { existsSync, mkdirSync, readFileSync, rmSync } from "fs"; -import { join } from "path"; - -import { checkBuildArtifacts } from "./build/dawn-configuration"; -import { checkDuplicateHeaders } from "./build/util"; - -// ANSI color codes -const colors = { - reset: "\x1b[0m", - bright: "\x1b[1m", - dim: "\x1b[2m", - red: "\x1b[31m", - green: "\x1b[32m", - yellow: "\x1b[33m", - blue: "\x1b[34m", - cyan: "\x1b[36m", - white: "\x1b[37m", -}; - -const symbols = { - success: "✅", - error: "❌", - warning: "⚠️", - info: "ℹ️", - download: "⬇️", - extract: "📦", - clean: "🧹", - check: "✓", - arrow: "→", - rocket: "🚀", -}; - -// Helper functions for colored output -const log = { - info: (msg: string) => - console.log(`${colors.cyan}${symbols.info} ${msg}${colors.reset}`), - success: (msg: string) => - console.log(`${colors.green}${symbols.success} ${msg}${colors.reset}`), - error: (msg: string) => - console.error(`${colors.red}${symbols.error} ${msg}${colors.reset}`), - warning: (msg: string) => - console.log(`${colors.yellow}${symbols.warning} ${msg}${colors.reset}`), - step: (msg: string) => - console.log(`${colors.blue}${symbols.arrow} ${msg}${colors.reset}`), - header: (msg: string) => { - console.log(""); - console.log( - `${colors.bright}${colors.cyan}${"=".repeat(60)}${colors.reset}`, - ); - console.log( - `${colors.bright}${colors.cyan}${symbols.rocket} ${msg}${colors.reset}`, - ); - console.log( - `${colors.bright}${colors.cyan}${"=".repeat(60)}${colors.reset}`, - ); - console.log(""); - }, - subheader: (msg: string) => { - console.log(""); - console.log(`${colors.bright}${colors.blue}── ${msg} ──${colors.reset}`); - }, -}; - -// Read the dawn version from package.json -const packageJsonPath = join(__dirname, "..", "package.json"); -const packageJson = JSON.parse(readFileSync(packageJsonPath, "utf-8")); -const dawnVersion = packageJson.dawn; - -if (!dawnVersion) { - log.error("No 'dawn' field found in package.json"); - process.exit(1); -} - -// Workarounds in our C++ for Dawn bugs that an upstream fix makes obsolete. -// Each entry names the Dawn release it was validated against. Bumping the pin -// past it fails the install until whoever does the bump checks whether the -// upstream fix is included: if it is, delete the marked code and the entry; -// if it is not, update `pin` here (and re-verify the diagnostic screen). -const dawnWorkarounds = [ - { - marker: "DAWN_WORKAROUND_DEVICE_DESTROY_BEFORE_SURFACE_RELEASE", - pin: "chrome-m154a", - files: ["cpp/rnwgpu/SurfaceRegistry.h", "cpp/rnwgpu/api/GPUDevice.cpp"], - // Android: device.destroy() before the native view is dropped crashed in - // SwapChain::DetachFromSurfaceImpl (Vulkan FencedDeleter of the dead - // device). Verify with the "Device Destroy Before Detach" diagnostic in - // the example app. - upstream: "Dawn CL pending (see the workaround comment in the files)", - }, -]; - -for (const workaround of dawnWorkarounds) { - const root = join(__dirname, ".."); - const present = workaround.files.filter((file) => { - const path = join(root, file); - return ( - existsSync(path) && - readFileSync(path, "utf-8").includes(workaround.marker) - ); - }); - if (present.length === 0) { - log.error( - `Workaround ${workaround.marker} is gone from the sources; remove its entry from scripts/install-dawn.ts`, - ); - process.exit(1); - } - if (present.length !== workaround.files.length) { - const missing = workaround.files.filter((file) => !present.includes(file)); - log.error( - `Workaround ${workaround.marker} is only partially applied: missing from ${missing.join(", ")}`, - ); - process.exit(1); - } - if (dawnVersion !== workaround.pin) { - log.error( - `Dawn pin changed (${workaround.pin} -> ${dawnVersion}) but ${workaround.marker} is still in ${present.join(", ")}`, - ); - log.error( - `Check whether this Dawn contains the upstream fix (${workaround.upstream}). If it does, remove the marked code and this entry; if not, update the pin in scripts/install-dawn.ts`, - ); - process.exit(1); - } -} - -// Parse the dawn version to construct the release tag -// Format: "chrome-m152" -> "dawn-chrome-m152" -const releaseTag = `dawn-${dawnVersion.replace("/", "-")}`; -const releaseUrl = `https://github.com/wcandillon/react-native-webgpu/releases/tag/${releaseTag}`; - -log.header(`Installing Dawn ${dawnVersion}`); -log.info(`Release: ${colors.dim}${releaseUrl}${colors.reset}`); - -// Define the libs directory -const libsDir = join(__dirname, "..", "libs"); - -// Clean up existing libs directory if it exists -if (existsSync(libsDir)) { - log.step(`${symbols.clean} Cleaning existing libs directory...`); - rmSync(libsDir, { recursive: true, force: true }); -} - -// Create libs directory -mkdirSync(libsDir, { recursive: true }); - -// Define the cpp directory -const cppDir = join(__dirname, "..", "cpp"); - -// Define the assets to download -const assets = [ - { - name: `dawn-android-${releaseTag}.tar.gz`, - extractTo: libsDir, - postProcess: () => { - // Rename dawn-android to android for compatibility - const oldPath = join(libsDir, "dawn-android"); - const newPath = join(libsDir, "android"); - if (existsSync(oldPath)) { - execSync(`mv "${oldPath}" "${newPath}"`); - } - }, - }, - { - name: `dawn-apple-${releaseTag}.xcframework.zip`, - extractTo: libsDir, - postProcess: () => { - // The extracted xcframework needs to be placed as libs/apple/libwebgpu_dawn.xcframework - const extractedPath = join(libsDir, "dawn-apple.xcframework"); - const targetDir = join(libsDir, "apple"); - const targetPath = join(targetDir, "libwebgpu_dawn.xcframework"); - - if (existsSync(extractedPath)) { - // Create apple directory if it doesn't exist - if (!existsSync(targetDir)) { - mkdirSync(targetDir, { recursive: true }); - } - // Move the xcframework to the correct location - execSync(`mv "${extractedPath}" "${targetPath}"`); - } - }, - }, - { - name: `dawn-headers-${releaseTag}.tar.gz`, - extractTo: libsDir, - postProcess: () => { - // clean folders - rmSync("cpp/dawn", { recursive: true, force: true }); - rmSync("cpp/webgpu", { recursive: true, force: true }); - // Move headers directly to cpp directory - const headersIncludePath = join(libsDir, "dawn-headers", "include"); - if (existsSync(join(headersIncludePath, "webgpu"))) { - execSync(`cp -R "${join(headersIncludePath, "webgpu")}" "${cppDir}/"`); - } - if (existsSync(join(headersIncludePath, "dawn"))) { - execSync(`cp -R "${join(headersIncludePath, "dawn")}" "${cppDir}/"`); - } - // Remove the dawn-headers directory after copying - rmSync(join(libsDir, "dawn-headers"), { recursive: true, force: true }); - rmSync("cpp/dawn/wire", { recursive: true, force: true }); - // Copy headers from cpp/dawn/ to cpp/webgpu/ and then delete source files - execSync( - `cp "cpp/dawn/webgpu_cpp_print.h" "cpp/webgpu/webgpu_cpp_print.h"`, - ); - execSync(`cp "cpp/dawn/webgpu_cpp.h" "cpp/webgpu/webgpu_cpp.h"`); - execSync(`cp "cpp/dawn/webgpu.h" "cpp/webgpu/webgpu.h"`); - rmSync("cpp/dawn", { recursive: true, force: true }); - checkDuplicateHeaders(`cpp`); - }, - }, -]; - -// Download and extract assets -log.subheader("Downloading Assets"); - -// Add nice names for display -const assetNames: { [key: string]: string } = { - [`dawn-android-${releaseTag}.tar.gz`]: "Android Libraries", - [`dawn-apple-${releaseTag}.xcframework.zip`]: "Apple Framework", - [`dawn-headers-${releaseTag}.tar.gz`]: "C++ Headers", -}; - -for (const [index, asset] of assets.entries()) { - const assetUrl = `https://github.com/wcandillon/react-native-webgpu/releases/download/${releaseTag}/${asset.name}`; - const tarPath = join(libsDir, asset.name); - const displayName = assetNames[asset.name] || asset.name; - - console.log(""); - log.step(`[${index + 1}/${assets.length}] ${displayName}`); - - try { - // Download the asset - process.stdout.write( - ` ${colors.dim}${symbols.download} Downloading...${colors.reset}`, - ); - execSync(`curl -L -o "${tarPath}" "${assetUrl}" 2>&1`, { stdio: "pipe" }); - process.stdout.write("\r\x1b[K"); // Clear the line - - // Extract the tar file - process.stdout.write( - ` ${colors.dim}${symbols.extract} Extracting...${colors.reset}`, - ); - if (asset.name.endsWith(".zip")) { - execSync(`unzip -q -o "${tarPath}" -d "${asset.extractTo}"`, { - stdio: "pipe", - }); - } else { - execSync(`tar -xzf "${tarPath}" -C "${asset.extractTo}"`, { - stdio: "pipe", - }); - } - process.stdout.write("\r\x1b[K"); // Clear the line - - // Remove the tar file after extraction - rmSync(tarPath); - - // Run post-processing if defined - if (asset.postProcess) { - asset.postProcess(); - } - - log.success(`${displayName} installed`); - } catch (error) { - console.log(""); // New line after progress - log.error(`Failed to process ${displayName}`); - console.error(error); - process.exit(1); - } -} - -// Verify build artifacts -log.subheader("Verifying Installation"); -console.log(""); - -const originalLog = console.log; -try { - // Capture the output to format it nicely - const artifacts: string[] = []; - console.log = (msg: string) => { - if (msg.includes("✅")) { - artifacts.push(msg.replace("✅", "").trim()); - } else if (msg.includes("Check build artifacts")) { - // Skip this line - } else if (msg.includes("Failed:")) { - // Will be handled by the error - } else { - originalLog(msg); - } - }; - - checkBuildArtifacts(); - console.log = originalLog; - - // Display verified artifacts - artifacts.forEach((artifact) => { - console.log( - ` ${colors.green}${symbols.check}${colors.reset} ${colors.dim}${artifact}${colors.reset}`, - ); - }); - - console.log(""); - log.header(`Dawn ${dawnVersion} installed successfully!`); -} catch (error) { - console.log = originalLog; - console.log(""); - log.error("Installation verification failed"); - throw error; -} diff --git a/packages/webgpu/scripts/package-swift-template.ts b/packages/webgpu/scripts/package-swift-template.ts deleted file mode 100644 index 2057eb78b8..0000000000 --- a/packages/webgpu/scripts/package-swift-template.ts +++ /dev/null @@ -1,196 +0,0 @@ -// Template for the generated packages/webgpu/Package.swift. -// Kept in its own module so generate-package-swift.ts stays focused on -// fetching the release metadata. -// -// The manifest mirrors react-native-skia's packages/skia/Package.swift -// (same integration model, same relative paths, same platform floor, same -// defines). Keep the two aligned when changing either. - -export type WebGPUDawnBinaryTarget = - | { kind: "remote"; url: string; checksum: string } - | { kind: "local"; path: string }; - -export interface PackageSwiftInputs { - target: WebGPUDawnBinaryTarget; - // Dawn release tag, e.g. "dawn-chrome-m154". Same string that - // react-native-skia's Graphite installer records in - // libs/.dawn-version, which is what the manifest compares against. - dawnReleaseTag: string; -} - -// Must match `spm.name` in react-native.config.js: React Native's autolinker -// looks the product up by that name, and it is the package identity too. -export const SWIFT_PACKAGE_NAME = "ReactNativeWebGPU"; - -const renderBinaryTarget = (target: WebGPUDawnBinaryTarget) => - target.kind === "remote" - ? `.binaryTarget( - name: "WebGPUDawn", - url: "${target.url}", - checksum: "${target.checksum}" - )` - : `.binaryTarget( - name: "WebGPUDawn", - path: "${target.path}" - )`; - -export const renderPackageSwift = ({ - target, - dawnReleaseTag, -}: PackageSwiftInputs) => `// swift-tools-version: 6.0 -// Generated by scripts/generate-package-swift.ts — do not edit by hand. -// Re-run that script after a new Dawn release to update the URL/checksum below. -// -// SwiftPM manifest for react-native-webgpu. iOS only. -// Additive: the CocoaPods podspec remains the supported default. -// -// React Native 0.87+ references a library that ships its own Package.swift -// through a symlink at /ios/build/generated/autolinking/libs/, and -// resolves the relative paths below against that symlink. They are the same -// for every standard app, because the symlink location is. Earlier React -// Native releases have no SwiftPM autolinking: keep CocoaPods there. - -import Foundation -import PackageDescription - -// Absolute location of this package. Xcode passes the autolinking symlink as -// the package directory, so resolve it before deriving sibling paths. -let packageRoot = URL(fileURLWithPath: Context.packageDirectory) - .resolvingSymlinksInPath().path -let sibling = { (relative: String) -> String in - URL(fileURLWithPath: "\\(packageRoot)/\\(relative)").standardized.path -} - -// Skia Graphite and WebGPU must link the exact same Dawn, or the pair links -// fine and crashes at runtime. react-native-skia's podspec enforces this at -// \`pod install\` time by comparing its libs/.dawn-version against this -// package's \`dawn\` field. A Swift package has no install hook, so the same -// check runs here, at manifest evaluation. SwiftPM caches evaluations, so -// after changing either package's Dawn version reset the package caches -// (File > Packages > Reset Package Caches) if this does not re-run. -let dawnReleaseTag = "${dawnReleaseTag}" -// Only Graphite builds of react-native-skia carry this marker (Ganesh builds -// do not link Dawn and impose no constraint). From v3 the Skia binaries ship -// in react-native-skia-graphite-apple-ios, which records the tag at -// libs/.dawn-version; react-native-skia's podspec copies it into its own -// libs/ at \`pod install\`, which never runs here. The v2 Graphite previews -// (e.g. @shopify/react-native-skia@2.12.0-next.1) keep it in their own libs/. -// The graphite packages are normally hoisted next to this package, but may -// be nested under react-native-skia when the package manager cannot hoist -// them. Every marker found is checked. -let skiaDawnMarkers = [ - "react-native-skia-graphite-apple-ios/libs/.dawn-version", - "react-native-skia-graphite-apple-macos/libs/.dawn-version", - "react-native-skia/node_modules/react-native-skia-graphite-apple-ios/libs/.dawn-version", - "react-native-skia/node_modules/react-native-skia-graphite-apple-macos/libs/.dawn-version", - "@shopify/react-native-skia/libs/.dawn-version", -].flatMap { marker in - [ - sibling("../\\(marker)"), // consumer: sibling in node_modules - sibling("../../node_modules/\\(marker)"), // this monorepo - ] -} -for marker in skiaDawnMarkers { - guard let data = FileManager.default.contents(atPath: marker), - let skiaDawn = String(data: data, encoding: .utf8)? - .trimmingCharacters(in: .whitespacesAndNewlines) - else { continue } - if skiaDawn != dawnReleaseTag { - fatalError( - """ - react-native-webgpu: Dawn version mismatch. This package links \\(dawnReleaseTag) \\ - but the react-native-skia Graphite binaries (\\(marker)) link \\(skiaDawn). \\ - Align the two packages so the app contains exactly one Dawn. - """) - } -} - -// Unlike a native Xcode target, SwiftPM doesn't generate an implicit -// per-target header map, so quoted includes only resolve within the -// including file's own directory. The sources use bare cross-directory -// includes (e.g. apple/WebGPUModule.h includes "RNWebGPUManager.h" from -// cpp/rnwgpu), so every directory that's the target of one of those bare -// includes has to be listed explicitly here. -let internalHeaderDirs = [ - "apple", - // "cpp" itself resolves the "webgpu/..." and "dawn/..." namespaced - // includes. Those two directories are only present locally when built via - // \`yarn install-dawn\` (without the xcframework's embedded headers); a - // remote binaryTarget's xcframework embeds them instead (see - // build-dawn.yml's \`-headers\` flag), so "cpp" not containing them there - // is fine — the xcframework's own headers cover it. - "cpp", - "cpp/jsi", - "cpp/rnwgpu", - "cpp/rnwgpu/api", - "cpp/rnwgpu/api/descriptors", - "cpp/rnwgpu/async", -] - -let package = Package( - name: "${SWIFT_PACKAGE_NAME}", - // SwiftPM refuses to link a product whose floor is above the depending - // target's. React Native's generated Autolinked aggregate hardcodes iOS 15.0 - // (react-native#58379 derives it from the app instead), so this must not - // exceed 15.0; a lower floor is always accepted. - platforms: [.iOS(.v15)], - products: [ - // Autolinking looks this name up verbatim; react-native.config.js pins it. - .library(name: "${SWIFT_PACKAGE_NAME}", targets: ["${SWIFT_PACKAGE_NAME}"]) - ], - dependencies: [ - .package(name: "React-GeneratedCode", path: "../../../ios"), - .package(name: "ReactNative", path: "../../../../xcframeworks"), - ], - targets: [ - // Dawn's compiled WebGPU implementation. The xcframework embeds the - // \`webgpu/\` and \`dawn/\` C headers per-slice (built via \`-headers\` in - // build-dawn.yml), so SPM exposes them to dependents automatically. - ${renderBinaryTarget(target)}, - .target( - name: "${SWIFT_PACKAGE_NAME}", - dependencies: [ - .product(name: "ReactHeaders", package: "ReactNative"), - .product(name: "ReactNativeHeaders", package: "ReactNative"), - .product(name: "ReactNativeDependenciesHeaders", package: "ReactNative"), - // RNWgpuViewSpec, generated by the app's codegen run. - .product(name: "ReactAppHeaders", package: "React-GeneratedCode"), - "WebGPUDawn", - ], - // apple/ and cpp/ have no common ancestor below the package root, and - // .headerSearchPath cannot escape the target path. - path: ".", - // Explicit, so SwiftPM never walks node_modules, lib, android, or the - // headers-only cpp/webgpu and cpp/dawn trees. - sources: ["apple", "cpp/jsi", "cpp/rnwgpu"], - // SwiftPM requires a public headers directory inside the target and - // defaults to "include", which this package does not have. - publicHeadersPath: "apple", - cxxSettings: internalHeaderDirs.map { CXXSetting.headerSearchPath($0) } + [ - // CocoaPods forces both project-wide; the SwiftPM path defines neither. - // React Native's headers gate on them, and the prebuilt React.framework - // was built with both, so the module must see the same declarations. - .define("RCT_NEW_ARCH_ENABLED", to: "1"), - .define("RCT_REMOVE_LEGACY_ARCH", to: "1"), - - // React's prebuilt C++ ABI is NDEBUG-gated (DebugStringConvertible's - // vtable and ShadowNode layout diverge). Omitting either breaks the - // Release link. - .define("DEBUG", .when(configuration: .debug)), - .define("NDEBUG", .when(configuration: .release)), - ], - linkerSettings: [ - // VideoPlayer uses AVFoundation / CoreMedia, shared-texture surfaces - // use CoreVideo (CVPixelBuffer), and ImageIO provides CGImageSource, - // the image decoder behind createImageBitmap. - .linkedFramework("AVFoundation"), - .linkedFramework("CoreMedia"), - .linkedFramework("CoreVideo"), - .linkedFramework("ImageIO"), - ] - ), - ], - // React Native's headers need C++20. - cxxLanguageStandard: .cxx20 -) -`; diff --git a/packages/webgpu/src/__tests__/FeatureNames.spec.ts b/packages/webgpu/src/__tests__/FeatureNames.spec.ts index 6b1fd9ba4b..5468593513 100644 --- a/packages/webgpu/src/__tests__/FeatureNames.spec.ts +++ b/packages/webgpu/src/__tests__/FeatureNames.spec.ts @@ -7,10 +7,20 @@ const cppDir = path.resolve(__dirname, "..", "..", "cpp"); const read = (...segments: string[]) => fs.readFileSync(path.join(cppDir, ...segments), "utf-8"); -// Every value of wgpu::FeatureName, straight from the Dawn headers installed by -// `yarn install-dawn`. A milestone upgrade grows this list. +// The Dawn headers of the installed react-native-webgpu-dawn package. +const dawnInclude = path.join( + path.dirname(require.resolve("react-native-webgpu-dawn/package.json")), + "include", +); + +// Every value of wgpu::FeatureName, straight from the Dawn headers (the +// webgpu/ header is a shim onto the generated dawn/ one). A milestone upgrade +// grows this list. const dawnFeatureNames = () => { - const header = read("webgpu", "webgpu_cpp.h"); + const header = fs.readFileSync( + path.join(dawnInclude, "dawn", "webgpu_cpp.h"), + "utf-8", + ); const body = /enum class FeatureName[^{]*\{([\s\S]*?)\n\};/.exec(header); if (!body) { throw new Error("Could not find enum class FeatureName in webgpu_cpp.h"); diff --git a/spm-example/README.md b/spm-example/README.md index 7f2dda57cf..589dc9e500 100644 --- a/spm-example/README.md +++ b/spm-example/README.md @@ -42,9 +42,8 @@ Release embeds its own JS bundle, so it needs no Metro. For Debug, run - **Stale `Package.resolved`.** Xcode caches package pins in `ios/SpmExample.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved`. - When switching the Dawn binary between the release zip and a local - `libs/apple/` build (`yarn generate-package-swift --local`), delete it first - or the old source is silently kept. + After changing the `react-native-webgpu-dawn` version, delete it first or the + old pin is silently kept. - **`spm update` re-adds an absolute `HERMES_CLI_PATH`.** On React Native 0.87.1 the injector writes this machine's own path to `hermesc` into `project.pbxproj` and `.spm-injected.json`. The build does not need it, so it diff --git a/yarn.lock b/yarn.lock index 929ad8a2e9..539406284d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7957,7 +7957,7 @@ __metadata: react-native-nitro-modules: 0.35.7 react-native-reanimated: 4.3.1 react-native-safe-area-context: ^5.4.0 - react-native-skia: 3.0.6 + react-native-skia: 3.0.8 react-native-test-app: 4.4.10 react-native-vision-camera: 5.0.10 react-native-vision-camera-worklets: 5.0.10 @@ -20803,9 +20803,9 @@ __metadata: languageName: node linkType: hard -"react-native-skia@npm:3.0.6": - version: 3.0.6 - resolution: "react-native-skia@npm:3.0.6" +"react-native-skia@npm:3.0.8": + version: 3.0.8 + resolution: "react-native-skia@npm:3.0.8" dependencies: canvaskit-wasm: 0.41.0 react-native-skia-graphite-android: 154.1.0 @@ -20826,7 +20826,7 @@ __metadata: optional: true bin: setup-skia-web: scripts/setup-canvaskit.js - checksum: f8560a493501e087c01f1316fc52dea34c614713d7bb52e1c8556cd6f031ffeaf4bbc2274b0438006d312cae418da2991d4365a4a4802e4bf9d8733b21bc96f2 + checksum: bbcc642bd99a3839124389ea229450c9993b04b804703e96d8c94647bbf954a171088bd4d2c5a1b529d3eb26c0b52809934cba17aa0ff5482d8242d34b640e24 languageName: node linkType: hard @@ -20911,6 +20911,13 @@ __metadata: languageName: node linkType: hard +"react-native-webgpu-dawn@npm:154.2.0": + version: 154.2.0 + resolution: "react-native-webgpu-dawn@npm:154.2.0" + checksum: e9798715a2f6402a3dd265b0daace8232e0245c118badba2a043c4696b7c34de5bc958267602cc0f9524c43d032efa8c3fcad40453dc1ca9c07c1a3cba60f995 + languageName: node + linkType: hard + "react-native-webgpu-monorepo@workspace:.": version: 0.0.0-use.local resolution: "react-native-webgpu-monorepo@workspace:." @@ -20972,6 +20979,7 @@ __metadata: react-native-builder-bob: ^0.23.2 react-native-reanimated: ^4.2.1 react-native-web: ^0.21.2 + react-native-webgpu-dawn: 154.2.0 react-native-worklets: 0.8.3 rimraf: ^5.0.7 seedrandom: ^3.0.5 From 0ddf815165e3037025ee901d2a160c7a40d1c453 Mon Sep 17 00:00:00 2001 From: William Candillon Date: Wed, 7 Oct 2026 21:03:11 +0200 Subject: [PATCH 2/3] =?UTF-8?q?docs(=F0=9F=93=9A):=20update=20the=20Dawn?= =?UTF-8?q?=20compatibility=20table=20for=20react-native-webgpu-dawn?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Both libraries now depend on the react-native-webgpu-dawn package. The table lists which releases pair, including the mixed rows where one side still vendors the same Dawn commit, and the Android limitation of react-native-skia 3.0.6 and 3.0.7 next to a react-native-webgpu that links the package. --- .../docs/integrations/react-native-skia.mdx | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/apps/docs/content/docs/integrations/react-native-skia.mdx b/apps/docs/content/docs/integrations/react-native-skia.mdx index 486d782284..b18673bc4b 100644 --- a/apps/docs/content/docs/integrations/react-native-skia.mdx +++ b/apps/docs/content/docs/integrations/react-native-skia.mdx @@ -14,23 +14,26 @@ Starting with v3, react-native-skia renders with Graphite, on top of Dawn, the s With react-native-skia v2, which keeps the Ganesh backend (and was published as `@shopify/react-native-skia` up to 2.14), there is no coupling at all: any version of either package can be installed together, and they simply don't interact. -Because react-native-skia links react-native-webgpu's Dawn copy, the two packages must be built against the same Dawn; this is what makes sharing an instance and importing devices sound. Releases are kept in lockstep, and the native build fails with an explicit message if the tags ever differ, so a mismatch surfaces at build time rather than as undefined behavior at runtime. react-native-skia v2 has no such constraint. +Because react-native-skia links react-native-webgpu's Dawn copy, the two packages must be built against the same Dawn; this is what makes sharing an instance and importing devices sound. Releases are kept in lockstep, and the native build fails with an explicit `Dawn version mismatch` message if the two ever differ, so a mismatch surfaces at build time rather than as undefined behavior at runtime. react-native-skia v2 has no such constraint. ## Compatibility -Both packages follow Chrome/Skia milestones: react-native-skia publishes its binaries as `react-native-skia-graphite-*` and the Dawn they were built with as `react-native-webgpu-dawn`, all at `.x.y`, and react-native-webgpu depends on that Dawn package. Pick one row and install versions from it. A letter suffix on the Dawn tag (for instance `dawn-chrome-m154a`) is the same Dawn commit rebuilt with additional patches; it still counts as a different tag, so the two packages must agree on the suffix too. +Both packages follow Chrome/Skia milestones. react-native-skia publishes its binaries as `react-native-skia-graphite-*` and the Dawn they were built with as `react-native-webgpu-dawn`, all at `.x.y`, and both libraries depend on that Dawn package at the exact same version. Pick one row and install versions from it. A letter suffix on a Dawn tag (for instance `dawn-chrome-m154a`) is the same Dawn commit rebuilt with additional patches; it still counts as a different Dawn, so the two packages must agree on the suffix too. -| Milestone | react-native-webgpu | Dawn release tag | react-native-skia | +| Milestone | react-native-webgpu | Dawn | react-native-skia | | --- | --- | --- | --- | -| m154a | >= 0.12.1 | `dawn-chrome-m154a` (`react-native-webgpu-dawn` 154.2.0 from 0.13) | >= 3.0.6 (Graphite `154.x`) | -| m154 | 0.10.0 to 0.11.2 | `dawn-chrome-m154` | 3.0.0 to 3.0.5 (Graphite `154.x`) | +| m154a | 0.12.2 and later | `react-native-webgpu-dawn` 154.2.0 | 3.0.9 and later, or 3.0.8 | +| m154a | 0.12.1 | `dawn-chrome-m154a`, vendored | 3.0.6 to 3.0.8, or 3.0.9 and later | +| m154 | 0.10.0 to 0.11.2 | `dawn-chrome-m154`, vendored | 3.0.0 to 3.0.5 | + +From react-native-webgpu 0.12.2 and react-native-skia 3.0.9 both libraries depend on `react-native-webgpu-dawn` and the native build checks that they resolve the same version of it. The rows mixing one of them with an older release work because the older release vendors the same Dawn commit: react-native-skia 3.0.8 defers to react-native-webgpu's Dawn, and react-native-skia 3.0.9 accepts a react-native-webgpu 0.12.1 whose `dawnCommit` matches. On Android, react-native-skia 3.0.6 and 3.0.7 cannot pair with react-native-webgpu 0.12.2 and later: they still package their own `libwebgpu_dawn.so` next to the one from the package and the build fails merging the two. The Graphite previews of v2 (`@shopify/react-native-skia@next`, for instance 2.12.0-next.1) pair with react-native-webgpu the same way. Regular v2 releases are not part of this pairing: they do not link Dawn, so any version works alongside any version of react-native-webgpu. react-native-webgpu 0.6.4 and earlier predate the interop APIs (`importDevice` landed in 0.7.0); install them alongside react-native-skia v2 only. -To check what an installed pair is built against, compare `node -p "require('react-native-webgpu/package.json').dawn"` with the Dawn tag recorded next to the Skia binaries, in `node_modules/react-native-skia-graphite-apple-ios/libs/.dawn-version` (or `react-native-skia-graphite-android`). They have to name the same milestone. The installed Dawn itself is `node -p "require('react-native-webgpu-dawn/package.json').dawn.commit"`. +To check what an installed pair is built against, make sure a single version of `react-native-webgpu-dawn` is installed (`npm ls react-native-webgpu-dawn`, or `yarn why react-native-webgpu-dawn`); its `package.json` records the Dawn commit under `dawn.commit`. For a release that still vendors its Dawn, compare `node -p "require('react-native-webgpu/package.json').dawnCommit"` with that commit, or the `dawn` tag with the one recorded next to the Skia binaries in `node_modules/react-native-skia-graphite-apple-ios/libs/.dawn-version` (react-native-skia 3.0.x). ## Rendering with Skia's device From 4d4846160c46bbb89c76e6b5579e6b4a4e932f8a Mon Sep 17 00:00:00 2001 From: William Candillon Date: Wed, 7 Oct 2026 21:05:25 +0200 Subject: [PATCH 3/3] =?UTF-8?q?docs(=F0=9F=93=9A):=20the=20Dawn=20package?= =?UTF-8?q?=20lands=20in=20react-native-webgpu=200.13.0=20and=20react-nati?= =?UTF-8?q?ve-skia=203.1.0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/docs/content/docs/integrations/react-native-skia.mdx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/docs/content/docs/integrations/react-native-skia.mdx b/apps/docs/content/docs/integrations/react-native-skia.mdx index b18673bc4b..ce1e062a51 100644 --- a/apps/docs/content/docs/integrations/react-native-skia.mdx +++ b/apps/docs/content/docs/integrations/react-native-skia.mdx @@ -23,11 +23,11 @@ Both packages follow Chrome/Skia milestones. react-native-skia publishes its bin | Milestone | react-native-webgpu | Dawn | react-native-skia | | --- | --- | --- | --- | -| m154a | 0.12.2 and later | `react-native-webgpu-dawn` 154.2.0 | 3.0.9 and later, or 3.0.8 | -| m154a | 0.12.1 | `dawn-chrome-m154a`, vendored | 3.0.6 to 3.0.8, or 3.0.9 and later | +| m154a | 0.13.0 and later | `react-native-webgpu-dawn` 154.2.0 | 3.1.0 and later, or 3.0.8 | +| m154a | 0.12.1 | `dawn-chrome-m154a`, vendored | 3.0.6 to 3.0.8, or 3.1.0 and later | | m154 | 0.10.0 to 0.11.2 | `dawn-chrome-m154`, vendored | 3.0.0 to 3.0.5 | -From react-native-webgpu 0.12.2 and react-native-skia 3.0.9 both libraries depend on `react-native-webgpu-dawn` and the native build checks that they resolve the same version of it. The rows mixing one of them with an older release work because the older release vendors the same Dawn commit: react-native-skia 3.0.8 defers to react-native-webgpu's Dawn, and react-native-skia 3.0.9 accepts a react-native-webgpu 0.12.1 whose `dawnCommit` matches. On Android, react-native-skia 3.0.6 and 3.0.7 cannot pair with react-native-webgpu 0.12.2 and later: they still package their own `libwebgpu_dawn.so` next to the one from the package and the build fails merging the two. +From react-native-webgpu 0.13.0 and react-native-skia 3.1.0 both libraries depend on `react-native-webgpu-dawn` and the native build checks that they resolve the same version of it. The rows mixing one of them with an older release work because the older release vendors the same Dawn commit: react-native-skia 3.0.8 defers to react-native-webgpu's Dawn, and react-native-skia 3.1.0 accepts a react-native-webgpu 0.12.1 whose `dawnCommit` matches. On Android, react-native-skia 3.0.6 and 3.0.7 cannot pair with react-native-webgpu 0.13.0 and later: they still package their own `libwebgpu_dawn.so` next to the one from the package and the build fails merging the two. The Graphite previews of v2 (`@shopify/react-native-skia@next`, for instance 2.12.0-next.1) pair with react-native-webgpu the same way. Regular v2 releases are not part of this pairing: they do not link Dawn, so any version works alongside any version of react-native-webgpu.