diff --git a/.github/workflows/prebuild-ios.yml b/.github/workflows/prebuild-ios.yml index e2bf4b0b346..dd43f7762ff 100644 --- a/.github/workflows/prebuild-ios.yml +++ b/.github/workflows/prebuild-ios.yml @@ -43,3 +43,71 @@ jobs: key: v1-ios-dependencies-${{ hashfiles('scripts/releases/ios-prebuilds/configuration.js') }} enableCrossOsArchive: true path: packages/react-native/third-party/ + + build-apple-slices: + name: Build Apple Slice + runs-on: macos-14 + needs: [prepare_workspace] + strategy: + fail-fast: false + matrix: + flavor: ['Debug', 'Release'] + slice: ['ios', + 'ios-simulator', + 'macos', + 'mac-catalyst', + 'tvos', + 'tvos-simulator', + 'xros', + 'xros-simulator'] + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: Setup node.js + uses: ./.github/actions/setup-node + - name: Setup xcode + uses: ./.github/actions/setup-xcode + with: + xcode-version: '16.1' + - name: Restore slice folder + id: restore-slice-folder + uses: actions/cache/restore@v4 + with: + path: packages/react-native/third-party/.build/Build/Products + key: v1-ios-dependencies-slice-folder-${{ matrix.slice }}-${{ matrix.flavor }}-${{ hashfiles('scripts/releases/ios-prebuilds/configuration.js') }} + - name: Yarn Install + if: steps.restore-slice-folder.outputs.cache-hit != 'true' + uses: ./.github/actions/yarn-install + - name: Restore workspace + if: steps.restore-slice-folder.outputs.cache-hit != 'true' + uses: actions/download-artifact@v4 + with: + name: ios-prebuilds-workspace + path: packages/react-native/third-party/ + - name: Print third-party folder structure + run: ls -lR packages/react-native/third-party + - name: Install VisionOS + if: ${{ steps.restore-slice-folder.outputs.cache-hit != 'true' && (matrix.slice == 'xros' || matrix.slice == 'xros-simulator') }} + run: | + # https://github.com/actions/runner-images/issues/10559 + sudo xcodebuild -runFirstLaunch + sudo xcrun simctl list + sudo xcodebuild -downloadPlatform visionOS + sudo xcodebuild -runFirstLaunch + - name: Build slice ${{ matrix.slice }} for ${{ matrix.flavor }} + if: steps.restore-slice-folder.outputs.cache-hit != 'true' + run: node scripts/releases/prepare-ios-prebuilds.js -b -p ${{ matrix.slice }} -r ${{ matrix.flavor }} + - name: Upload Artifacts + uses: actions/upload-artifact@v4.3.4 + with: + name: ios-slice-${{ matrix.flavor }}-${{ matrix.slice }} + path: | + packages/react-native/third-party/.build/Build/Products + - name: Save Cache + uses: actions/cache/save@v4 + if: ${{ github.ref == 'refs/heads/main' }} # To avoid that the cache explode + with: + key: v1-ios-dependencies-slice-folder-${{ matrix.slice }}-${{ matrix.flavor }}-${{ hashfiles('scripts/releases/ios-prebuilds/configuration.js') }} + enableCrossOsArchive: true + path: | + packages/react-native/third-party/.build/Build/Products diff --git a/scripts/releases/ios-prebuild/build.js b/scripts/releases/ios-prebuild/build.js index 288eb37ceee..96a6fdf4826 100644 --- a/scripts/releases/ios-prebuild/build.js +++ b/scripts/releases/ios-prebuild/build.js @@ -16,7 +16,7 @@ const fs = require('fs'); const path = require('path'); /*:: -import type { Dependency, Platform } from './types'; +import type { Dependency, Destination, Platform } from './types'; */ /** @@ -28,15 +28,21 @@ async function buildDepenencies( scheme /*: string */, configuration /*: string */, dependencies /*: $ReadOnlyArray */, - platforms /*: $ReadOnlyArray */, + destinations /*: $ReadOnlyArray */, rootFolder /*: string */, buildFolder /*: string */, ) { console.log('✅ Building dependencies...'); await Promise.all( - platforms.map(platform => - buildPlatform(scheme, configuration, platform, rootFolder, buildFolder), + destinations.map(destination => + buildPlatform( + scheme, + configuration, + destination, + rootFolder, + buildFolder, + ), ), ); @@ -50,13 +56,13 @@ async function buildDepenencies( async function buildPlatform( scheme /*: string */, configuration /*: string */, - platform /*: Platform */, + destination /*: Destination */, rootFolder /*: string */, buildFolder /*: string */, ) { - console.log(`Building ${platform}...`); + console.log(`Building ${destination}...`); const command = - `xcodebuild -scheme "${scheme}" -destination "generic/platform=${platform}" ` + + `xcodebuild -scheme "${scheme}" -destination "generic/platform=${destination}" ` + `-derivedDataPath "${buildFolder}" ` + `-configuration "${configuration}" ` + 'SKIP_INSTALL=NO \ diff --git a/scripts/releases/ios-prebuild/cli.js b/scripts/releases/ios-prebuild/cli.js index 5cc36865b8b..f01007ed17e 100644 --- a/scripts/releases/ios-prebuild/cli.js +++ b/scripts/releases/ios-prebuild/cli.js @@ -13,9 +13,22 @@ const {dependencies, platforms} = require('./configuration'); const yargs = require('yargs'); /*:: -import type {Dependency, Platform} from './types'; +import type {Dependency, Destination, Platform} from './types'; */ +// CI can't use commas in cache keys, so 'macOS,variant=Mac Catalyst' was creating troubles +// This map that converts from platforms to valid Xcodebuild destinations. +const platformToDestination /*: $ReadOnly<{|[Platform]: Destination|}> */ = { + ios: 'iOS', + 'ios-simulator': 'iOS Simulator', + macos: 'macOS', + 'mac-catalyst': 'macOS,variant=Mac Catalyst', + tvos: 'tvOS', + 'tvos-simulator': 'tvOS Simulator', + xros: 'visionOS', + 'xros-simulator': 'visionOS Simulator', +}; + const arrayLike = (value /*: Array */) /*: Array */ => Array.isArray(value) ? value : [value]; @@ -74,7 +87,7 @@ async function getCLIConfiguration() /*: Promise, + destinations: $ReadOnlyArray, dependencies: $ReadOnlyArray, configuration: string, |}> */ { @@ -102,7 +115,9 @@ async function getCLIConfiguration() /*: Promise argv.platforms.includes(p)); + const resolvedPlatforms = platforms + .filter(p => argv.platforms.includes(p)) + .map(p => platformToDestination[p]); const resolvedDependencies = dependencies.filter(d => argv.dependencies.includes(d.name), ); @@ -121,7 +136,7 @@ async function getCLIConfiguration() /*: Promise */ = [ - 'iOS', - 'iOS Simulator', - 'macOS', - 'macOS,variant=Mac Catalyst', - 'tvOS', - 'tvOS Simulator', - 'visionOS', - 'visionOS Simulator', + 'ios', + 'ios-simulator', + 'macos', + 'mac-catalyst', + 'tvos', + 'tvos-simulator', + 'xros', + 'xros-simulator', ]; const CPP_STANDARD = 'c++20'; diff --git a/scripts/releases/ios-prebuild/types.js b/scripts/releases/ios-prebuild/types.js index 7e86ff60046..2d842afca77 100644 --- a/scripts/releases/ios-prebuild/types.js +++ b/scripts/releases/ios-prebuild/types.js @@ -49,13 +49,23 @@ export type Dependency = $ReadOnly<{ }>; export type Platform = + 'ios' | + 'ios-simulator' | + 'macos' | + 'mac-catalyst' | + 'tvos' | + 'tvos-simulator' | + 'xros' | + 'xros-simulator'; + +export type Destination = 'iOS' | - 'iOS Simulator' | - 'macOS' | + 'iOS Simulator' | + 'macOS' | 'macOS,variant=Mac Catalyst' | 'tvOS' | 'tvOS Simulator' | - 'visionOS' | + 'visionOS' | 'visionOS Simulator'; */ diff --git a/scripts/releases/prepare-ios-prebuilds.js b/scripts/releases/prepare-ios-prebuilds.js index e249af454bc..cfc716e56c7 100644 --- a/scripts/releases/prepare-ios-prebuilds.js +++ b/scripts/releases/prepare-ios-prebuilds.js @@ -52,7 +52,7 @@ async function main() { SCHEME, cli.configuration, cli.dependencies, - cli.platforms, + cli.destinations, rootFolder, buildFolder, );