new·The score now tells you which way it movedA brain's exam only ever grows: its own material writes questions, and so does every question a real caller asked and did not get answered. The score is a percentage over that growing set, so a brain that learned more could post a smaller number — and this week three did. One of them answered two MORE questions than the week before and showed eighteen points less. Printed as a single percentage, that reads as decline to a reader and as punishment to anyone who contributes material.all news →
mozg.beta
Sign in

Expo · EAS · all subjects

build-reference/ios-builds

94 notes in this subject, read out of this brain and free to use. This is page 1 of 2.

iOS build local steps: upload to GCS

EAS CLI creates a tarball of the repository and uploads it to a private Google Cloud Storage bucket, then sends the build request to EAS Build.

iOS build remote steps: VM creation

EAS Build creates a new macOS VM for each build. Every build gets its own fresh macOS VM with all required build tools installed, including Xcode and Fastlane.

iOS build remote steps: npm install

After downloading and unpacking the project tarball, EAS Build runs `npm install` in the project root (or `yarn install` if yarn.lock exists).

iOS build remote steps: pod install

After restoring cache, EAS Build runs `pod install` in the ios directory inside the project.

iOS build custom scripts

EAS Build supports the following custom scripts from package.json: `eas-build-pre-install` (runs before npm install), `eas-build-post-install` (runs after pod install), `eas-build-on-success` (runs if build succeeds), `eas-build-on-error` (runs if build fails), and `eas-build-on-complete` (runs after build with EAS_BUILD_STATUS environment variable set to either `finished` or `errored`). The deprecated `eas-build-pre-upload-artifacts` script is no longer used.

iOS build NPM_TOKEN handling

If `NPM_TOKEN` is set, EAS Build creates a .npmrc file during the remote build process.

iOS build expo-doctor check

EAS Build runs `npx expo-doctor` after npm install to diagnose potential issues with your project configuration.

Repack iOS IPA command example

$ npx @expo/repack-app --platform ios --source-app MyApp.ipa

Repack iOS .app bundle command example

$ npx @expo/repack-app --platform ios --source-app MyApp.app

Repack iOS signing command example

$ npx @expo/repack-app --platform ios --source-app MyApp.ipa --signing-identity "Apple Distribution: ..." --provisioning-profile /path/to/profile.mobileprovision

iOS repack signing limitation

iOS repacking supports ad-hoc and development signing only.

iOS ad hoc builds with --non-interactive behavior

For iOS ad hoc builds, `eas build --non-interactive` reuses a valid provisioning profile without updating its device list. The build can succeed, but the app may not install on registered devices added after the profile was last updated.

Refresh ad hoc provisioning profile flag

Pass `--refresh-ad-hoc-provisioning-profile` with `--non-interactive` to update the Expo-managed ad hoc provisioning profile on the Apple Developer Portal before the build. This flag requires EAS CLI 19.1.0 or later.

Build for iOS with eas build --platform ios

To create a build for the Apple App Store, run the command eas build --platform ios. You can optionally attach a message with --message flag, for example: eas build --platform ios --message "Some message".

eas/generate_gymfile_from_template template variables

The eas/generate_gymfile_from_template default templates use the following template variables: CLEAN, SCHEME, BUILD_CONFIGURATION, EXPORT_METHOD, PROFILES, ICLOUD_CONTAINER_ENVIRONMENT, KEYCHAIN_PATH, LOGS_DIRECTORY, OUTPUT_DIRECTORY, DERIVED_DATA_PATH, and SCHEME_SIMULATOR_DESTINATION. These values are provided to the template based on inputs and default EAS Build configuration.

eas/generate_gymfile_from_template function inputs

The eas/generate_gymfile_from_template function accepts inputs: template (optional string, custom template, defaults to built-in template), credentials (optional json, app credentials for iOS build), build_configuration (optional string, defaults to Debug for development or Release), scheme (optional string, defaults to first scheme in Xcode project), clean (optional boolean, defaults to true), and extra (optional json, extra values for custom templates).

eas/configure_ios_version is not mandatory

It is not mandatory to use eas/configure_ios_version. If not used, the version from native code generated during the prebuild phase will be used.

eas/run_fastlane step for iOS builds

The eas/run_fastlane step is used in custom iOS build workflows to execute fastlane commands. It typically appears after eas/generate_gymfile_from_template in the build steps sequence. Source code is available at https://github.com/expo/eas-cli/blob/main/packages/build-tools/src/steps/functions/runFastlane.ts

