xref: /expo/packages/@expo/cli/src/run/ios/runIosAsync.ts (revision 20924d47)
1import chalk from 'chalk';
2
3import * as Log from '../../log';
4import { maybePromptToSyncPodsAsync } from '../../utils/cocoapods';
5import { setNodeEnv } from '../../utils/nodeEnv';
6import { profile } from '../../utils/profile';
7import { getSchemesForIosAsync } from '../../utils/scheme';
8import { ensureNativeProjectAsync } from '../ensureNativeProject';
9import { logProjectLogsLocation } from '../hints';
10import { startBundlerAsync } from '../startBundler';
11import * as XcodeBuild from './XcodeBuild';
12import { Options } from './XcodeBuild.types';
13import { launchAppAsync } from './launchApp';
14import { resolveOptionsAsync } from './options/resolveOptions';
15
16export async function runIosAsync(projectRoot: string, options: Options) {
17  setNodeEnv(options.configuration === 'Release' ? 'production' : 'development');
18
19  assertPlatform();
20
21  const install = !!options.install;
22
23  if ((await ensureNativeProjectAsync(projectRoot, { platform: 'ios', install })) && install) {
24    await maybePromptToSyncPodsAsync(projectRoot);
25  }
26
27  // Resolve the CLI arguments into useable options.
28  const props = await resolveOptionsAsync(projectRoot, options);
29
30  // Spawn the `xcodebuild` process to create the app binary.
31  const buildOutput = await XcodeBuild.buildAsync(props);
32
33  // Find the path to the built app binary, this will be used to install the binary
34  // on a device.
35  const binaryPath = await profile(XcodeBuild.getAppBinaryPath)(buildOutput);
36
37  // Start the dev server which creates all of the required info for
38  // launching the app on a simulator.
39  const manager = await startBundlerAsync(projectRoot, {
40    port: props.port,
41    headless: !props.shouldStartBundler,
42    // If a scheme is specified then use that instead of the package name.
43    scheme: (await getSchemesForIosAsync(projectRoot))?.[0],
44  });
45
46  // Install and launch the app binary on a device.
47  await launchAppAsync(binaryPath, manager, {
48    isSimulator: props.isSimulator,
49    device: props.device,
50    shouldStartBundler: props.shouldStartBundler,
51  });
52
53  // Log the location of the JS logs for the device.
54  if (props.shouldStartBundler) {
55    logProjectLogsLocation();
56  }
57}
58
59function assertPlatform() {
60  if (process.platform !== 'darwin') {
61    Log.exit(
62      chalk`iOS apps can only be built on macOS devices. Use {cyan eas build -p ios} to build in the cloud.`
63    );
64  }
65}
66