diff options
Diffstat (limited to 'StoneIsland/platforms/ios/cordova/lib/build.js')
| -rw-r--r--[-rwxr-xr-x] | StoneIsland/platforms/ios/cordova/lib/build.js | 276 |
1 files changed, 153 insertions, 123 deletions
diff --git a/StoneIsland/platforms/ios/cordova/lib/build.js b/StoneIsland/platforms/ios/cordova/lib/build.js index f51b084c..a7203875 100755..100644 --- a/StoneIsland/platforms/ios/cordova/lib/build.js +++ b/StoneIsland/platforms/ios/cordova/lib/build.js @@ -17,38 +17,51 @@ * under the License. */ -var Q = require('q'); -var path = require('path'); -var shell = require('shelljs'); -var spawn = require('./spawn'); -var fs = require('fs'); -var plist = require('plist'); -var util = require('util'); +const path = require('path'); +const which = require('which'); +const { + CordovaError, + events, + superspawn: { spawn } +} = require('cordova-common'); +const fs = require('fs-extra'); +const plist = require('plist'); +const util = require('util'); -var check_reqs = require('./check_reqs'); -var projectFile = require('./projectFile'); - -var events = require('cordova-common').events; - -var projectPath = path.join(__dirname, '..', '..'); -var projectName = null; +const check_reqs = require('./check_reqs'); +const projectFile = require('./projectFile'); // These are regular expressions to detect if the user is changing any of the built-in xcodebuildArgs /* eslint-disable no-useless-escape */ -var buildFlagMatchers = { - 'xcconfig': /^\-xcconfig\s*(.*)$/, - 'workspace': /^\-workspace\s*(.*)/, - 'scheme': /^\-scheme\s*(.*)/, - 'configuration': /^\-configuration\s*(.*)/, - 'sdk': /^\-sdk\s*(.*)/, - 'destination': /^\-destination\s*(.*)/, - 'archivePath': /^\-archivePath\s*(.*)/, - 'configuration_build_dir': /^(CONFIGURATION_BUILD_DIR=.*)/, - 'shared_precomps_dir': /^(SHARED_PRECOMPS_DIR=.*)/ +const buildFlagMatchers = { + workspace: /^\-workspace\s*(.*)/, + scheme: /^\-scheme\s*(.*)/, + configuration: /^\-configuration\s*(.*)/, + sdk: /^\-sdk\s*(.*)/, + destination: /^\-destination\s*(.*)/, + archivePath: /^\-archivePath\s*(.*)/, + configuration_build_dir: /^(CONFIGURATION_BUILD_DIR=.*)/, + shared_precomps_dir: /^(SHARED_PRECOMPS_DIR=.*)/ }; /* eslint-enable no-useless-escape */ /** + * Creates a project object (see projectFile.js/parseProjectFile) from + * a project path and name + * + * @param {*} projectPath + * @param {*} projectName + */ +function createProjectObject (projectPath, projectName) { + const locations = { + root: projectPath, + pbxproj: path.join(projectPath, `${projectName}.xcodeproj`, 'project.pbxproj') + }; + + return projectFile.parse(locations); +} + +/** * Returns a promise that resolves to the default simulator target; the logic here * matches what `cordova emulate ios` does. * @@ -58,13 +71,13 @@ var buildFlagMatchers = { * @return {Promise} */ function getDefaultSimulatorTarget () { - return require('./list-emulator-build-targets').run() - .then(function (emulators) { - var targetEmulator; + return require('./listEmulatorBuildTargets').run() + .then(emulators => { + let targetEmulator; if (emulators.length > 0) { targetEmulator = emulators[0]; } - emulators.forEach(function (emulator) { + emulators.forEach(emulator => { if (emulator.name.indexOf('iPhone') === 0) { targetEmulator = emulator; } @@ -73,120 +86,137 @@ function getDefaultSimulatorTarget () { }); } -module.exports.run = function (buildOpts) { - var emulatorTarget = ''; +module.exports.run = buildOpts => { + let emulatorTarget = ''; + const projectPath = path.join(__dirname, '..', '..'); + let projectName = ''; buildOpts = buildOpts || {}; if (buildOpts.debug && buildOpts.release) { - return Q.reject('Cannot specify "debug" and "release" options together.'); + return Promise.reject(new CordovaError('Cannot specify "debug" and "release" options together.')); } if (buildOpts.device && buildOpts.emulator) { - return Q.reject('Cannot specify "device" and "emulator" options together.'); + return Promise.reject(new CordovaError('Cannot specify "device" and "emulator" options together.')); } if (buildOpts.buildConfig) { if (!fs.existsSync(buildOpts.buildConfig)) { - return Q.reject('Build config file does not exist:' + buildOpts.buildConfig); + return Promise.reject(new CordovaError(`Build config file does not exist: ${buildOpts.buildConfig}`)); } - events.emit('log', 'Reading build config file:', path.resolve(buildOpts.buildConfig)); - var contents = fs.readFileSync(buildOpts.buildConfig, 'utf-8'); - var buildConfig = JSON.parse(contents.replace(/^\ufeff/, '')); // Remove BOM + events.emit('log', `Reading build config file: ${path.resolve(buildOpts.buildConfig)}`); + const contents = fs.readFileSync(buildOpts.buildConfig, 'utf-8'); + const buildConfig = JSON.parse(contents.replace(/^\ufeff/, '')); // Remove BOM if (buildConfig.ios) { - var buildType = buildOpts.release ? 'release' : 'debug'; - var config = buildConfig.ios[buildType]; + const buildType = buildOpts.release ? 'release' : 'debug'; + const config = buildConfig.ios[buildType]; if (config) { - ['codeSignIdentity', 'codeSignResourceRules', 'provisioningProfile', 'developmentTeam', 'packageType', 'buildFlag', 'iCloudContainerEnvironment'].forEach( - function (key) { + ['codeSignIdentity', 'codeSignResourceRules', 'provisioningProfile', 'developmentTeam', 'packageType', 'buildFlag', 'iCloudContainerEnvironment', 'automaticProvisioning'].forEach( + key => { buildOpts[key] = buildOpts[key] || config[key]; }); } } } - return require('./list-devices').run() - .then(function (devices) { + return require('./listDevices').run() + .then(devices => { if (devices.length > 0 && !(buildOpts.emulator)) { // we also explicitly set device flag in options as we pass // those parameters to other api (build as an example) buildOpts.device = true; return check_reqs.check_ios_deploy(); } - }).then(function () { + }).then(() => { // CB-12287: Determine the device we should target when building for a simulator if (!buildOpts.device) { - var newTarget = buildOpts.target || ''; + let newTarget = buildOpts.target || ''; if (newTarget) { // only grab the device name, not the runtime specifier newTarget = newTarget.split(',')[0]; } // a target was given to us, find the matching Xcode destination name - var promise = require('./list-emulator-build-targets').targetForSimIdentifier(newTarget); - return promise.then(function (theTarget) { + const promise = require('./listEmulatorBuildTargets').targetForSimIdentifier(newTarget); + return promise.then(theTarget => { if (!theTarget) { - return getDefaultSimulatorTarget().then(function (defaultTarget) { + return getDefaultSimulatorTarget().then(defaultTarget => { emulatorTarget = defaultTarget.name; - events.emit('log', 'Building for ' + emulatorTarget + ' Simulator'); + events.emit('warn', `No simulator found for "${newTarget}. Falling back to the default target.`); + events.emit('log', `Building for "${emulatorTarget}" Simulator (${defaultTarget.identifier}, ${defaultTarget.simIdentifier}).`); return emulatorTarget; }); } else { emulatorTarget = theTarget.name; - events.emit('log', 'Building for ' + emulatorTarget + ' Simulator'); + events.emit('log', `Building for "${emulatorTarget}" Simulator (${theTarget.identifier}, ${theTarget.simIdentifier}).`); return emulatorTarget; } }); } - }).then(function () { - return check_reqs.run(); - }).then(function () { - return findXCodeProjectIn(projectPath); - }).then(function (name) { + }) + .then(() => check_reqs.run()) + .then(() => findXCodeProjectIn(projectPath)) + .then(name => { projectName = name; - var extraConfig = ''; + let extraConfig = ''; if (buildOpts.codeSignIdentity) { - extraConfig += 'CODE_SIGN_IDENTITY = ' + buildOpts.codeSignIdentity + '\n'; - extraConfig += 'CODE_SIGN_IDENTITY[sdk=iphoneos*] = ' + buildOpts.codeSignIdentity + '\n'; + extraConfig += `CODE_SIGN_IDENTITY = ${buildOpts.codeSignIdentity}\n`; + extraConfig += `CODE_SIGN_IDENTITY[sdk=iphoneos*] = ${buildOpts.codeSignIdentity}\n`; } if (buildOpts.codeSignResourceRules) { - extraConfig += 'CODE_SIGN_RESOURCE_RULES_PATH = ' + buildOpts.codeSignResourceRules + '\n'; + extraConfig += `CODE_SIGN_RESOURCE_RULES_PATH = ${buildOpts.codeSignResourceRules}\n`; } if (buildOpts.provisioningProfile) { - extraConfig += 'PROVISIONING_PROFILE = ' + buildOpts.provisioningProfile + '\n'; + extraConfig += `PROVISIONING_PROFILE = ${buildOpts.provisioningProfile}\n`; } if (buildOpts.developmentTeam) { - extraConfig += 'DEVELOPMENT_TEAM = ' + buildOpts.developmentTeam + '\n'; + extraConfig += `DEVELOPMENT_TEAM = ${buildOpts.developmentTeam}\n`; } - return Q.nfcall(fs.writeFile, path.join(__dirname, '..', 'build-extras.xcconfig'), extraConfig, 'utf-8'); - }).then(function () { - var configuration = buildOpts.release ? 'Release' : 'Debug'; - events.emit('log', 'Building project: ' + path.join(projectPath, projectName + '.xcworkspace')); - events.emit('log', '\tConfiguration: ' + configuration); - events.emit('log', '\tPlatform: ' + (buildOpts.device ? 'device' : 'emulator')); + function writeCodeSignStyle (value) { + const project = createProjectObject(projectPath, projectName); - var buildOutputDir = path.join(projectPath, 'build', (buildOpts.device ? 'device' : 'emulator')); + events.emit('verbose', `Set CODE_SIGN_STYLE Build Property to ${value}.`); + project.xcode.updateBuildProperty('CODE_SIGN_STYLE', value); + events.emit('verbose', `Set ProvisioningStyle Target Attribute to ${value}.`); + project.xcode.addTargetAttribute('ProvisioningStyle', value); + + project.write(); + } + + if (buildOpts.provisioningProfile) { + events.emit('verbose', 'ProvisioningProfile build option set, changing project settings to Manual.'); + writeCodeSignStyle('Manual'); + } else if (buildOpts.automaticProvisioning) { + events.emit('verbose', 'ProvisioningProfile build option NOT set, changing project settings to Automatic.'); + writeCodeSignStyle('Automatic'); + } + + return fs.writeFile(path.join(__dirname, '..', 'build-extras.xcconfig'), extraConfig, 'utf-8'); + }).then(() => { + const configuration = buildOpts.release ? 'Release' : 'Debug'; + + events.emit('log', `Building project: ${path.join(projectPath, `${projectName}.xcworkspace`)}`); + events.emit('log', `\tConfiguration: ${configuration}`); + events.emit('log', `\tPlatform: ${buildOpts.device ? 'device' : 'emulator'}`); + events.emit('log', `\tTarget: ${emulatorTarget}`); + + const buildOutputDir = path.join(projectPath, 'build', (buildOpts.device ? 'device' : 'emulator')); // remove the build/device folder before building - return spawn('rm', [ '-rf', buildOutputDir ], projectPath) - .then(function () { - var xcodebuildArgs = getXcodeBuildArgs(projectName, projectPath, configuration, buildOpts.device, buildOpts.buildFlag, emulatorTarget); - return spawn('xcodebuild', xcodebuildArgs, projectPath); - }); + fs.removeSync(buildOutputDir); - }).then(function () { + const xcodebuildArgs = getXcodeBuildArgs(projectName, projectPath, configuration, buildOpts.device, buildOpts.buildFlag, emulatorTarget, buildOpts.automaticProvisioning); + return spawn('xcodebuild', xcodebuildArgs, { cwd: projectPath, printCommand: true, stdio: 'inherit' }); + }).then(() => { if (!buildOpts.device || buildOpts.noSign) { return; } - var locations = { - root: projectPath, - pbxproj: path.join(projectPath, projectName + '.xcodeproj', 'project.pbxproj') - }; - - var bundleIdentifier = projectFile.parse(locations).getPackageName(); - var exportOptions = {'compileBitcode': false, 'method': 'development'}; + const project = createProjectObject(projectPath, projectName); + const bundleIdentifier = project.getPackageName(); + const exportOptions = { compileBitcode: false, method: 'development' }; if (buildOpts.packageType) { exportOptions.method = buildOpts.packageType; @@ -201,7 +231,7 @@ module.exports.run = function (buildOpts) { } if (buildOpts.provisioningProfile && bundleIdentifier) { - exportOptions.provisioningProfiles = { [ bundleIdentifier ]: String(buildOpts.provisioningProfile) }; + exportOptions.provisioningProfiles = { [bundleIdentifier]: String(buildOpts.provisioningProfile) }; exportOptions.signingStyle = 'manual'; } @@ -209,13 +239,13 @@ module.exports.run = function (buildOpts) { exportOptions.signingCertificate = buildOpts.codeSignIdentity; } - var exportOptionsPlist = plist.build(exportOptions); - var exportOptionsPath = path.join(projectPath, 'exportOptions.plist'); + const exportOptionsPlist = plist.build(exportOptions); + const exportOptionsPath = path.join(projectPath, 'exportOptions.plist'); - var buildOutputDir = path.join(projectPath, 'build', 'device'); + const buildOutputDir = path.join(projectPath, 'build', 'device'); function checkSystemRuby () { - var ruby_cmd = shell.which('ruby'); + const ruby_cmd = which.sync('ruby', { nothrow: true }); if (ruby_cmd !== '/usr/bin/ruby') { events.emit('warn', 'Non-system Ruby in use. This may cause packaging to fail.\n' + @@ -225,11 +255,11 @@ module.exports.run = function (buildOpts) { } function packageArchive () { - var xcodearchiveArgs = getXcodeArchiveArgs(projectName, projectPath, buildOutputDir, exportOptionsPath); - return spawn('xcodebuild', xcodearchiveArgs, projectPath); + const xcodearchiveArgs = getXcodeArchiveArgs(projectName, projectPath, buildOutputDir, exportOptionsPath, buildOpts.automaticProvisioning); + return spawn('xcodebuild', xcodearchiveArgs, { cwd: projectPath, printCommand: true, stdio: 'inherit' }); } - return Q.nfcall(fs.writeFile, exportOptionsPath, exportOptionsPlist, 'utf-8') + return fs.writeFile(exportOptionsPath, exportOptionsPlist, 'utf-8') .then(checkSystemRuby) .then(packageArchive); }); @@ -242,20 +272,17 @@ module.exports.run = function (buildOpts) { */ function findXCodeProjectIn (projectPath) { // 'Searching for Xcode project in ' + projectPath); - var xcodeProjFiles = shell.ls(projectPath).filter(function (name) { - return path.extname(name) === '.xcodeproj'; - }); + const xcodeProjFiles = fs.readdirSync(projectPath).filter(name => path.extname(name) === '.xcodeproj'); if (xcodeProjFiles.length === 0) { - return Q.reject('No Xcode project found in ' + projectPath); + return Promise.reject(new CordovaError(`No Xcode project found in ${projectPath}`)); } if (xcodeProjFiles.length > 1) { - events.emit('warn', 'Found multiple .xcodeproj directories in \n' + - projectPath + '\nUsing first one'); + events.emit('warn', `Found multiple .xcodeproj directories in \n${projectPath}\nUsing first one`); } - var projectName = path.basename(xcodeProjFiles[0], '.xcodeproj'); - return Q.resolve(projectName); + const projectName = path.basename(xcodeProjFiles[0], '.xcodeproj'); + return Promise.resolve(projectName); } module.exports.findXCodeProjectIn = findXCodeProjectIn; @@ -268,21 +295,21 @@ module.exports.findXCodeProjectIn = findXCodeProjectIn; * @param {Boolean} isDevice Flag that specify target for package (device/emulator) * @param {Array} buildFlags * @param {String} emulatorTarget Target for emulator (rather than default) + * @param {Boolean} autoProvisioning Whether to allow Xcode to automatically update provisioning * @return {Array} Array of arguments that could be passed directly to spawn method */ -function getXcodeBuildArgs (projectName, projectPath, configuration, isDevice, buildFlags, emulatorTarget) { - var xcodebuildArgs; - var options; - var buildActions; - var settings; - var customArgs = {}; +function getXcodeBuildArgs (projectName, projectPath, configuration, isDevice, buildFlags, emulatorTarget, autoProvisioning) { + let options; + let buildActions; + let settings; + const customArgs = {}; customArgs.otherFlags = []; if (buildFlags) { if (typeof buildFlags === 'string' || buildFlags instanceof String) { parseBuildFlag(buildFlags, customArgs); } else { // buildFlags is an Array of strings - buildFlags.forEach(function (flag) { + buildFlags.forEach(flag => { parseBuildFlag(flag, customArgs); }); } @@ -290,36 +317,38 @@ function getXcodeBuildArgs (projectName, projectPath, configuration, isDevice, b if (isDevice) { options = [ - '-xcconfig', customArgs.xcconfig || path.join(__dirname, '..', 'build-' + configuration.toLowerCase() + '.xcconfig'), - '-workspace', customArgs.workspace || projectName + '.xcworkspace', + '-workspace', customArgs.workspace || `${projectName}.xcworkspace`, '-scheme', customArgs.scheme || projectName, '-configuration', customArgs.configuration || configuration, '-destination', customArgs.destination || 'generic/platform=iOS', - '-archivePath', customArgs.archivePath || projectName + '.xcarchive' + '-archivePath', customArgs.archivePath || `${projectName}.xcarchive` ]; - buildActions = [ 'archive' ]; + buildActions = ['archive']; settings = [ - customArgs.configuration_build_dir || 'CONFIGURATION_BUILD_DIR=' + path.join(projectPath, 'build', 'device'), - customArgs.shared_precomps_dir || 'SHARED_PRECOMPS_DIR=' + path.join(projectPath, 'build', 'sharedpch') + customArgs.configuration_build_dir || `CONFIGURATION_BUILD_DIR=${path.join(projectPath, 'build', 'device')}`, + customArgs.shared_precomps_dir || `SHARED_PRECOMPS_DIR=${path.join(projectPath, 'build', 'sharedpch')}` ]; // Add other matched flags to otherFlags to let xcodebuild present an appropriate error. // This is preferable to just ignoring the flags that the user has passed in. if (customArgs.sdk) { customArgs.otherFlags = customArgs.otherFlags.concat(['-sdk', customArgs.sdk]); } + + if (autoProvisioning) { + options = options.concat(['-allowProvisioningUpdates']); + } } else { // emulator options = [ - '-xcconfig', customArgs.xcconfig || path.join(__dirname, '..', 'build-' + configuration.toLowerCase() + '.xcconfig'), - '-workspace', customArgs.project || projectName + '.xcworkspace', + '-workspace', customArgs.project || `${projectName}.xcworkspace`, '-scheme', customArgs.scheme || projectName, '-configuration', customArgs.configuration || configuration, '-sdk', customArgs.sdk || 'iphonesimulator', - '-destination', customArgs.destination || 'platform=iOS Simulator,name=' + emulatorTarget + '-destination', customArgs.destination || `platform=iOS Simulator,name=${emulatorTarget}` ]; - buildActions = [ 'build' ]; + buildActions = ['build']; settings = [ - customArgs.configuration_build_dir || 'CONFIGURATION_BUILD_DIR=' + path.join(projectPath, 'build', 'emulator'), - customArgs.shared_precomps_dir || 'SHARED_PRECOMPS_DIR=' + path.join(projectPath, 'build', 'sharedpch') + customArgs.configuration_build_dir || `CONFIGURATION_BUILD_DIR=${path.join(projectPath, 'build', 'emulator')}`, + customArgs.shared_precomps_dir || `SHARED_PRECOMPS_DIR=${path.join(projectPath, 'build', 'sharedpch')}` ]; // Add other matched flags to otherFlags to let xcodebuild present an appropriate error. // This is preferable to just ignoring the flags that the user has passed in. @@ -327,8 +356,8 @@ function getXcodeBuildArgs (projectName, projectPath, configuration, isDevice, b customArgs.otherFlags = customArgs.otherFlags.concat(['-archivePath', customArgs.archivePath]); } } - xcodebuildArgs = options.concat(buildActions).concat(settings).concat(customArgs.otherFlags); - return xcodebuildArgs; + + return options.concat(buildActions).concat(settings).concat(customArgs.otherFlags); } /** @@ -337,21 +366,22 @@ function getXcodeBuildArgs (projectName, projectPath, configuration, isDevice, b * @param {String} projectPath Path to project file. Will be used to set CWD for xcodebuild * @param {String} outputPath Output directory to contain the IPA * @param {String} exportOptionsPath Path to the exportOptions.plist file + * @param {Boolean} autoProvisioning Whether to allow Xcode to automatically update provisioning * @return {Array} Array of arguments that could be passed directly to spawn method */ -function getXcodeArchiveArgs (projectName, projectPath, outputPath, exportOptionsPath) { +function getXcodeArchiveArgs (projectName, projectPath, outputPath, exportOptionsPath, autoProvisioning) { return [ '-exportArchive', - '-archivePath', projectName + '.xcarchive', + '-archivePath', `${projectName}.xcarchive`, '-exportOptionsPlist', exportOptionsPath, '-exportPath', outputPath - ]; + ].concat(autoProvisioning ? ['-allowProvisioningUpdates'] : []); } function parseBuildFlag (buildFlag, args) { - var matched; - for (var key in buildFlagMatchers) { - var found = buildFlag.match(buildFlagMatchers[key]); + let matched; + for (const key in buildFlagMatchers) { + const found = buildFlag.match(buildFlagMatchers[key]); if (found) { matched = true; // found[0] is the whole match, found[1] is the first match in parentheses. |