Example: development build iOS simulator configuration

A simple iOS simulator build can be configured with these steps: eas/checkout, eas/install_node_modules, eas/prebuild, run with command 'pod install' in ./ios directory, eas/generate_gymfile_from_template, eas/run_fastlane, eas/find_and_upload_build_artifacts.

Example: production build iOS for Apple App Store

A customized iOS App Store build uses these steps: eas/checkout, eas/install_node_modules, eas/resolve_apple_team_id_from_credentials (with id), eas/prebuild with apple_team_id input, run 'pod install' in ./ios directory, eas/configure_ios_credentials, eas/generate_gymfile_from_template with credentials input from eas.job.secrets.buildCredentials, eas/run_fastlane, eas/find_and_upload_build_artifacts.

Minimal React Native iOS app download size

The download size on the App Store of a minimal React Native app created using the blank template is just under 4 MB.

IPA file is a ZIP containing the .app bundle

IPA (iOS App Store Package) files are ZIP files that include the .app bundle and other resources needed to run the app on an iOS device. They include security and code signing information such as the provisioning profile and entitlements, and are used for various types of distribution including App Store, Ad Hoc, Enterprise, and TestFlight.

.app bundle cannot be installed directly on physical iOS devices

The .app file is the actual application bundle for your app. When you download and install a build of your app into an iOS Simulator, you are downloading the .app bundle. However, you cannot install a .app file directly to a physical iOS device.

App Store processes IPA into device-specific binaries

The App Store will process the IPA file and split it into smaller binaries for each device type. Therefore, the size of the IPA does not represent the download size of your app to users.

Get iOS app size estimates from TestFlight

On App Store Connect, navigate to TestFlight and select your build by clicking on the build number, then switch to the Build Metadata tab and click App File Sizes. You will see a list of estimated download and install sizes depending on the device type. Actual install sizes may vary slightly depending on the iOS version of the device.

Inspect iOS IPA contents by extracting as ZIP

To examine the contents of an iOS IPA, rename the file from app.ipa to app.zip and extract it. Use the macOS utility assetutil to inspect Assets.car for assets.

Manual code signing configuration for iOS without CNG

Without CNG, add two fields to the <dict> element in ios/project-name/Supporting/Expo.plist. First, convert the certificate by replacing \r with &#xD; using: node -e "console.log(require('fs').readFileSync('./certs/certificate.pem', 'utf8').replace(/\\r/g, '&#xD;'));". Then add: ```xml <key>EXUpdatesCodeSigningCertificate</key> <string>-----BEGIN CERTIFICATE-----&#xD; (insert XML-escaped certificate, spanning multiple lines with \r escaped but \n not escaped)&#xD; -----END CERTIFICATE-----&#xD; </string> <key>EXUpdatesCodeSigningMetadata</key> <dict> <key>keyid</key> <string>main</string> <key>alg</key> <string>rsa-v1_5-sha256</string> </dict> ```

Inspect Expo.plist after prebuild

When running eas build, npx expo prebuild is run to unpack android and ios directories. If the project does not have these directories, run npx expo prebuild locally to inspect the project state. Look for ios/your-project-name/Supporting/Expo.plist and verify it contains: <key>EXUpdatesRuntimeVersion</key> <string>your-runtime-version-here</string> and <key>EXUpdatesURL</key> <string>https://u.expo.dev/your-project-id-here</string>.

Inspect Expo.plist in iOS Simulator build

To inspect an iOS Simulator build on macOS: Create an iOS Simulator build by adding "ios": { "simulator": true } to a build profile; download and unzip the result; right-click on the app and select "Show Package Contents"; inspect the Expo.plist file. Expect to see: <key>EXUpdatesRequestHeaders</key> <dict> <key>expo-channel-name</key> <string>your-channel-name</string> </dict>, <key>EXUpdatesRuntimeVersion</key> <string>your-runtime-version</string>, and <key>EXUpdatesURL</key> <string>https://u.expo.dev/your-project-id</string>.

EAS Build iOS-specific options

iOS-specific options are available for EAS Build configuration, including image, env, and simulator properties.

iOS Podfile abstract target for app variants

