gradle: Build only the active architecture when applicable

This commit is contained in:
Andrew Grieve 2014-09-24 16:07:31 -04:00
parent 9e3ccf4b3e
commit 162d9b6c2e
4 changed files with 174 additions and 139 deletions

View File

@ -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 {

View File

@ -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);
});
});
}

View File

@ -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);
});
});
}

View File

@ -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);
});
});
}