amis-rpc-design/node_modules/@react-native-community/cli-platform-ios/build/commands/runIOS/index.js
2023-10-07 19:42:30 +08:00

379 lines
16 KiB
JavaScript

"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
function _child_process() {
const data = _interopRequireDefault(require("child_process"));
_child_process = function () {
return data;
};
return data;
}
function _path() {
const data = _interopRequireDefault(require("path"));
_path = function () {
return data;
};
return data;
}
function _fs() {
const data = _interopRequireDefault(require("fs"));
_fs = function () {
return data;
};
return data;
}
function _chalk() {
const data = _interopRequireDefault(require("chalk"));
_chalk = function () {
return data;
};
return data;
}
var _getDestinationSimulator = require("../../tools/getDestinationSimulator");
function _cliTools() {
const data = require("@react-native-community/cli-tools");
_cliTools = function () {
return data;
};
return data;
}
var _buildProject = require("../buildIOS/buildProject");
var _buildIOS = require("../buildIOS");
var _listIOSDevices = _interopRequireDefault(require("../../tools/listIOSDevices"));
var _checkIfConfigurationExists = require("../../tools/checkIfConfigurationExists");
var _getProjectInfo = require("../../tools/getProjectInfo");
var _getConfigurationScheme = require("../../tools/getConfigurationScheme");
var _selectFromInteractiveMode = require("../../tools/selectFromInteractiveMode");
var _prompts = require("../../tools/prompts");
var _getSimulators = _interopRequireDefault(require("../../tools/getSimulators"));
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
*/
async function runIOS(_, ctx, args) {
_cliTools().link.setPlatform('ios');
if (ctx.reactNativeVersion !== 'unknown') {
_cliTools().link.setVersion(ctx.reactNativeVersion);
}
if (!ctx.project.ios) {
throw new (_cliTools().CLIError)('iOS project folder not found. Are you sure this is a React Native project?');
}
const {
xcodeProject,
sourceDir
} = ctx.project.ios;
if (!xcodeProject) {
throw new (_cliTools().CLIError)(`Could not find Xcode project files in "${sourceDir}" folder`);
}
process.chdir(sourceDir);
if (args.binaryPath) {
args.binaryPath = _path().default.isAbsolute(args.binaryPath) ? args.binaryPath : _path().default.join(ctx.root, args.binaryPath);
if (!_fs().default.existsSync(args.binaryPath)) {
throw new (_cliTools().CLIError)('binary-path was specified, but the file was not found.');
}
}
if (args.configuration) {
_cliTools().logger.warn('--configuration has been deprecated. Use --mode instead.');
_cliTools().logger.warn('Parameters were automatically reassigned to --mode on this run.');
args.mode = args.configuration;
}
const projectInfo = (0, _getProjectInfo.getProjectInfo)();
if (args.mode) {
(0, _checkIfConfigurationExists.checkIfConfigurationExists)(projectInfo, args.mode);
}
const inferredSchemeName = _path().default.basename(xcodeProject.name, _path().default.extname(xcodeProject.name));
let scheme = args.scheme || inferredSchemeName;
let mode = args.mode;
if (args.interactive) {
const selection = await (0, _selectFromInteractiveMode.selectFromInteractiveMode)({
scheme,
mode
});
if (selection.scheme) {
scheme = selection.scheme;
}
if (selection.mode) {
mode = selection.mode;
}
}
const modifiedArgs = {
...args,
scheme,
mode
};
modifiedArgs.mode = (0, _getConfigurationScheme.getConfigurationScheme)({
scheme: modifiedArgs.scheme,
mode: modifiedArgs.mode
}, sourceDir);
_cliTools().logger.info(`Found Xcode ${xcodeProject.isWorkspace ? 'workspace' : 'project'} "${_chalk().default.bold(xcodeProject.name)}"`);
const availableDevices = await (0, _listIOSDevices.default)();
if (modifiedArgs.listDevices || modifiedArgs.interactive) {
if (modifiedArgs.device || modifiedArgs.udid) {
_cliTools().logger.warn(`Both ${modifiedArgs.device ? 'device' : 'udid'} and "list-devices" parameters were passed to "run" command. We will list available devices and let you choose from one.`);
}
const selectedDevice = await (0, _prompts.promptForDeviceSelection)(availableDevices);
if (!selectedDevice) {
throw new (_cliTools().CLIError)(`Failed to select device, please try to run app without ${args.listDevices ? 'list-devices' : 'interactive'} command.`);
}
if (selectedDevice.type === 'simulator') {
return runOnSimulator(xcodeProject, scheme, modifiedArgs, selectedDevice);
} else {
return runOnDevice(selectedDevice, scheme, xcodeProject, modifiedArgs);
}
}
if (!modifiedArgs.device && !modifiedArgs.udid && !modifiedArgs.simulator) {
const bootedDevices = availableDevices.filter(({
type,
isAvailable
}) => type === 'device' && isAvailable);
const simulators = (0, _getSimulators.default)();
const bootedSimulators = Object.keys(simulators.devices).map(key => simulators.devices[key]).reduce((acc, val) => acc.concat(val), []).filter(({
state
}) => state === 'Booted');
const booted = [...bootedDevices, ...bootedSimulators];
if (booted.length === 0) {
_cliTools().logger.info('No booted devices or simulators found. Launching first available simulator...');
return runOnSimulator(xcodeProject, scheme, modifiedArgs);
}
_cliTools().logger.info(`Found booted ${booted.map(({
name
}) => name).join(', ')}`);
return runOnBootedDevicesSimulators(scheme, xcodeProject, modifiedArgs, bootedDevices, bootedSimulators);
}
if (modifiedArgs.device && modifiedArgs.udid) {
return _cliTools().logger.error('The `device` and `udid` options are mutually exclusive.');
}
if (modifiedArgs.udid) {
const device = availableDevices.find(d => d.udid === modifiedArgs.udid);
if (!device) {
return _cliTools().logger.error(`Could not find a device with udid: "${_chalk().default.bold(modifiedArgs.udid)}". ${printFoundDevices(availableDevices)}`);
}
if (device.type === 'simulator') {
return runOnSimulator(xcodeProject, scheme, modifiedArgs);
} else {
return runOnDevice(device, scheme, xcodeProject, modifiedArgs);
}
} else if (modifiedArgs.device) {
const physicalDevices = availableDevices.filter(({
type
}) => type !== 'simulator');
const device = matchingDevice(physicalDevices, modifiedArgs.device);
if (device) {
return runOnDevice(device, scheme, xcodeProject, modifiedArgs);
}
} else {
runOnSimulator(xcodeProject, scheme, modifiedArgs);
}
}
async function runOnBootedDevicesSimulators(scheme, xcodeProject, args, devices, simulators) {
for (const device of devices) {
await runOnDevice(device, scheme, xcodeProject, args);
}
for (const simulator of simulators) {
await runOnSimulator(xcodeProject, scheme, args, simulator);
}
}
async function runOnSimulator(xcodeProject, scheme, args, simulator) {
// let selectedSimulator;
/**
* If provided simulator does not exist, try simulators in following order
* - iPhone 14
* - iPhone 13
* - iPhone 12
* - iPhone 11
*/
let selectedSimulator;
if (simulator) {
selectedSimulator = simulator;
} else {
const fallbackSimulators = ['iPhone 14', 'iPhone 13', 'iPhone 12', 'iPhone 11'];
selectedSimulator = (0, _getDestinationSimulator.getDestinationSimulator)(args, fallbackSimulators);
}
if (!selectedSimulator) {
throw new (_cliTools().CLIError)(`No simulator available with ${args.simulator ? `name "${args.simulator}"` : `udid "${args.udid}"`}`);
}
/**
* Booting simulator through `xcrun simctl boot` will boot it in the `headless` mode
* (running in the background).
*
* In order for user to see the app and the simulator itself, we have to make sure
* that the Simulator.app is running.
*
* We also pass it `-CurrentDeviceUDID` so that when we launch it for the first time,
* it will not boot the "default" device, but the one we set. If the app is already running,
* this flag has no effect.
*/
const activeDeveloperDir = _child_process().default.execFileSync('xcode-select', ['-p'], {
encoding: 'utf8'
}).trim();
_child_process().default.execFileSync('open', [`${activeDeveloperDir}/Applications/Simulator.app`, '--args', '-CurrentDeviceUDID', selectedSimulator.udid]);
if (!selectedSimulator.booted) {
bootSimulator(selectedSimulator);
}
let buildOutput, appPath;
if (!args.binaryPath) {
buildOutput = await (0, _buildProject.buildProject)(xcodeProject, selectedSimulator.udid, scheme, args);
appPath = getBuildPath(xcodeProject, args.mode || args.configuration, buildOutput, scheme);
} else {
appPath = args.binaryPath;
}
_cliTools().logger.info(`Installing "${_chalk().default.bold(appPath)} on ${selectedSimulator.name}"`);
_child_process().default.spawnSync('xcrun', ['simctl', 'install', selectedSimulator.udid, appPath], {
stdio: 'inherit'
});
const bundleID = _child_process().default.execFileSync('/usr/libexec/PlistBuddy', ['-c', 'Print:CFBundleIdentifier', _path().default.join(appPath, 'Info.plist')], {
encoding: 'utf8'
}).trim();
_cliTools().logger.info(`Launching "${_chalk().default.bold(bundleID)}"`);
const result = _child_process().default.spawnSync('xcrun', ['simctl', 'launch', selectedSimulator.udid, bundleID]);
if (result.status === 0) {
_cliTools().logger.success('Successfully launched the app on the simulator');
} else {
_cliTools().logger.error('Failed to launch the app on simulator', result.stderr.toString());
}
}
async function runOnDevice(selectedDevice, scheme, xcodeProject, args) {
if (args.binaryPath && selectedDevice.type === 'catalyst') {
throw new (_cliTools().CLIError)('binary-path was specified for catalyst device, which is not supported.');
}
const isIOSDeployInstalled = _child_process().default.spawnSync('ios-deploy', ['--version'], {
encoding: 'utf8'
});
if (isIOSDeployInstalled.error) {
throw new (_cliTools().CLIError)(`Failed to install the app on the device because we couldn't execute the "ios-deploy" command. Please install it by running "${_chalk().default.bold('brew install ios-deploy')}" and try again.`);
}
if (selectedDevice.type === 'catalyst') {
const buildOutput = await (0, _buildProject.buildProject)(xcodeProject, selectedDevice.udid, scheme, args);
const appPath = getBuildPath(xcodeProject, args.mode || args.configuration, buildOutput, scheme, true);
const appProcess = _child_process().default.spawn(`${appPath}/${scheme}`, [], {
detached: true,
stdio: 'ignore'
});
appProcess.unref();
} else {
let buildOutput, appPath;
if (!args.binaryPath) {
buildOutput = await (0, _buildProject.buildProject)(xcodeProject, selectedDevice.udid, scheme, args);
appPath = getBuildPath(xcodeProject, args.mode || args.configuration, buildOutput, scheme);
} else {
appPath = args.binaryPath;
}
const iosDeployInstallArgs = ['--bundle', appPath, '--id', selectedDevice.udid, '--justlaunch'];
_cliTools().logger.info(`Installing and launching your app on ${selectedDevice.name}`);
const iosDeployOutput = _child_process().default.spawnSync('ios-deploy', iosDeployInstallArgs, {
encoding: 'utf8'
});
if (iosDeployOutput.error) {
throw new (_cliTools().CLIError)(`Failed to install the app on the device. We've encountered an error in "ios-deploy" command: ${iosDeployOutput.error.message}`);
}
}
return _cliTools().logger.success('Installed the app on the device.');
}
function bootSimulator(selectedSimulator) {
const simulatorFullName = formattedDeviceName(selectedSimulator);
_cliTools().logger.info(`Launching ${simulatorFullName}`);
_child_process().default.spawnSync('xcrun', ['simctl', 'boot', selectedSimulator.udid]);
}
function getTargetPaths(buildSettings) {
const settings = JSON.parse(buildSettings);
// Find app in all building settings - look for WRAPPER_EXTENSION: 'app',
for (const i in settings) {
const wrapperExtension = settings[i].buildSettings.WRAPPER_EXTENSION;
if (wrapperExtension === 'app') {
return {
targetBuildDir: settings[i].buildSettings.TARGET_BUILD_DIR,
executableFolderPath: settings[i].buildSettings.EXECUTABLE_FOLDER_PATH
};
}
}
return {};
}
function getBuildPath(xcodeProject, mode, buildOutput, scheme, isCatalyst = false) {
const buildSettings = _child_process().default.execFileSync('xcodebuild', [xcodeProject.isWorkspace ? '-workspace' : '-project', xcodeProject.name, '-scheme', scheme, '-sdk', getPlatformName(buildOutput), '-configuration', mode, '-showBuildSettings', '-json'], {
encoding: 'utf8'
});
const {
targetBuildDir,
executableFolderPath
} = getTargetPaths(buildSettings);
if (!targetBuildDir) {
throw new (_cliTools().CLIError)('Failed to get the target build directory.');
}
if (!executableFolderPath) {
throw new (_cliTools().CLIError)('Failed to get the app name.');
}
return `${targetBuildDir}${isCatalyst ? '-maccatalyst' : ''}/${executableFolderPath}`;
}
function getPlatformName(buildOutput) {
// Xcode can sometimes escape `=` with a backslash or put the value in quotes
const platformNameMatch = /export PLATFORM_NAME\\?="?(\w+)"?$/m.exec(buildOutput);
if (!platformNameMatch) {
throw new (_cliTools().CLIError)('Couldn\'t find "PLATFORM_NAME" variable in xcodebuild output. Please report this issue and run your project with Xcode instead.');
}
return platformNameMatch[1];
}
function matchingDevice(devices, deviceName) {
if (deviceName === true) {
const firstIOSDevice = devices.find(d => d.type === 'device');
if (firstIOSDevice) {
_cliTools().logger.info(`Using first available device named "${_chalk().default.bold(firstIOSDevice.name)}" due to lack of name supplied.`);
return firstIOSDevice;
} else {
_cliTools().logger.error('No iOS devices connected.');
return undefined;
}
}
const deviceByName = devices.find(device => device.name === deviceName || formattedDeviceName(device) === deviceName);
if (!deviceByName) {
_cliTools().logger.error(`Could not find a device named: "${_chalk().default.bold(String(deviceName))}". ${printFoundDevices(devices)}`);
}
return deviceByName;
}
function formattedDeviceName(simulator) {
return simulator.version ? `${simulator.name} (${simulator.version})` : simulator.name;
}
function printFoundDevices(devices) {
return ['Available devices:', ...devices.map(device => ` - ${device.name} (${device.udid})`)].join('\n');
}
var _default = {
name: 'run-ios',
description: 'builds your app and starts it on iOS simulator',
func: runIOS,
examples: [{
desc: 'Run on a different simulator, e.g. iPhone SE (2nd generation)',
cmd: 'react-native run-ios --simulator "iPhone SE (2nd generation)"'
}, {
desc: "Run on a connected device, e.g. Max's iPhone",
cmd: 'react-native run-ios --device "Max\'s iPhone"'
}, {
desc: 'Run on the AppleTV simulator',
cmd: 'react-native run-ios --simulator "Apple TV" --scheme "helloworld-tvOS"'
}],
options: [..._buildIOS.iosBuildOptions, {
name: '--no-packager',
description: 'Do not launch packager while building'
}, {
name: '--binary-path <string>',
description: 'Path relative to project root where pre-built .app binary lives.'
}, {
name: '--list-devices',
description: 'List all available iOS devices and simulators and let you choose one to run the app. '
}, {
name: '--interactive',
description: 'Explicitly select which scheme and configuration to use before running a build and select device to run the application.'
}]
};
exports.default = _default;
//# sourceMappingURL=index.ts.map