To support multiple iOS app variants, replace a single target in the Podfile with an abstract target containing common configuration, then add individual targets for each variant. For example: abstract_target 'common' do, then target 'myapp' do end and target 'myapp-dev' do end.

Configure iOS bundle identifier for app variants

In Xcode Build Settings for an iOS target, find and change the Product Bundle Identifier to a unique value for each variant.

Change iOS app display name with DISPLAY_NAME variable

To change the display name for an iOS variant, open Info.plist and add key 'Bundle display name' with value '$(DISPLAY_NAME)'. Then in Xcode Build Settings for each target, find the User-Defined section and add key 'DISPLAY_NAME' with the desired name for that target.

Interactively select simulator with Shift+I

Press Shift + I in the Expo CLI to interactively select a simulator to open from a list of available iOS Simulators.

Xcode license acceptance may be required

When starting an app with Expo CLI, you may get a warning about needing to accept the Xcode license. Run the command that the warning suggests.

Multiple simulators can run simultaneously

You can open multiple iOS Simulators at the same time. However, Expo CLI will always target the most recently opened simulator.

Resolve xcrun errors by reinstalling Expo Go

For miscellaneous xcrun errors, try manually uninstalling Expo Go on your simulator and reinstalling by pressing Shift + I in the Expo CLI Terminal UI and selecting the desired simulator.

Reset simulator if low on memory or corrupted

If the Expo CLI is printing error messages and reinstalling Expo Go doesn't help, focus the simulator window and in the Mac toolbar choose Device > Erase All Content and Settings. This reinitializes your simulator from a blank image and can help when your computer is low on memory and the simulator fails to store internal files.

Expo Orbit for simulator management

You can use the Expo Orbit app which allows launching builds and simulator management with one click from the menu bar on macOS.

EAS Build CocoaPods cache server

EAS Build serves most CocoaPods artifacts from a cache server, improving consistency of pod install times. The cache is bypassed automatically if you provide your own .netrc or .curlrc files. To disable the CocoaPods cache server, set the EAS_BUILD_DISABLE_COCOAPODS_CACHE environment variable to "1" in eas.json.

Caching Podfile.lock in eas.json

When using prebuild to generate the ios directory remotely at build time, the Podfile.lock is typically not committed to source control. To cache Podfile.lock for deterministic builds, add ./ios/Podfile.lock to the cache.paths list in your build profile in eas.json. The tradeoff is that without using the lockfile during local development, your ability to determine when changes are needed and update dependencies is limited. If cached, you may occasionally need to clear the cache to fix build errors.

Podfile.lock caching example

Example eas.json configuration to cache Podfile.lock: ```json { "build": { "production": { "cache": { "paths": ["./ios/Podfile.lock"] } } } } ```

iOS build server resource allocation

iOS builder VMs run on Mac mini hosts in an isolated environment. Every build gets its own fresh macOS VM. iOS builds have iOS-specific resource classes that determine the build environment capacity.

iOS global npm configuration

The global npm configuration on iOS build servers in ~/.npmrc is: registry=http://npm.caches.eas-build.internal

iOS global Yarn configuration

The global Yarn configuration on iOS build servers in ~/.yarnrc.yml is: unsafeHttpWhitelist with '*', npmRegistryServer set to 'http://npm.caches.eas-build.internal', and enableImmutableInstalls set to false.

iOS build server image macos-tahoe-26.4-xcode-26.4

The 'macos-tahoe-26.4-xcode-26.4' image is marked as 'sdk-56' alias. It includes macOS Tahoe 26.4.1, Xcode 26.4 (17E202), Node.js 22.22.2, Bun 1.3.13, Yarn 1.22.22, pnpm 10.33.3, npm 10.9.4, fastlane 2.233.1, CocoaPods 1.16.2, Ruby 3.2, node-gyp 12.3.0, and Maestro 2.5.1.

iOS build server image macos-sequoia-15.6-xcode-16.4 for SDK 54

The 'macos-sequoia-15.6-xcode-16.4' image is recommended for SDK 54 if you don't want to use Xcode 26. It includes macOS Sequoia 15.6, Xcode 16.4 (16F6), Node.js 20.19.4, Bun 1.2.20, Yarn 1.22.22, pnpm 10.14.0, npm 10.9.3, fastlane 2.228.0, CocoaPods 1.16.2, Ruby 3.2, node-gyp 11.3.0, Maestro 1.41.0, jq 1.8.0, Azul Zulu JDK 17.58.21 (OpenJDK 17.0.15), Git 2.49.0, Git LFS 3.6.1, applesimutils 0.9.10, and idb-companion 1.1.8.

