From ca7cbdee858e84c4a74a2d9c7be151f5cfdcfbfe Mon Sep 17 00:00:00 2001 From: Sandro Machado Date: Thu, 10 Nov 2016 09:54:25 -0800 Subject: [PATCH] Add the scheme configuration option to the run-ios command Summary: With the current `run-ios` script it is not possible to create/run iOS release builds or any other kind of scheme configuration from the terminal (we need to use `Xcode`). The reason for this is that the `run-ios` script does not expose the scheme configuration option for the `xcodebuild` command. This PR exposes that property and allows the developers to directly create/run release builds from the terminal. This PR also closes [this](https://productpains.com/post/react-native/create-ios-release-builds-from-terminal) request at `productpains`. And answers to [this](http://stackoverflow.com/questions/40303229/run-a-react-native-ios-release-build-from-terminal) question at the `stackoverflow`. **Test plan (required)** To generate a release build just run: ``` sh react-native run-ios --configuration Release ``` The output ``` sh Found Xcode project App.xcodeproj Launching iPhone 6 (iOS 9.3)... Building using "xcodebuild -project App.xcodeproj -scheme App -destination id=B0738993-CE4A-4D Closes https://github.com/facebook/react-native/pull/10637 Differential Revision: D4151793 Pulled By: cpojer fbshipit-source-id: 5a0fcdd59589977f3e251ec9bb3ba85e8919cffc --- docs/RunningOnDevice.md | 4 ++++ local-cli/runIOS/runIOS.js | 39 +++++++++++++++++++++----------------- 2 files changed, 26 insertions(+), 17 deletions(-) diff --git a/docs/RunningOnDevice.md b/docs/RunningOnDevice.md index ec68c62b2..c3fda2446 100644 --- a/docs/RunningOnDevice.md +++ b/docs/RunningOnDevice.md @@ -206,6 +206,10 @@ Building an app for distribution in the App Store requires using the `Release` s Apps built for `Release` will automatically disable the in-app Developer menu, which will prevent your users from inadvertently accessing the menu in production. It will also load the JavaScript locally, so you can put the app on a device and test whilst not connected to the computer. +> Hint +> +> You can also use the `React Native CLI` to perform this operation using the option `--configuration` with the value `Release` (e.g. `react-native run-ios --configuration Release`). + Once built for release, you'll be able to distribute the app to beta testers and submit the app to the App Store. ### App Transport Security diff --git a/local-cli/runIOS/runIOS.js b/local-cli/runIOS/runIOS.js index a1fac7952..6ad64b05c 100644 --- a/local-cli/runIOS/runIOS.js +++ b/local-cli/runIOS/runIOS.js @@ -14,6 +14,9 @@ const path = require('path'); const findXcodeProject = require('./findXcodeProject'); const parseIOSDevicesList = require('./parseIOSDevicesList'); const findMatchingSimulator = require('./findMatchingSimulator'); +const getBuildPath = function(configuration = 'Debug', appName, isDevice) { + return `build/Build/Products/${configuration}-${isDevice ? 'iphoneos' : 'iphonesimulator'}/${appName}.app`; +}; function runIOS(argv, config, args) { process.chdir(args.projectPath); @@ -31,7 +34,7 @@ function runIOS(argv, config, args) { if (args.device) { const selectedDevice = matchingDevice(devices, args.device); if (selectedDevice){ - return runOnDevice(selectedDevice, scheme, xcodeProject); + return runOnDevice(selectedDevice, scheme, xcodeProject, args.configuration); } else { if (devices){ console.log('Could not find device with the name: "' + args.device + '".'); @@ -42,19 +45,19 @@ function runIOS(argv, config, args) { } } } else if (args.udid) { - return runOnDeviceByUdid(args.udid, scheme, xcodeProject, devices); + return runOnDeviceByUdid(args, scheme, xcodeProject, devices); } else { return runOnSimulator(xcodeProject, args, inferredSchemeName, scheme); } } -function runOnDeviceByUdid(udid, scheme, xcodeProject, devices) { - const selectedDevice = matchingDeviceByUdid(devices, udid); +function runOnDeviceByUdid(args, scheme, xcodeProject, devices) { + const selectedDevice = matchingDeviceByUdid(devices, args.udid); if (selectedDevice){ - return runOnDevice(selectedDevice, scheme, xcodeProject); + return runOnDevice(selectedDevice, scheme, xcodeProject, args.configuration); } else { if (devices){ - console.log('Could not find device with the udid: "' + udid + '".'); + console.log('Could not find device with the udid: "' + args.udid + '".'); console.log('Choose one of the following:'); printFoundDevices(devices); } else { @@ -88,12 +91,12 @@ function runOnSimulator(xcodeProject, args, inferredSchemeName, scheme){ } resolve(selectedSimulator.udid) }) - .then((udid) => buildProject(xcodeProject, udid, scheme)) + .then((udid) => buildProject(xcodeProject, udid, scheme, args.configuration)) .then((appName) => { if (!appName) { appName = inferredSchemeName; } - const appPath = `build/Build/Products/Debug-iphonesimulator/${appName}.app`; + let appPath = getBuildPath(args.configuration, appName); console.log(`Installing ${appPath}`); child_process.spawnSync('xcrun', ['simctl', 'install', 'booted', appPath], {stdio: 'inherit'}); @@ -108,14 +111,14 @@ function runOnSimulator(xcodeProject, args, inferredSchemeName, scheme){ }) } -function runOnDevice(selectedDevice, scheme, xcodeProject){ - return buildProject(xcodeProject, selectedDevice.udid, scheme) +function runOnDevice(selectedDevice, scheme, xcodeProject, configuration){ + return buildProject(xcodeProject, selectedDevice.udid, scheme, configuration) .then((appName) => { if (!appName) { appName = scheme; } const iosDeployInstallArgs = [ - '--bundle', 'build/Build/Products/Debug-iphoneos/' + appName + '.app', + '--bundle', getBuildPath(configuration, appName, true), '--id' , selectedDevice.udid, '--justlaunch' ]; @@ -132,11 +135,12 @@ function runOnDevice(selectedDevice, scheme, xcodeProject){ }); } -function buildProject(xcodeProject, udid, scheme) { +function buildProject(xcodeProject, udid, scheme, configuration = 'Debug') { return new Promise((resolve,reject) => { - const xcodebuildArgs = [ + var xcodebuildArgs = [ xcodeProject.isWorkspace ? '-workspace' : '-project', xcodeProject.name, + '-configuration', configuration, '-scheme', scheme, '-destination', `id=${udid}`, '-derivedDataPath', 'build', @@ -162,13 +166,12 @@ function buildProject(xcodeProject, udid, scheme) { }); } - function matchingDevice(devices, deviceName) { if (deviceName === true && devices.length === 1) { console.log(`Using first available device ${devices[0].name} due to lack of name supplied.`) return devices[0]; - } + } for (let i = devices.length - 1; i >= 0; i--) { if (devices[i].name === deviceName || formattedDeviceName(devices[i]) === deviceName) { return devices[i]; @@ -176,7 +179,6 @@ function matchingDevice(devices, deviceName) { } } - function matchingDeviceByUdid(devices, udid) { for (let i = devices.length - 1; i >= 0; i--) { if (devices[i].udid === udid) { @@ -217,7 +219,10 @@ module.exports = { command: '--simulator [string]', description: 'Explicitly set simulator to use', default: 'iPhone 6', - }, { + } , { + command: '--configuration [string]', + description: 'Explicitly set the scheme configuration to use', + } , { command: '--scheme [string]', description: 'Explicitly set Xcode scheme to use', }, {