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