iOS build server image macos-sequoia-15.4-xcode-16.3

The 'macos-sequoia-15.4-xcode-16.3' image includes macOS Sequoia 15.4.1, Xcode 16.3 (16E140), Node.js 20.19.1, Bun 1.2.11, Yarn 1.22.22, pnpm 9.15.9, npm 9.8.1, fastlane 2.227.1, CocoaPods 1.16.2, Ruby 3.2, node-gyp 11.2.0, jq 1.7.1, Azul Zulu JDK 17.58.21 (OpenJDK 17.0.15), Git 2.49.0, Git LFS 3.6.1, applesimutils 0.9.10, and idb-companion 1.1.8.

iOS build server image macos-sequoia-15.3-xcode-16.2

The 'macos-sequoia-15.3-xcode-16.2' image is marked as 'sdk-52' alias. It includes macOS Sequoia 15.3, Xcode 16.2 (16C5032a), Node.js 20.18.3, Bun 1.2.4, Yarn 1.22.22, pnpm 9.15.5, npm 9.8.1, fastlane 2.226.0, CocoaPods 1.16.2, Ruby 3.2, and node-gyp 11.1.0.

iOS build server image macos-sonoma-14.5-xcode-15.4

The 'macos-sonoma-14.5-xcode-15.4' image is marked as 'sdk-51', 'sdk-50', and 'sdk-49' aliases. It includes macOS Sonoma 14.5, Xcode 15.4 (15F31d), Node.js 18.18.0, Bun 1.1.13, Yarn 1.22.21, pnpm 9.3.0, npm 9.8.1, fastlane 2.220.0, CocoaPods 1.14.3, Ruby 2.7, and node-gyp 10.1.0.

iOS build server image macos-sonoma-14.4-xcode-15.3

The 'macos-sonoma-14.4-xcode-15.3' image includes macOS Sonoma 14.4.1, Xcode 15.3 (15E204a), Node.js 18.18.0, Bun 1.0.35, Yarn 1.22.21, pnpm 8.14.1, npm 9.8.1, fastlane 2.219.0, CocoaPods 1.14.3, Ruby 2.7, and node-gyp 10.0.1.

iOS build server image macos-ventura-13.6-xcode-15.0

The 'macos-ventura-13.6-xcode-15.0' image includes macOS Ventura 13.6, Xcode 15.0 (15A240d), Node.js 18.18.0, Bun 1.0.14, Yarn 1.22.19, pnpm 8.7.6, npm 9.8.1, fastlane 2.216.0, CocoaPods 1.13.0, Ruby 2.7, and node-gyp 10.0.1.

Supported Xcode versions for EAS Build

EAS Build aims to support all stable Xcode releases that allow you to submit your app to the App Store Connect when used during the build process. This usually means supporting the latest stable Xcode version and the previous one, until a new minimal Xcode version requirement is introduced by Apple.

iOS build process overview: local and remote phases

EAS Build for iOS projects has two main phases. Local steps on the developer's machine include checking git index, preparing credentials, validating the Xcode project, creating a tarball, and uploading to Google Cloud Storage. Remote steps on a macOS VM include downloading the tarball, setting up dependencies, restoring credentials into a keychain, running prebuild if needed, caching, building with fastlane gym, and uploading the application archive.

Local step: tarball creation and upload

EAS CLI creates a tarball containing a copy of the repository and uploads it to a private Google Cloud Storage (GCS) bucket, then sends the build request to EAS Build.

Remote step: fresh macOS VM provisioning

Every iOS build gets its own fresh macOS VM with all build tools pre-installed including Xcode, Fastlane, and other utilities.

Remote step: eas-build-pre-install script execution

EAS Build runs the eas-build-pre-install script from package.json if defined, after downloading the project tarball and before running npm install.

Remote step: package installation

EAS Build runs npm install in the project root, or yarn install if yarn.lock exists.

Remote step: expo-doctor diagnostics

EAS Build runs npx expo-doctor to diagnose potential issues with the project configuration.

Remote step: prebuild for CNG projects

For projects using Continuous Native Generation (CNG), EAS Build runs npx expo prebuild to generate android and ios directories using the versioned Expo CLI.

Give your agent this brain