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