From 162d9b6c2eed589b8fddd9e39b4433eb1b251331 Mon Sep 17 00:00:00 2001 From: Andrew Grieve Date: Wed, 24 Sep 2014 16:07:31 -0400 Subject: [PATCH 1/2] gradle: Build only the active architecture when applicable --- bin/templates/cordova/lib/build.js | 56 ++++++++----- bin/templates/cordova/lib/device.js | 73 +++++++++-------- bin/templates/cordova/lib/emulator.js | 75 ++++++++++-------- bin/templates/cordova/lib/run.js | 109 ++++++++++++-------------- 4 files changed, 174 insertions(+), 139 deletions(-) diff --git a/bin/templates/cordova/lib/build.js b/bin/templates/cordova/lib/build.js index c5b6b092..7fc36d70 100644 --- a/bin/templates/cordova/lib/build.js +++ b/bin/templates/cordova/lib/build.js @@ -53,7 +53,7 @@ function sortFilesByDate(files) { }).map(function(p) { return p.p; }); } -function findOutputApksHelper(dir, build_type) { +function findOutputApksHelper(dir, build_type, arch) { var ret = findApks(dir).filter(function(candidate) { // Need to choose between release and debug .apk. if (build_type === 'debug') { @@ -69,9 +69,15 @@ function findOutputApksHelper(dir, build_type) { return ret; } var archSpecific = !!/-x86|-arm/.exec(ret[0]); - return ret.filter(function(p) { + ret = ret.filter(function(p) { return !!/-x86|-arm/.exec(p) == archSpecific; }); + if (arch) { + ret = ret.filter(function(p) { + return p.indexOf('-' + arch) != -1; + }); + } + return ret; } function hasCustomRules() { @@ -163,11 +169,11 @@ var builders = { findOutputApks: function(build_type) { var binDir = path.join(ROOT, hasCustomRules() ? 'ant-build' : 'bin'); - return findOutputApksHelper(binDir, build_type); + return findOutputApksHelper(binDir, build_type, null); } }, gradle: { - getArgs: function(cmd) { + getArgs: function(cmd, arch) { var lintSteps; if (process.env['BUILD_MULTIPLE_APKS']) { lintSteps = [ @@ -187,7 +193,15 @@ var builders = { 'copyDebugLint' ]; } - if (cmd == 'debug') { + if (arch == 'arm' && cmd == 'debug') { + cmd = 'assembleArmv7Debug'; + } else if (arch == 'arm' && cmd == 'release') { + cmd = 'assembleArmv7Release'; + } else if (arch == 'x86' && cmd == 'debug') { + cmd = 'assembleX86Debug'; + } else if (arch == 'x86' && cmd == 'release') { + cmd = 'assembleX86Release'; + } else if (cmd == 'debug') { cmd = 'assembleDebug'; } else if (cmd == 'release') { cmd = 'assembleRelease'; @@ -260,10 +274,10 @@ var builders = { * Builds the project with gradle. * Returns a promise. */ - build: function(build_type) { + build: function(build_type, arch) { var builder = this; var wrapper = path.join(ROOT, 'gradlew'); - var args = this.getArgs(build_type == 'debug' ? 'debug' : 'release'); + var args = this.getArgs(build_type == 'debug' ? 'debug' : 'release', arch); return Q().then(function() { return spawn(wrapper, args); }); @@ -278,9 +292,9 @@ var builders = { }); }, - findOutputApks: function(build_type) { + findOutputApks: function(build_type, arch) { var binDir = path.join(ROOT, 'build', 'outputs', 'apk'); - return findOutputApksHelper(binDir, build_type); + return findOutputApksHelper(binDir, build_type, arch); } }, @@ -295,19 +309,20 @@ var builders = { clean: function() { return Q(); }, - findOutputApks: function(build_type) { - return sortFilesByDate(builders.ant.findOutputApks(build_type).concat(builders.gradle.findOutputApks(build_type))); + findOutputApks: function(build_type, arch) { + return sortFilesByDate(builders.ant.findOutputApks(build_type, arch).concat(builders.gradle.findOutputApks(build_type, arch))); } } }; -function parseOpts(options) { +function parseOpts(options, resolvedTarget) { // Backwards-compatibility: Allow a single string argument if (typeof options == "string") options = [options]; var ret = { buildType: 'debug', - buildMethod: process.env['ANDROID_BUILD'] || 'ant' + buildMethod: process.env['ANDROID_BUILD'] || 'ant', + arch: null }; // Iterate through command line options @@ -333,6 +348,12 @@ function parseOpts(options) { return Q.reject('Build option \'' + options[i] + '\' not recognized.'); } } + + var multiApk = ret.buildMethod == 'gradle' && process.env['BUILD_MULTIPLE_APKS']; + if (multiApk && !/0|false|no/i.exec(multiApk)) { + ret.arch = resolvedTarget && resolvedTarget.arch; + } + return ret; } @@ -355,15 +376,14 @@ module.exports.runClean = function(options) { * Builds the project with the specifed options * Returns a promise. */ -module.exports.run = function(options) { - var opts = parseOpts(options); - +module.exports.run = function(options, optResolvedTarget) { + var opts = parseOpts(options, optResolvedTarget); var builder = builders[opts.buildMethod]; return builder.prepEnv() .then(function() { - return builder.build(opts.buildType); + return builder.build(opts.buildType, opts.arch); }).then(function() { - var apkPaths = builder.findOutputApks(opts.buildType); + var apkPaths = builder.findOutputApks(opts.buildType, opts.arch); console.log('Built the following apk(s):'); console.log(' ' + apkPaths.join('\n ')); return { diff --git a/bin/templates/cordova/lib/device.js b/bin/templates/cordova/lib/device.js index b2df1d70..6be55e30 100644 --- a/bin/templates/cordova/lib/device.js +++ b/bin/templates/cordova/lib/device.js @@ -43,20 +43,14 @@ module.exports.list = function() { }); } -/* - * Installs a previously built application on the device - * and launches it. - * Returns a promise. - */ -module.exports.install = function(target, buildResults) { - var launchName; +module.exports.resolveTarget = function(target) { return this.list() .then(function(device_list) { - if (!device_list || !device_list.length) + if (!device_list || !device_list.length) { return Q.reject('ERROR: Failed to deploy to device, no devices found.'); - + } // default device - target = typeof target !== 'undefined' ? target : device_list[0]; + target = target || device_list[0]; if (device_list.indexOf(target) < 0) { return Q.reject('ERROR: Unable to find target \'' + target + '\'.'); @@ -64,28 +58,45 @@ module.exports.install = function(target, buildResults) { return build.detectArchitecture(target) .then(function(arch) { - var apk_path = build.findBestApkForArchitecture(buildResults, arch); - launchName = appinfo.getActivityName(); - console.log('Using apk: ' + apk_path); - console.log('Installing app on device...'); - var cmd = 'adb -s ' + target + ' install -r "' + apk_path + '"'; - return exec(cmd); + return { target: target, arch: arch, isEmulator: false }; }); - }).then(function(output) { - if (output.match(/Failure/)) return Q.reject('ERROR: Failed to install apk to device: ' + output); + }); +}; - //unlock screen - var cmd = 'adb -s ' + target + ' shell input keyevent 82'; - return exec(cmd); - }, function(err) { return Q.reject('ERROR: Failed to install apk to device: ' + err); }) - .then(function() { - // launch the application - console.log('Launching application...'); - var cmd = 'adb -s ' + target + ' shell am start -W -a android.intent.action.MAIN -n ' + launchName; - return exec(cmd); - }).then(function() { - console.log('LAUNCH SUCCESS'); - }, function(err) { - return Q.reject('ERROR: Failed to launch application on device: ' + err); +/* + * Installs a previously built application on the device + * and launches it. + * Returns a promise. + */ +module.exports.install = function(target, buildResults) { + return Q().then(function() { + if (target && typeof target == 'object') { + return target; + } + return module.exports.resolveTarget(target); + }).then(function(resolvedTarget) { + var apk_path = build.findBestApkForArchitecture(buildResults, resolvedTarget.arch); + var launchName = appinfo.getActivityName(); + console.log('Using apk: ' + apk_path); + console.log('Installing app on device...'); + var cmd = 'adb -s ' + resolvedTarget.target + ' install -r "' + apk_path + '"'; + return exec(cmd) + .then(function(output) { + if (output.match(/Failure/)) return Q.reject('ERROR: Failed to install apk to device: ' + output); + + //unlock screen + var cmd = 'adb -s ' + resolvedTarget.target + ' shell input keyevent 82'; + return exec(cmd); + }, function(err) { return Q.reject('ERROR: Failed to install apk to device: ' + err); }) + .then(function() { + // launch the application + console.log('Launching application...'); + var cmd = 'adb -s ' + resolvedTarget.target + ' shell am start -W -a android.intent.action.MAIN -n ' + launchName; + return exec(cmd); + }).then(function() { + console.log('LAUNCH SUCCESS'); + }, function(err) { + return Q.reject('ERROR: Failed to launch application on device: ' + err); + }); }); } diff --git a/bin/templates/cordova/lib/emulator.js b/bin/templates/cordova/lib/emulator.js index ecc8b380..8cf58e2d 100644 --- a/bin/templates/cordova/lib/emulator.js +++ b/bin/templates/cordova/lib/emulator.js @@ -273,14 +273,7 @@ module.exports.create_image = function(name, target) { } } -/* - * Installs a previously built application on the emulator and launches it. - * If no target is specified, then it picks one. - * If no started emulators are found, error out. - * Returns a promise. - */ -module.exports.install = function(target, buildResults) { - var self = this; +module.exports.resolveTarget = function(target) { return this.list_started() .then(function(emulator_list) { if (emulator_list.length < 1) { @@ -288,37 +281,55 @@ module.exports.install = function(target, buildResults) { } // default emulator - target = typeof target !== 'undefined' ? target : emulator_list[0]; + target = target || emulator_list[0]; if (emulator_list.indexOf(target) < 0) { return Q.reject('Unable to find target \'' + target + '\'. Failed to deploy to emulator.'); } return build.detectArchitecture(target) .then(function(arch) { - var apk_path = build.findBestApkForArchitecture(buildResults, arch); - console.log('Installing app on emulator...'); - console.log('Using apk: ' + apk_path); - return exec('adb -s ' + target + ' install -r "' + apk_path + '"'); + return {target:target, arch:arch, isEmulator:true}; }); - }).then(function(output) { - if (output.match(/Failure/)) { - return Q.reject('Failed to install apk to emulator: ' + output); + }); +}; + +/* + * Installs a previously built application on the emulator and launches it. + * If no target is specified, then it picks one. + * If no started emulators are found, error out. + * Returns a promise. + */ +module.exports.install = function(target, buildResults) { + return Q().then(function() { + if (target && typeof target == 'object') { + return target; } - return Q(); - }, function(err) { - return Q.reject('Failed to install apk to emulator: ' + err); - }).then(function() { - //unlock screen - return exec('adb -s ' + target + ' shell input keyevent 82'); - }).then(function() { - // launch the application - console.log('Launching application...'); - var launchName = appinfo.getActivityName(); - cmd = 'adb -s ' + target + ' shell am start -W -a android.intent.action.MAIN -n ' + launchName; - return exec(cmd); - }).then(function(output) { - console.log('LAUNCH SUCCESS'); - }, function(err) { - return Q.reject('Failed to launch app on emulator: ' + err); + return module.exports.resolveTarget(target); + }).then(function(resolvedTarget) { + var apk_path = build.findBestApkForArchitecture(buildResults, resolvedTarget.arch); + console.log('Installing app on emulator...'); + console.log('Using apk: ' + apk_path); + return exec('adb -s ' + resolvedTarget.target + ' install -r "' + apk_path + '"') + .then(function(output) { + if (output.match(/Failure/)) { + return Q.reject('Failed to install apk to emulator: ' + output); + } + return Q(); + }, function(err) { + return Q.reject('Failed to install apk to emulator: ' + err); + }).then(function() { + //unlock screen + return exec('adb -s ' + resolvedTarget.target + ' shell input keyevent 82'); + }).then(function() { + // launch the application + console.log('Launching application...'); + var launchName = appinfo.getActivityName(); + cmd = 'adb -s ' + resolvedTarget.target + ' shell am start -W -a android.intent.action.MAIN -n ' + launchName; + return exec(cmd); + }).then(function(output) { + console.log('LAUNCH SUCCESS'); + }, function(err) { + return Q.reject('Failed to launch app on emulator: ' + err); + }); }); } diff --git a/bin/templates/cordova/lib/run.js b/bin/templates/cordova/lib/run.js index 16e8065b..024fcd08 100644 --- a/bin/templates/cordova/lib/run.js +++ b/bin/templates/cordova/lib/run.js @@ -55,73 +55,66 @@ var path = require('path'), } } - return build.run(buildFlags).then(function(buildResults) { - if (install_target == '--device') { - return device.install(null, buildResults); - } else if (install_target == '--emulator') { - return emulator.list_started().then(function(started) { - var p = started && started.length > 0 ? Q() : emulator.start(); - return p.then(function() { emulator.install(null, buildResults); }); - }); - } else if (install_target) { - var devices, started_emulators, avds; - return device.list() - .then(function(res) { - devices = res; - return emulator.list_started(); - }).then(function(res) { - started_emulators = res; - return emulator.list_images(); - }).then(function(res) { - avds = res; - if (devices.indexOf(install_target) > -1) { - return device.install(install_target, buildResults); - } else if (started_emulators.indexOf(install_target) > -1) { - return emulator.install(install_target, buildResults); - } else { - // if target emulator isn't started, then start it. - var emulator_ID; - for(avd in avds) { - if(avds[avd].name == install_target) { - return emulator.start(install_target) - .then(function() { emulator.install(emulator_ID, buildResults); }); - } - } - return Q.reject('Target \'' + install_target + '\' not found, unable to run project'); - } - }); - } else { + return Q() + .then(function() { + if (!install_target) { // no target given, deploy to device if available, otherwise use the emulator. return device.list() .then(function(device_list) { if (device_list.length > 0) { console.log('WARNING : No target specified, deploying to device \'' + device_list[0] + '\'.'); - return device.install(device_list[0], buildResults); + install_target = device_list[0]; } else { - return emulator.list_started() - .then(function(emulator_list) { - if (emulator_list.length > 0) { - console.log('WARNING : No target specified, deploying to emulator \'' + emulator_list[0] + '\'.'); - return emulator.install(emulator_list[0], buildResults); - } else { - console.log('WARNING : No started emulators found, starting an emulator.'); - return emulator.best_image() - .then(function(best_avd) { - if(best_avd) { - return emulator.start(best_avd.name) - .then(function(emulator_ID) { - console.log('WARNING : No target specified, deploying to emulator \'' + emulator_ID + '\'.'); - return emulator.install(emulator_ID, buildResults); - }); - } else { - return emulator.start(); - } - }); - } - }); + console.log('WARNING : No target specified, deploying to emulator'); + install_target = '--emulator'; } }); } + }).then(function() { + if (install_target == '--device') { + return device.resolveTarget(null); + } else if (install_target == '--emulator') { + // Give preference to any already started emulators. Else, start one. + return emulator.list_started() + .then(function(started) { + return started && started.length > 0 ? started[0] : emulator.start(); + }).then(function(emulatorId) { + return emulator.resolveTarget(emulatorId); + }); + } + // They specified a specific device/emulator ID. + return device.list() + .then(function(devices) { + if (devices.indexOf(install_target) > -1) { + return device.resolveTarget(install_target); + } + return emulator.list_started() + .then(function(started_emulators) { + if (started_emulators.indexOf(install_target) > -1) { + return emulator.resolveTarget(install_target); + } + return emulator.list_images() + .then(function(avds) { + // if target emulator isn't started, then start it. + for (avd in avds) { + if (avds[avd].name == install_target) { + return emulator.start(install_target) + .then(function(emulatorId) { + return emulator.resolveTarget(emulatorId); + }); + } + } + return Q.reject('Target \'' + install_target + '\' not found, unable to run project'); + }); + }); + }); + }).then(function(resolvedTarget) { + return build.run(buildFlags, resolvedTarget).then(function(buildResults) { + if (resolvedTarget.isEmulator) { + return emulator.install(resolvedTarget, buildResults); + } + return device.install(resolvedTarget, buildResults); + }); }); } From a986e723384cb7d9e8aeb6b273fd467f827ffb03 Mon Sep 17 00:00:00 2001 From: Max Woghiren Date: Mon, 22 Sep 2014 16:04:24 -0400 Subject: [PATCH 2/2] Added gradle distribution URL updating. (commit fix-up) --- bin/templates/cordova/lib/build.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/bin/templates/cordova/lib/build.js b/bin/templates/cordova/lib/build.js index 7fc36d70..85a6e7cd 100644 --- a/bin/templates/cordova/lib/build.js +++ b/bin/templates/cordova/lib/build.js @@ -239,8 +239,7 @@ var builders = { // If the gradle distribution URL is set, make sure it points to version 1.12. // If it's not set, do nothing, assuming that we're using a future version of gradle that we don't want to mess with. - // For some reason, using ^ and $ don't work. This does the job, though. - var distributionUrlRegex = /distributionUrl.*zip/; + var distributionUrlRegex = '/^distributionUrl=.*$/'; var distributionUrl = 'distributionUrl=http\\://services.gradle.org/distributions/gradle-1.12-all.zip'; var gradleWrapperPropertiesPath = path.join(projectPath, 'gradle', 'wrapper', 'gradle-wrapper.properties'); shell.sed('-i', distributionUrlRegex, distributionUrl, gradleWrapperPropertiesPath);