diff options
| author | Jules Laplace <julescarbon@gmail.com> | 2017-09-26 01:35:13 +0200 |
|---|---|---|
| committer | Jules Laplace <julescarbon@gmail.com> | 2017-09-26 01:35:13 +0200 |
| commit | 597fa051833ca3df6eb185c0143ff82e02dacba1 (patch) | |
| tree | cb25347477c57f82e955b054b70f4bb5359fb0d2 /StoneIsland/platforms/ios/cordova/lib | |
| parent | 6a9186aea6b85beef28e3eb765fbf2322a1c7890 (diff) | |
push plugin ugh
Diffstat (limited to 'StoneIsland/platforms/ios/cordova/lib')
6 files changed, 315 insertions, 57 deletions
diff --git a/StoneIsland/platforms/ios/cordova/lib/Podfile.js b/StoneIsland/platforms/ios/cordova/lib/Podfile.js index 2cf254cc..084c10c3 100755 --- a/StoneIsland/platforms/ios/cordova/lib/Podfile.js +++ b/StoneIsland/platforms/ios/cordova/lib/Podfile.js @@ -66,7 +66,7 @@ Podfile.prototype.__parseForPods = function(text) { // pod 'Foobar', '1.2' // pod 'Foobar', 'abc 123 1.2' // pod 'PonyDebugger', :configurations => ['Debug', 'Beta'] - var podRE = new RegExp('pod \'(\\w+)\'\\s*,?\\s*(.*)'); + var podRE = new RegExp('pod \'([^\']*)\'\\s*,?\\s*(.*)'); // only grab lines that don't have the pod spec' return arr.filter(function(line) { diff --git a/StoneIsland/platforms/ios/cordova/lib/build.js b/StoneIsland/platforms/ios/cordova/lib/build.js index c40bfe8b..29d808ab 100755 --- a/StoneIsland/platforms/ios/cordova/lib/build.js +++ b/StoneIsland/platforms/ios/cordova/lib/build.js @@ -53,7 +53,33 @@ var buildFlagMatchers = { 'shared_precomps_dir' : /^(SHARED_PRECOMPS_DIR=.*)/ }; +/** + * Returns a promise that resolves to the default simulator target; the logic here + * matches what `cordova emulate ios` does. + * + * The return object has two properties: `name` (the Xcode destination name), + * `identifier` (the simctl identifier), and `simIdentifier` (essentially the cordova emulate target) + * + * @return {Promise} + */ +function getDefaultSimulatorTarget() { + return require('./list-emulator-build-targets').run() + .then(function (emulators) { + var targetEmulator; + if (emulators.length > 0) { + targetEmulator = emulators[0]; + } + emulators.forEach(function (emulator) { + if (emulator.name.indexOf('iPhone') === 0) { + targetEmulator = emulator; + } + }); + return targetEmulator; + }); +} + module.exports.run = function (buildOpts) { + var emulatorTarget = ''; buildOpts = buildOpts || {}; @@ -93,6 +119,22 @@ return require('./list-devices').run() return check_reqs.check_ios_deploy(); } }).then(function () { + // CB-12287: Determine the device we should target when building for a simulator + if (!buildOpts.device) { + var promise; + if (buildOpts.target) { + // a target was given to us, find the matching Xcode destination name + promise = require('./list-emulator-build-targets').targetForSimIdentifier(buildOpts.target); + } else { + // no target provided, pick a default one (matching our emulator logic) + promise = getDefaultSimulatorTarget(); + } + return promise.then(function(theTarget) { + emulatorTarget = theTarget.name; + events.emit('log', 'Building for ' + emulatorTarget + ' Simulator'); + }); + } + }).then(function () { return check_reqs.run(); }).then(function () { return findXCodeProjectIn(projectPath); @@ -120,12 +162,12 @@ return require('./list-devices').run() events.emit('log','\tConfiguration: ' + configuration); events.emit('log','\tPlatform: ' + (buildOpts.device ? 'device' : 'emulator')); - var buildOutputDir = path.join(projectPath, 'build', 'device'); + var 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); + var xcodebuildArgs = getXcodeBuildArgs(projectName, projectPath, configuration, buildOpts.device, buildOpts.buildFlag, emulatorTarget); return spawn('xcodebuild', xcodebuildArgs, projectPath); }); @@ -165,35 +207,9 @@ return require('./list-devices').run() return spawn('xcodebuild', xcodearchiveArgs, projectPath); } - function unpackIPA() { - var ipafile = path.join(buildOutputDir, projectName + '.ipa'); - - // unpack the existing platform/ios/build/device/appname.ipa (zipfile), will create a Payload folder - return spawn('unzip', [ '-o', '-qq', ipafile ], buildOutputDir); - } - - function moveApp() { - var appFileInflated = path.join(buildOutputDir, 'Payload', projectName + '.app'); - var appFile = path.join(buildOutputDir, projectName + '.app'); - var payloadFolder = path.join(buildOutputDir, 'Payload'); - - // delete the existing platform/ios/build/device/appname.app - return spawn('rm', [ '-rf', appFile ], buildOutputDir) - .then(function() { - // move the platform/ios/build/device/Payload/appname.app to parent - return spawn('mv', [ '-f', appFileInflated, buildOutputDir ], buildOutputDir); - }) - .then(function() { - // delete the platform/ios/build/device/Payload folder - return spawn('rm', [ '-rf', payloadFolder ], buildOutputDir); - }); - } - return Q.nfcall(fs.writeFile, exportOptionsPath, exportOptionsPlist, 'utf-8') .then(checkSystemRuby) - .then(packageArchive) - .then(unpackIPA) - .then(moveApp); + .then(packageArchive); }); }; @@ -224,13 +240,15 @@ module.exports.findXCodeProjectIn = findXCodeProjectIn; /** * Returns array of arguments for xcodebuild - * @param {String} projectName Name of xcode project - * @param {String} projectPath Path to project file. Will be used to set CWD for xcodebuild - * @param {String} configuration Configuration name: debug|release - * @param {Boolean} isDevice Flag that specify target for package (device/emulator) - * @return {Array} Array of arguments that could be passed directly to spawn method + * @param {String} projectName Name of xcode project + * @param {String} projectPath Path to project file. Will be used to set CWD for xcodebuild + * @param {String} configuration Configuration name: debug|release + * @param {Boolean} isDevice Flag that specify target for package (device/emulator) + * @param {Array} buildFlags + * @param {String} emulatorTarget Target for emulator (rather than default) + * @return {Array} Array of arguments that could be passed directly to spawn method */ -function getXcodeBuildArgs(projectName, projectPath, configuration, isDevice, buildFlags) { +function getXcodeBuildArgs(projectName, projectPath, configuration, isDevice, buildFlags, emulatorTarget) { var xcodebuildArgs; var options; var buildActions; @@ -274,7 +292,7 @@ function getXcodeBuildArgs(projectName, projectPath, configuration, isDevice, bu '-scheme', customArgs.scheme || projectName, '-configuration', customArgs.configuration || configuration, '-sdk', customArgs.sdk || 'iphonesimulator', - '-destination', customArgs.destination || 'platform=iOS Simulator,name=iPhone 5s' + '-destination', customArgs.destination || 'platform=iOS Simulator,name=' + emulatorTarget ]; buildActions = [ 'build' ]; settings = [ @@ -341,6 +359,7 @@ module.exports.help = function help() { console.log('Usage: build [--debug | --release] [--archs=\"<list of architectures...>\"]'); console.log(' [--device | --simulator] [--codeSignIdentity=\"<identity>\"]'); console.log(' [--codeSignResourceRules=\"<resourcerules path>\"]'); + console.log(' [--developmentTeam=\"<Team ID>\"]'); console.log(' [--provisioningProfile=\"<provisioning profile>\"]'); console.log(' --help : Displays this dialog.'); console.log(' --debug : Builds project in debug mode. (Default)'); @@ -352,6 +371,8 @@ module.exports.help = function help() { console.log(' : Specifies, what type of project to build'); console.log(' --codeSignIdentity : Type of signing identity used for code signing.'); console.log(' --codeSignResourceRules : Path to ResourceRules.plist.'); + console.log(' --developmentTeam : New for Xcode 8. The development team (Team ID)'); + console.log(' to use for code signing.'); console.log(' --provisioningProfile : UUID of the profile.'); console.log(' --device --noSign : Builds project without application signing.'); console.log(''); diff --git a/StoneIsland/platforms/ios/cordova/lib/list-emulator-build-targets b/StoneIsland/platforms/ios/cordova/lib/list-emulator-build-targets new file mode 100755 index 00000000..d17fc8ca --- /dev/null +++ b/StoneIsland/platforms/ios/cordova/lib/list-emulator-build-targets @@ -0,0 +1,108 @@ +#!/usr/bin/env node + +/* + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. +*/ + +/*jshint node: true*/ + +var Q = require('q'), + exec = require('child_process').exec; + +/** + * Returns a list of available simulator build targets of the form + * + * [ + * { name: <xcode-destination-name>, + * identifier: <simctl-identifier>, + * simIdentifier: <cordova emulate target> + * } + * ] + * + */ +function listEmulatorBuildTargets () { + return Q.nfcall(exec, 'xcrun simctl list --json') + .then(function(stdio) { + return JSON.parse(stdio[0]); + }) + .then(function(simInfo) { + var devices = simInfo.devices; + var deviceTypes = simInfo.devicetypes; + return deviceTypes.reduce(function (typeAcc, deviceType) { + if (!deviceType.name.match(/^[iPad|iPhone]/)) { + // ignore targets we don't support (like Apple Watch or Apple TV) + return typeAcc; + } + var availableDevices = Object.keys(devices).reduce(function (availAcc, deviceCategory) { + var availableDevicesInCategory = devices[deviceCategory]; + availableDevicesInCategory.forEach(function (device) { + if (device.name === deviceType.name.replace(/\-inch/g, ' inch') && + device.availability.toLowerCase().indexOf('unavailable') < 0) { + availAcc.push(device); + } + }); + return availAcc; + }, []); + // we only want device types that have at least one available device + // (regardless of OS); this filters things out like iPhone 4s, which + // is present in deviceTypes, but probably not available on the user's + // system. + if (availableDevices.length > 0) { + typeAcc.push(deviceType); + } + return typeAcc; + }, []); + }) + .then(function(filteredTargets) { + // the simIdentifier, or cordova emulate target name, is the very last part + // of identifier. + return filteredTargets.map(function (target) { + var identifierPieces = target.identifier.split("."); + target.simIdentifier = identifierPieces[identifierPieces.length-1]; + return target; + }); + }); +} + +exports.run = listEmulatorBuildTargets; + +/** + * Given a simIdentifier, return the matching target. + * + * @param {string} simIdentifier a target, like "iPhone-SE" + * @return {Object} the matching target, or undefined if no match + */ +exports.targetForSimIdentifier = function(simIdentifier) { + return listEmulatorBuildTargets() + .then(function(targets) { + return targets.reduce(function(acc, target) { + if (!acc && target.simIdentifier.toLowerCase() === simIdentifier.toLowerCase()) { + acc = target; + } + return acc; + }, undefined); + }); +} + +// Check if module is started as separate script. +// If so, then invoke main method and print out results. +if (!module.parent) { + listEmulatorBuildTargets().then(function (targets) { + console.log(JSON.stringify(targets, null, 2)); + }); +} diff --git a/StoneIsland/platforms/ios/cordova/lib/plugman/pluginHandlers.js b/StoneIsland/platforms/ios/cordova/lib/plugman/pluginHandlers.js index 297e3863..416aba96 100755 --- a/StoneIsland/platforms/ios/cordova/lib/plugman/pluginHandlers.js +++ b/StoneIsland/platforms/ios/cordova/lib/plugman/pluginHandlers.js @@ -14,10 +14,11 @@ specific language governing permissions and limitations under the License. */ - +'use strict'; var fs = require('fs'); var path = require('path'); var shell = require('shelljs'); +var util = require('util'); var events = require('cordova-common').events; var CordovaError = require('cordova-common').CordovaError; @@ -48,25 +49,44 @@ var handlers = { 'resource-file':{ install:function(obj, plugin, project, options) { var src = obj.src, - srcFile = path.resolve(plugin.dir, src), - destFile = path.resolve(project.resources_dir, path.basename(src)); - if (!fs.existsSync(srcFile)) throw new CordovaError('Cannot find resource file "' + srcFile + '" for plugin ' + plugin.id + ' in iOS platform'); - if (fs.existsSync(destFile)) throw new CordovaError('File already exists at detination "' + destFile + '" for resource file specified by plugin ' + plugin.id + ' in iOS platform'); - project.xcode.addResourceFile(path.join('Resources', path.basename(src))); + target = obj.target, + srcFile = path.resolve(plugin.dir, src); + + if (!target) { + target = path.basename(src); + } + var destFile = path.resolve(project.resources_dir, target); + + if (!fs.existsSync(srcFile)) { + throw new CordovaError('Cannot find resource file "' + srcFile + '" for plugin ' + plugin.id + ' in iOS platform'); + } + if (fs.existsSync(destFile)) { + throw new CordovaError('File already exists at destination "' + destFile + '" for resource file specified by plugin ' + plugin.id + ' in iOS platform'); + } + project.xcode.addResourceFile(path.join('Resources', target)); var link = !!(options && options.link); copyFile(plugin.dir, src, project.projectDir, destFile, link); }, uninstall:function(obj, plugin, project, options) { var src = obj.src, - destFile = path.resolve(project.resources_dir, path.basename(src)); - project.xcode.removeResourceFile(path.join('Resources', path.basename(src))); + target = obj.target; + + if (!target) { + target = path.basename(src); + } + var destFile = path.resolve(project.resources_dir, target); + + project.xcode.removeResourceFile(path.join('Resources', target)); shell.rm('-rf', destFile); } }, 'framework':{ // CB-5238 custom frameworks only install:function(obj, plugin, project, options) { var src = obj.src, - custom = obj.custom; + custom = !!(obj.custom), // convert to boolean (if truthy/falsy) + embed = !!(obj.embed), // convert to boolean (if truthy/falsy) + link = !embed; // either link or embed can be true, but not both. the other has to be false + if (!custom) { var keepFrameworks = keep_these_frameworks; @@ -76,7 +96,10 @@ var handlers = { } else { project.frameworks[src] = project.frameworks[src] || 0; project.frameworks[src]++; - project.xcode.addFramework(src, {weak: obj.weak}); + let opt = { customFramework: false, embed: false, link: true, weak: obj.weak }; + events.emit('verbose', util.format('Adding non-custom framework to project... %s -> %s', src, JSON.stringify(opt))); + project.xcode.addFramework(src, opt); + events.emit('verbose', util.format('Non-custom framework added to project. %s -> %s', src, JSON.stringify(opt))); } } return; @@ -85,14 +108,20 @@ var handlers = { targetDir = path.resolve(project.plugins_dir, plugin.id, path.basename(src)); if (!fs.existsSync(srcFile)) throw new CordovaError('Cannot find framework "' + srcFile + '" for plugin ' + plugin.id + ' in iOS platform'); if (fs.existsSync(targetDir)) throw new CordovaError('Framework "' + targetDir + '" for plugin ' + plugin.id + ' already exists in iOS platform'); - var link = !!(options && options.link); - copyFile(plugin.dir, src, project.projectDir, targetDir, link); // frameworks are directories + var symlink = !!(options && options.link); + copyFile(plugin.dir, src, project.projectDir, targetDir, symlink); // frameworks are directories // CB-10773 translate back slashes to forward on win32 var project_relative = fixPathSep(path.relative(project.projectDir, targetDir)); - var pbxFile = project.xcode.addFramework(project_relative, {customFramework: true}); - if (pbxFile) { - project.xcode.addToPbxEmbedFrameworksBuildPhase(pbxFile); + // CB-11233 create Embed Frameworks Build Phase if does not exist + var existsEmbedFrameworks = project.xcode.buildPhaseObject('PBXCopyFilesBuildPhase', 'Embed Frameworks'); + if (!existsEmbedFrameworks && embed) { + events.emit('verbose', '"Embed Frameworks" Build Phase (Embedded Binaries) does not exist, creating it.'); + project.xcode.addBuildPhase([], 'PBXCopyFilesBuildPhase', 'Embed Frameworks', null, 'frameworks'); } + let opt = { customFramework: true, embed: embed, link: link, sign: true }; + events.emit('verbose', util.format('Adding custom framework to project... %s -> %s', src, JSON.stringify(opt))); + project.xcode.addFramework(project_relative, opt); + events.emit('verbose', util.format('Custom framework added to project. %s -> %s', src, JSON.stringify(opt))); }, uninstall:function(obj, plugin, project, options) { var src = obj.src; @@ -304,7 +333,7 @@ function copyFile (plugin_dir, src, project_dir, dest, link) { shell.mkdir('-p', path.dirname(dest)); if (link) { - symlinkFileOrDirTree(src, dest); + linkFileOrDirTree(src, dest); } else if (fs.statSync(src).isDirectory()) { // XXX shelljs decides to create a directory when -R|-r is used which sucks. http://goo.gl/nbsjq shell.cp('-Rf', path.join(src, '/*'), dest); @@ -322,7 +351,7 @@ function copyNewFile (plugin_dir, src, project_dir, dest, link) { copyFile(plugin_dir, src, project_dir, dest, !!link); } -function symlinkFileOrDirTree(src, dest) { +function linkFileOrDirTree(src, dest) { if (fs.existsSync(dest)) { shell.rm('-Rf', dest); } @@ -330,11 +359,11 @@ function symlinkFileOrDirTree(src, dest) { if (fs.statSync(src).isDirectory()) { shell.mkdir('-p', dest); fs.readdirSync(src).forEach(function(entry) { - symlinkFileOrDirTree(path.join(src, entry), path.join(dest, entry)); + linkFileOrDirTree(path.join(src, entry), path.join(dest, entry)); }); } else { - fs.symlinkSync(path.relative(fs.realpathSync(path.dirname(dest)), src), dest); + fs.linkSync(src, dest); } } diff --git a/StoneIsland/platforms/ios/cordova/lib/prepare.js b/StoneIsland/platforms/ios/cordova/lib/prepare.js index d8f52ac9..c02c187f 100755 --- a/StoneIsland/platforms/ios/cordova/lib/prepare.js +++ b/StoneIsland/platforms/ios/cordova/lib/prepare.js @@ -17,6 +17,7 @@ under the License. */ +'use strict'; var Q = require('q'); var fs = require('fs'); var path = require('path'); @@ -33,6 +34,7 @@ var PlatformJson = require('cordova-common').PlatformJson; var PlatformMunger = require('cordova-common').ConfigChanges.PlatformMunger; var PluginInfoProvider = require('cordova-common').PluginInfoProvider; var FileUpdater = require('cordova-common').FileUpdater; +var projectFile = require('./projectFile'); // launch storyboard and related constants var LAUNCHIMAGE_BUILD_SETTING = 'ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME'; @@ -62,6 +64,7 @@ module.exports.prepare = function (cordovaProject, options) { updateIcons(cordovaProject, self.locations); updateSplashScreens(cordovaProject, self.locations); updateLaunchStoryboardImages(cordovaProject, self.locations); + updateFileResources(cordovaProject, self.locations); }) .then(function () { events.emit('verbose', 'Prepared iOS project successfully'); @@ -88,6 +91,7 @@ module.exports.clean = function (options) { cleanIcons(projectRoot, projectConfig, self.locations); cleanSplashScreens(projectRoot, projectConfig, self.locations); cleanLaunchStoryboardImages(projectRoot, projectConfig, self.locations); + cleanFileResources(projectRoot, projectConfig, self.locations); }); }; @@ -452,6 +456,75 @@ function cleanSplashScreens(projectRoot, projectConfig, locations) { } } +function updateFileResources(cordovaProject, locations) { + const platformDir = path.relative(cordovaProject.root, locations.root); + const files = cordovaProject.projectConfig.getFileResources('ios'); + + const project = projectFile.parse(locations); + + // if there are resource-file elements in config.xml + if (files.length === 0) { + events.emit('verbose', 'This app does not have additional resource files defined'); + return; + } + + let resourceMap = {}; + files.forEach(function(res) { + let src = res.src, + target = res.target; + + if (!target) { + target = src; + } + + let targetPath = path.join(project.resources_dir, target); + targetPath = path.relative(cordovaProject.root, targetPath); + + const resfile = path.join('Resources', path.relative(project.resources_dir, targetPath)); + project.xcode.addResourceFile(resfile); + + resourceMap[targetPath] = src; + }); + + events.emit('verbose', 'Updating resource files at ' + platformDir); + FileUpdater.updatePaths( + resourceMap, { rootDir: cordovaProject.root }, logFileOp); + + project.write(); +} + +function cleanFileResources(projectRoot, projectConfig, locations) { + const platformDir = path.relative(projectRoot, locations.root); + const files = projectConfig.getFileResources('ios'); + if (files.length > 0) { + events.emit('verbose', 'Cleaning resource files at ' + platformDir); + + const project = projectFile.parse(locations); + + var resourceMap = {}; + files.forEach(function(res) { + let src = res.src, + target = res.target; + + if (!target) { + target = src; + } + + let targetPath = path.join(project.resources_dir, target); + targetPath = path.relative(projectRoot, targetPath); + const resfile = path.join('Resources', path.basename(targetPath)); + project.xcode.removeResourceFile(resfile); + + resourceMap[targetPath] = null; + }); + + FileUpdater.updatePaths( + resourceMap, { rootDir: projectRoot, all: true}, logFileOp); + + project.write(); + } +} + /** * Returns an array of images for each possible idiom, scale, and size class. The images themselves are * located in the platform's splash images by their pattern (@scale~idiom~sizesize). All possible diff --git a/StoneIsland/platforms/ios/cordova/lib/run.js b/StoneIsland/platforms/ios/cordova/lib/run.js index 68c315a5..0caadf06 100755 --- a/StoneIsland/platforms/ios/cordova/lib/run.js +++ b/StoneIsland/platforms/ios/cordova/lib/run.js @@ -69,10 +69,37 @@ module.exports.run = function (runOptions) { return build.findXCodeProjectIn(projectPath); }).then(function (projectName) { var appPath = path.join(projectPath, 'build', 'emulator', projectName + '.app'); + var buildOutputDir = path.join(projectPath, 'build', 'device'); + // select command to run and arguments depending whether // we're running on device/emulator if (useDevice) { - return checkDeviceConnected().then(function () { + return checkDeviceConnected() + .then(function() { + // Unpack IPA + var ipafile = path.join(buildOutputDir, projectName + '.ipa'); + + // unpack the existing platform/ios/build/device/appname.ipa (zipfile), will create a Payload folder + return spawn('unzip', [ '-o', '-qq', ipafile ], buildOutputDir); + }) + .then(function() { + // Uncompress IPA (zip file) + var appFileInflated = path.join(buildOutputDir, 'Payload', projectName + '.app'); + var appFile = path.join(buildOutputDir, projectName + '.app'); + var payloadFolder = path.join(buildOutputDir, 'Payload'); + + // delete the existing platform/ios/build/device/appname.app + return spawn('rm', [ '-rf', appFile ], buildOutputDir) + .then(function() { + // move the platform/ios/build/device/Payload/appname.app to parent + return spawn('mv', [ '-f', appFileInflated, buildOutputDir ], buildOutputDir); + }) + .then(function() { + // delete the platform/ios/build/device/Payload folder + return spawn('rm', [ '-rf', payloadFolder ], buildOutputDir); + }); + }) + .then(function() { appPath = path.join(projectPath, 'build', 'device', projectName + '.app'); var extraArgs = []; if (runOptions.argv) { |
