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