From 6ce8038112ab9229f6c96f2da802d1206147ce05 Mon Sep 17 00:00:00 2001 From: szymonrybczak Date: Thu, 4 May 2023 09:54:57 +0200 Subject: [PATCH] feat: add `--target` option --- packages/cli-platform-ios/README.md | 8 +++ .../src/commands/buildIOS/buildProject.ts | 1 + .../src/commands/buildIOS/index.ts | 11 ++- .../src/commands/runIOS/index.ts | 68 +++++++++++++++---- .../cli-platform-ios/src/tools/prompts.ts | 17 +++++ .../src/tools/selectFromInteractiveMode.ts | 11 +++ 6 files changed, 100 insertions(+), 16 deletions(-) diff --git a/packages/cli-platform-ios/README.md b/packages/cli-platform-ios/README.md index 445a47b4c8..e04321adfb 100644 --- a/packages/cli-platform-ios/README.md +++ b/packages/cli-platform-ios/README.md @@ -61,6 +61,10 @@ react-native run-ios --mode "Release" Explicitly set Xcode scheme to use. +#### `--target ` + +Explicitly set Xcode target to use. + #### `--device [string]` Explicitly set device to use by name. The value is not required if you have a single device connected. @@ -151,6 +155,10 @@ react-native build-ios --mode "Release" Explicitly set Xcode scheme to use. +#### `--target ` + +Explicitly set Xcode target to use. + #### `--device [string]` Explicitly set device to use by name. The value is not required if you have a single device connected. diff --git a/packages/cli-platform-ios/src/commands/buildIOS/buildProject.ts b/packages/cli-platform-ios/src/commands/buildIOS/buildProject.ts index d38ed7aea1..c8d0c7d3c9 100644 --- a/packages/cli-platform-ios/src/commands/buildIOS/buildProject.ts +++ b/packages/cli-platform-ios/src/commands/buildIOS/buildProject.ts @@ -13,6 +13,7 @@ import { export type BuildFlags = { mode: string; + target: string; packager: boolean; verbose: boolean; xcconfig?: string; diff --git a/packages/cli-platform-ios/src/commands/buildIOS/index.ts b/packages/cli-platform-ios/src/commands/buildIOS/index.ts index 8b400d99c6..e1a960d379 100644 --- a/packages/cli-platform-ios/src/commands/buildIOS/index.ts +++ b/packages/cli-platform-ios/src/commands/buildIOS/index.ts @@ -69,9 +69,10 @@ async function buildIOS(_: Array, ctx: Config, args: FlagsT) { let scheme = args.scheme || inferredSchemeName; let mode = args.mode; + let target = args.target; if (args.interactive) { - const selection = await selectFromInteractiveMode({scheme, mode}); + const selection = await selectFromInteractiveMode({scheme, mode, target}); if (selection.scheme) { scheme = selection.scheme; @@ -80,6 +81,10 @@ async function buildIOS(_: Array, ctx: Config, args: FlagsT) { if (selection.mode) { mode = selection.mode; } + + if (selection.target) { + target = selection.target; + } } const modifiedArgs = {...args, scheme, mode}; @@ -261,6 +266,10 @@ export const iosBuildOptions = [ description: 'Custom params that will be passed to xcodebuild command.', parse: (val: string) => val.split(' '), }, + { + name: '--target ', + description: 'Explicitly set Xcode target to use.', + }, ]; export default { diff --git a/packages/cli-platform-ios/src/commands/runIOS/index.ts b/packages/cli-platform-ios/src/commands/runIOS/index.ts index 24e341e2da..02b8319298 100644 --- a/packages/cli-platform-ios/src/commands/runIOS/index.ts +++ b/packages/cli-platform-ios/src/commands/runIOS/index.ts @@ -91,9 +91,10 @@ async function runIOS(_: Array, ctx: Config, args: FlagsT) { let scheme = args.scheme || inferredSchemeName; let mode = args.mode; + let target = args.target; if (args.interactive) { - const selection = await selectFromInteractiveMode({scheme, mode}); + const selection = await selectFromInteractiveMode({scheme, mode, target}); if (selection.scheme) { scheme = selection.scheme; @@ -102,9 +103,13 @@ async function runIOS(_: Array, ctx: Config, args: FlagsT) { if (selection.mode) { mode = selection.mode; } + + if (selection.target) { + target = selection.target; + } } - const modifiedArgs = {...args, scheme, mode}; + const modifiedArgs = {...args, scheme, mode, target}; modifiedArgs.mode = getConfigurationScheme( {scheme: modifiedArgs.scheme, mode: modifiedArgs.mode}, @@ -291,11 +296,12 @@ async function runOnSimulator( args, ); - appPath = getBuildPath( + appPath = await getBuildPath( xcodeProject, args.mode || args.configuration, buildOutput, scheme, + args.target, ); } else { appPath = args.binaryPath; @@ -377,6 +383,7 @@ async function runOnDevice( args.mode || args.configuration, buildOutput, scheme, + args.target, true, ); const appProcess = child_process.spawn(`${appPath}/${scheme}`, [], { @@ -399,6 +406,7 @@ async function runOnDevice( args.mode || args.configuration, buildOutput, scheme, + args.target, ); } else { appPath = args.binaryPath; @@ -437,29 +445,54 @@ function bootSimulator(selectedSimulator: Device) { child_process.spawnSync('xcrun', ['simctl', 'boot', selectedSimulator.udid]); } -function getTargetPaths(buildSettings: string) { +async function getTargetPaths( + buildSettings: string, + scheme: string, + target: string | undefined, +) { 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, - }; + const targets = settings.map(({target}: any) => target); + let selectedTarget; + + if (target) { + if (!targets.includes(target)) { + selectedTarget = targets[0]; + + logger.info( + `Target ${chalk.bold(target)} not found for scheme ${chalk.bold( + scheme, + )}, automatically selected target ${chalk.bold(targets[0])}`, + ); + } else { + selectedTarget = target; } } + // Find app in all building settings - look for WRAPPER_EXTENSION: 'app', + + const targetIndex = targets.indexOf(selectedTarget); + + const wrapperExtension = + settings[targetIndex].buildSettings.WRAPPER_EXTENSION; + + if (wrapperExtension === 'app') { + return { + targetBuildDir: settings[targetIndex].buildSettings.TARGET_BUILD_DIR, + executableFolderPath: + settings[targetIndex].buildSettings.EXECUTABLE_FOLDER_PATH, + }; + } + return {}; } -function getBuildPath( +async function getBuildPath( xcodeProject: IOSProjectInfo, mode: BuildFlags['mode'], buildOutput: string, scheme: string, + target: string, isCatalyst: boolean = false, ) { const buildSettings = child_process.execFileSync( @@ -478,7 +511,12 @@ function getBuildPath( ], {encoding: 'utf8'}, ); - const {targetBuildDir, executableFolderPath} = getTargetPaths(buildSettings); + + const {targetBuildDir, executableFolderPath} = await getTargetPaths( + buildSettings, + scheme, + target, + ); if (!targetBuildDir) { throw new CLIError('Failed to get the target build directory.'); diff --git a/packages/cli-platform-ios/src/tools/prompts.ts b/packages/cli-platform-ios/src/tools/prompts.ts index bc91c043d4..26e7681008 100644 --- a/packages/cli-platform-ios/src/tools/prompts.ts +++ b/packages/cli-platform-ios/src/tools/prompts.ts @@ -34,6 +34,23 @@ export async function promptForConfigurationSelection( return configuration; } +export async function promptForTargetSelection( + targets: string[], + scheme: string, +): Promise { + const {target} = await prompts({ + name: 'target', + type: 'select', + message: `Select the target you want to use for scheme ${scheme}`, + choices: targets.map((value) => ({ + title: value, + value: value, + })), + }); + + return target; +} + export async function promptForDeviceSelection( availableDevices: Device[], ): Promise { diff --git a/packages/cli-platform-ios/src/tools/selectFromInteractiveMode.ts b/packages/cli-platform-ios/src/tools/selectFromInteractiveMode.ts index 03a92aeb46..f5bf03a233 100644 --- a/packages/cli-platform-ios/src/tools/selectFromInteractiveMode.ts +++ b/packages/cli-platform-ios/src/tools/selectFromInteractiveMode.ts @@ -4,19 +4,23 @@ import {getProjectInfo} from './getProjectInfo'; import { promptForConfigurationSelection, promptForSchemeSelection, + promptForTargetSelection, } from './prompts'; interface Args { scheme: string; mode: string; + target: string; } export async function selectFromInteractiveMode({ scheme, mode, + target, }: Args): Promise { let newScheme = scheme; let newMode = mode; + let newTarget = target; const project = getProjectInfo(); @@ -32,8 +36,15 @@ export async function selectFromInteractiveMode({ logger.info(`Automatically selected ${chalk.bold(mode)} configuration.`); } + if (project.targets.length > 2) { + newTarget = await promptForTargetSelection(project.targets, newScheme); + } else { + logger.info(`Automatically selected ${chalk.bold(newTarget)} target.`); + } + return { scheme: newScheme, mode: newMode, + target: newTarget, }; }