CB-7579 Fix run script's ability to use non-arch-specific APKs

This commit is contained in:
Andrew Grieve 2014-09-22 14:23:30 -04:00
parent 3f83fdbfc1
commit 879da03438
4 changed files with 93 additions and 95 deletions

View File

@ -32,23 +32,46 @@ var LOCAL_PROPERTIES_TEMPLATE =
'# This file is automatically generated.\n' + '# This file is automatically generated.\n' +
'# Do not modify this file -- YOUR CHANGES WILL BE ERASED!\n'; '# Do not modify this file -- YOUR CHANGES WILL BE ERASED!\n';
function find_files(directory, predicate) { function findApks(directory) {
var ret = [];
if (fs.existsSync(directory)) { if (fs.existsSync(directory)) {
var candidates = fs.readdirSync(directory).filter(predicate).map(function(p) { fs.readdirSync(directory).forEach(function(p) {
p = path.join(directory, p); if (path.extname(p) == '.apk') {
return { p: p, t: fs.statSync(p).mtime }; ret.push(path.join(directory, p));
}).sort(function(a,b) {
var timeDiff = b.t - a.t;
if (timeDiff === 0) {
return a.p.length - b.p.length;
} }
return timeDiff; });
}).map(function(p) { return p.p; });
return candidates;
} else {
console.error('ERROR : unable to find project ' + directory + ' directory, could not locate .apk');
process.exit(2);
} }
return ret;
}
function sortFilesByDate(files) {
return files.map(function(p) {
return { p: p, t: fs.statSync(p).mtime };
}).sort(function(a, b) {
var timeDiff = b.t - a.t;
return timeDiff === 0 ? a.p.length - b.p.length : timeDiff;
}).map(function(p) { return p.p; });
}
function findOutputApksHelper(dir, build_type) {
var ret = findApks(dir).filter(function(candidate) {
// Need to choose between release and debug .apk.
if (build_type === 'debug') {
return /-debug/.exec(candidate) && !/-unaligned|-unsigned/.exec(candidate);
}
if (build_type === 'release') {
return /-release/.exec(candidate) && !/-unaligned/.exec(candidate);
}
return true;
});
ret = sortFilesByDate(ret);
if (ret.length === 0) {
return ret;
}
var archSpecific = !!/-x86|-arm/.exec(ret[0]);
return ret.filter(function(p) {
return !!/-x86|-arm/.exec(p) == archSpecific;
});
} }
function hasCustomRules() { function hasCustomRules() {
@ -127,8 +150,6 @@ var builders = {
return check_reqs.check_ant() return check_reqs.check_ant()
.then(function() { .then(function() {
return spawn('ant', args); return spawn('ant', args);
}).then(function() {
return builder.getOutputFiles();
}); });
}, },
@ -140,22 +161,9 @@ var builders = {
}); });
}, },
// Find the recently-generated output APK files findOutputApks: function(build_type) {
// Ant only generates one output file; return it. var binDir = path.join(ROOT, hasCustomRules() ? 'ant-build' : 'bin');
getOutputFiles: function() { return findOutputApksHelper(binDir, build_type);
var binDir;
if(hasCustomRules()) {
binDir = path.join(ROOT, 'ant-build');
} else {
binDir = path.join(ROOT, 'bin');
}
var candidates = find_files(binDir, function(candidate) { return path.extname(candidate) == '.apk'; });
if (candidates.length === 0) {
console.error('ERROR : No .apk found in ' + binDir + ' directory');
process.exit(2);
}
var ret = candidates[0];
return [ret];
} }
}, },
gradle: { gradle: {
@ -227,8 +235,6 @@ var builders = {
var args = this.getArgs(build_type == 'debug' ? 'debug' : 'release'); var args = this.getArgs(build_type == 'debug' ? 'debug' : 'release');
return Q().then(function() { return Q().then(function() {
return spawn(wrapper, args); return spawn(wrapper, args);
}).then(function() {
return builder.getOutputFiles(build_type);
}); });
}, },
@ -241,21 +247,9 @@ var builders = {
}); });
}, },
// Find the recently-generated output APK files findOutputApks: function(build_type) {
// Gradle can generate multiple output files; return all of them.
getOutputFiles: function(build_type) {
var binDir = path.join(ROOT, 'build', 'outputs', 'apk'); var binDir = path.join(ROOT, 'build', 'outputs', 'apk');
var candidates = find_files(binDir, function(candidate) { return findOutputApksHelper(binDir, build_type);
// Need to choose between release and debug .apk.
if (build_type === 'debug') {
return (path.extname(candidate) == '.apk' && candidate.indexOf('-debug') >= 0);
}
if (build_type === 'release') {
return (path.extname(candidate) == '.apk' && candidate.indexOf('-release') >= 0);
}
return path.extname(candidate) == '.apk';
});
return candidates;
} }
}, },
@ -265,11 +259,14 @@ var builders = {
}, },
build: function() { build: function() {
console.log('Skipping build...'); console.log('Skipping build...');
return Q(); return Q(null);
}, },
clean: function() { clean: function() {
return Q(); return Q();
}, },
findOutputApks: function(build_type) {
return sortFilesByDate(builders.ant.findOutputApks(build_type).concat(builders.gradle.findOutputApks(build_type)));
}
} }
}; };
@ -284,7 +281,7 @@ function parseOpts(options) {
// Iterate through command line options // Iterate through command line options
for (var i=0; options && (i < options.length); ++i) { for (var i=0; options && (i < options.length); ++i) {
if (options[i].substring && options[i].substring(0,2) == "--") { if (/^--/.exec(options[i])) {
var option = options[i].substring(2); var option = options[i].substring(2);
switch(option) { switch(option) {
case 'debug': case 'debug':
@ -334,20 +331,15 @@ module.exports.run = function(options) {
return builder.prepEnv() return builder.prepEnv()
.then(function() { .then(function() {
return builder.build(opts.buildType); return builder.build(opts.buildType);
}).then(function(apkFiles) { }).then(function() {
// TODO: Rather than copy apks to out, it might be better to var apkPaths = builder.findOutputApks(opts.buildType);
// just write out what the last .apk build was. These files console.log('Built the following apk(s):');
// are used by get_apk(). console.log(' ' + apkPaths.join('\n '));
var outputDir = path.join(ROOT, 'out'); return {
shell.mkdir('-p', outputDir); apkPaths: apkPaths,
var builtApks = []; buildType: opts.buildType,
for (var i=0; i < apkFiles.length; ++i) { buildMethod: opts.buildMethod
var dst = path.join(outputDir, path.basename(apkFiles[i])); };
builtApks.push(dst);
shell.cp('-f', apkFiles[i], dst);
}
console.log('Built the following APKs:\n' + builtApks.join('\n'));
return builtApks;
}); });
}; };
@ -365,21 +357,25 @@ module.exports.detectArchitecture = function(target) {
}); });
}; };
/* module.exports.findBestApkForArchitecture = function(buildResults, arch) {
* Gets the path to the apk file, if not such file exists then var paths = buildResults.apkPaths.filter(function(p) {
* the script will error out. (should we error or just return undefined?) if (buildResults.buildType == 'debug') {
* This is called by the run script to install the apk to the device return /-debug/.exec(p);
*/ }
module.exports.get_apk = function(build_type, architecture) { return !/-debug/.exec(p);
var outputDir = path.join(ROOT, 'out'); });
var candidates = find_files(outputDir, function(filename) { return (!architecture) || filename.indexOf(architecture) >= 0; }); var archPattern = new RegExp('-' + arch);
if (candidates.length === 0) { var hasArchPattern = /-x86|-arm/;
console.error('ERROR : No .apk found in ' + outputDir + ' directory'); for (var i = 0; i < paths.length; ++i) {
process.exit(2); if (hasArchPattern.exec(paths[i])) {
if (archPattern.exec(paths[i])) {
return paths[i];
}
} else {
return paths[i];
}
} }
// TODO: Use build_type here. throw new Error('Could not find apk architecture: ' + arch + ' build-type: ' + buildResults.buildType);
console.log('Using apk: ' + candidates[0]);
return candidates[0];
}; };
module.exports.help = function() { module.exports.help = function() {

View File

@ -48,7 +48,7 @@ module.exports.list = function() {
* and launches it. * and launches it.
* Returns a promise. * Returns a promise.
*/ */
module.exports.install = function(target) { module.exports.install = function(target, buildResults) {
var launchName; var launchName;
return this.list() return this.list()
.then(function(device_list) { .then(function(device_list) {
@ -64,8 +64,9 @@ module.exports.install = function(target) {
return build.detectArchitecture(target) return build.detectArchitecture(target)
.then(function(arch) { .then(function(arch) {
var apk_path = build.get_apk(null, arch); var apk_path = build.findBestApkForArchitecture(buildResults, arch);
launchName = appinfo.getActivityName(); launchName = appinfo.getActivityName();
console.log('Using apk: ' + apk_path);
console.log('Installing app on device...'); console.log('Installing app on device...');
var cmd = 'adb -s ' + target + ' install -r "' + apk_path + '"'; var cmd = 'adb -s ' + target + ' install -r "' + apk_path + '"';
return exec(cmd); return exec(cmd);

View File

@ -279,7 +279,7 @@ module.exports.create_image = function(name, target) {
* If no started emulators are found, error out. * If no started emulators are found, error out.
* Returns a promise. * Returns a promise.
*/ */
module.exports.install = function(target) { module.exports.install = function(target, buildResults) {
var self = this; var self = this;
return this.list_started() return this.list_started()
.then(function(emulator_list) { .then(function(emulator_list) {
@ -295,8 +295,9 @@ module.exports.install = function(target) {
return build.detectArchitecture(target) return build.detectArchitecture(target)
.then(function(arch) { .then(function(arch) {
var apk_path = build.get_apk(null, arch); var apk_path = build.findBestApkForArchitecture(buildResults, arch);
console.log('Installing app on emulator...'); console.log('Installing app on emulator...');
console.log('Using apk: ' + apk_path);
return exec('adb -s ' + target + ' install -r "' + apk_path + '"'); return exec('adb -s ' + target + ' install -r "' + apk_path + '"');
}); });
}).then(function(output) { }).then(function(output) {

View File

@ -33,16 +33,16 @@ var path = require('path'),
* Returns a promise. * Returns a promise.
*/ */
module.exports.run = function(args) { module.exports.run = function(args) {
var build_type; var buildFlags = [];
var install_target; var install_target;
for (var i=2; i<args.length; i++) { for (var i=2; i<args.length; i++) {
if (args[i] == '--debug') { if (args[i] == '--debug') {
build_type = '--debug'; buildFlags.push('--debug');
} else if (args[i] == '--release') { } else if (args[i] == '--release') {
build_type = '--release'; buildFlags.push('--release');
} else if (args[i] == '--nobuild') { } else if (args[i] == '--nobuild') {
build_type = '--nobuild'; buildFlags.push('--nobuild');
} else if (args[i] == '--device') { } else if (args[i] == '--device') {
install_target = '--device'; install_target = '--device';
} else if (args[i] == '--emulator') { } else if (args[i] == '--emulator') {
@ -55,13 +55,13 @@ var path = require('path'),
} }
} }
return build.run(build_type).then(function() { return build.run(buildFlags).then(function(buildResults) {
if (install_target == '--device') { if (install_target == '--device') {
return device.install(); return device.install(null, buildResults);
} else if (install_target == '--emulator') { } else if (install_target == '--emulator') {
return emulator.list_started().then(function(started) { return emulator.list_started().then(function(started) {
var p = started && started.length > 0 ? Q() : emulator.start(); var p = started && started.length > 0 ? Q() : emulator.start();
return p.then(function() { emulator.install(); }); return p.then(function() { emulator.install(null, buildResults); });
}); });
} else if (install_target) { } else if (install_target) {
var devices, started_emulators, avds; var devices, started_emulators, avds;
@ -75,16 +75,16 @@ var path = require('path'),
}).then(function(res) { }).then(function(res) {
avds = res; avds = res;
if (devices.indexOf(install_target) > -1) { if (devices.indexOf(install_target) > -1) {
return device.install(install_target); return device.install(install_target, buildResults);
} else if (started_emulators.indexOf(install_target) > -1) { } else if (started_emulators.indexOf(install_target) > -1) {
return emulator.install(install_target); return emulator.install(install_target, buildResults);
} else { } else {
// if target emulator isn't started, then start it. // if target emulator isn't started, then start it.
var emulator_ID; var emulator_ID;
for(avd in avds) { for(avd in avds) {
if(avds[avd].name == install_target) { if(avds[avd].name == install_target) {
return emulator.start(install_target) return emulator.start(install_target)
.then(function() { emulator.install(emulator_ID); }); .then(function() { emulator.install(emulator_ID, buildResults); });
} }
} }
return Q.reject('Target \'' + install_target + '\' not found, unable to run project'); return Q.reject('Target \'' + install_target + '\' not found, unable to run project');
@ -96,13 +96,13 @@ var path = require('path'),
.then(function(device_list) { .then(function(device_list) {
if (device_list.length > 0) { if (device_list.length > 0) {
console.log('WARNING : No target specified, deploying to device \'' + device_list[0] + '\'.'); console.log('WARNING : No target specified, deploying to device \'' + device_list[0] + '\'.');
return device.install(device_list[0]); return device.install(device_list[0], buildResults);
} else { } else {
return emulator.list_started() return emulator.list_started()
.then(function(emulator_list) { .then(function(emulator_list) {
if (emulator_list.length > 0) { if (emulator_list.length > 0) {
console.log('WARNING : No target specified, deploying to emulator \'' + emulator_list[0] + '\'.'); console.log('WARNING : No target specified, deploying to emulator \'' + emulator_list[0] + '\'.');
return emulator.install(emulator_list[0]); return emulator.install(emulator_list[0], buildResults);
} else { } else {
console.log('WARNING : No started emulators found, starting an emulator.'); console.log('WARNING : No started emulators found, starting an emulator.');
return emulator.best_image() return emulator.best_image()
@ -111,7 +111,7 @@ var path = require('path'),
return emulator.start(best_avd.name) return emulator.start(best_avd.name)
.then(function(emulator_ID) { .then(function(emulator_ID) {
console.log('WARNING : No target specified, deploying to emulator \'' + emulator_ID + '\'.'); console.log('WARNING : No target specified, deploying to emulator \'' + emulator_ID + '\'.');
return emulator.install(emulator_ID); return emulator.install(emulator_ID, buildResults);
}); });
} else { } else {
return emulator.start(); return emulator.start();