summaryrefslogtreecommitdiff
path: root/StoneIsland/platforms/android/cordova/lib/build.js
diff options
context:
space:
mode:
Diffstat (limited to 'StoneIsland/platforms/android/cordova/lib/build.js')
-rw-r--r--[-rwxr-xr-x]StoneIsland/platforms/android/cordova/lib/build.js590
1 files changed, 87 insertions, 503 deletions
diff --git a/StoneIsland/platforms/android/cordova/lib/build.js b/StoneIsland/platforms/android/cordova/lib/build.js
index aa9f3d01..bd613da2 100755..100644
--- a/StoneIsland/platforms/android/cordova/lib/build.js
+++ b/StoneIsland/platforms/android/cordova/lib/build.js
@@ -19,477 +19,68 @@
under the License.
*/
-/* jshint sub:true */
-
-var shell = require('shelljs'),
- spawn = require('./spawn'),
- Q = require('q'),
+var Q = require('q'),
path = require('path'),
fs = require('fs'),
- os = require('os'),
- ROOT = path.join(__dirname, '..', '..');
-var check_reqs = require('./check_reqs');
-var exec = require('./exec');
-
+ nopt = require('nopt');
-var SIGNING_PROPERTIES = '-signing.properties';
-var MARKER = 'YOUR CHANGES WILL BE ERASED!';
-var TEMPLATE =
- '# This file is automatically generated.\n' +
- '# Do not modify this file -- ' + MARKER + '\n';
-
-function findApks(directory) {
- var ret = [];
- if (fs.existsSync(directory)) {
- fs.readdirSync(directory).forEach(function(p) {
- if (path.extname(p) == '.apk') {
- ret.push(path.join(directory, p));
- }
- });
- }
- return ret;
-}
+var Adb = require('./Adb');
-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; });
-}
+var builders = require('./builders/builders');
+var events = require('cordova-common').events;
+var spawn = require('cordova-common').superspawn.spawn;
+var CordovaError = require('cordova-common').CordovaError;
-function isAutoGenerated(file) {
- if(fs.existsSync(file)) {
- var fileContents = fs.readFileSync(file, 'utf8');
- return fileContents.indexOf(MARKER) > 0;
- }
- return false;
-}
+function parseOpts(options, resolvedTarget, projectRoot) {
+ options = options || {};
+ options.argv = nopt({
+ gradle: Boolean,
+ ant: Boolean,
+ prepenv: Boolean,
+ versionCode: String,
+ minSdkVersion: String,
+ gradleArg: [String, Array],
+ keystore: path,
+ alias: String,
+ storePassword: String,
+ password: String,
+ keystoreType: String
+ }, {}, options.argv, 0);
-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') {
- 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;
- }
- // Assume arch-specific build if newest apk has -x86 or -arm.
- var archSpecific = !!/-x86|-arm/.exec(ret[0]);
- // And show only arch-specific ones (or non-arch-specific)
- ret = ret.filter(function(p) {
- /*jshint -W018 */
- return !!/-x86|-arm/.exec(p) == archSpecific;
- /*jshint +W018 */
- });
- if (archSpecific && ret.length > 1) {
- ret = ret.filter(function(p) {
- return p.indexOf('-' + arch) != -1;
- });
- }
-
- return ret;
-}
-
-function hasCustomRules() {
- return fs.existsSync(path.join(ROOT, 'custom_rules.xml'));
-}
-
-function extractRealProjectNameFromManifest(projectPath) {
- var manifestPath = path.join(projectPath, 'AndroidManifest.xml');
- var manifestData = fs.readFileSync(manifestPath, 'utf8');
- var m = /<manifest[\s\S]*?package\s*=\s*"(.*?)"/i.exec(manifestData);
- if (!m) {
- throw new Error('Could not find package name in ' + manifestPath);
- }
-
- var packageName=m[1];
- var lastDotIndex = packageName.lastIndexOf('.');
- return packageName.substring(lastDotIndex + 1);
-}
-
-function extractProjectNameFromManifest(projectPath) {
- var manifestPath = path.join(projectPath, 'AndroidManifest.xml');
- var manifestData = fs.readFileSync(manifestPath, 'utf8');
- var m = /<activity[\s\S]*?android:name\s*=\s*"(.*?)"/i.exec(manifestData);
- if (!m) {
- throw new Error('Could not find activity name in ' + manifestPath);
- }
- return m[1];
-}
-
-function findAllUniq(data, r) {
- var s = {};
- var m;
- while ((m = r.exec(data))) {
- s[m[1]] = 1;
- }
- return Object.keys(s);
-}
-
-function readProjectProperties() {
- var data = fs.readFileSync(path.join(ROOT, 'project.properties'), 'utf8');
- return {
- libs: findAllUniq(data, /^\s*android\.library\.reference\.\d+=(.*)(?:\s|$)/mg),
- gradleIncludes: findAllUniq(data, /^\s*cordova\.gradle\.include\.\d+=(.*)(?:\s|$)/mg),
- systemLibs: findAllUniq(data, /^\s*cordova\.system\.library\.\d+=(.*)(?:\s|$)/mg)
+ var ret = {
+ buildType: options.release ? 'release' : 'debug',
+ buildMethod: process.env.ANDROID_BUILD || 'gradle',
+ prepEnv: options.argv.prepenv,
+ arch: resolvedTarget && resolvedTarget.arch,
+ extraArgs: []
};
-}
-
-var builders = {
- ant: {
- getArgs: function(cmd, opts) {
- var args = [cmd, '-f', path.join(ROOT, 'build.xml')];
- // custom_rules.xml is required for incremental builds.
- if (hasCustomRules()) {
- args.push('-Dout.dir=ant-build', '-Dgen.absolute.dir=ant-gen');
- }
- if(opts.packageInfo) {
- args.push('-propertyfile=' + path.join(ROOT, opts.buildType + SIGNING_PROPERTIES));
- }
- return args;
- },
- prepEnv: function(opts) {
- return check_reqs.check_ant()
- .then(function() {
- // Copy in build.xml on each build so that:
- // A) we don't require the Android SDK at project creation time, and
- // B) we always use the SDK's latest version of it.
- var sdkDir = process.env['ANDROID_HOME'];
- var buildTemplate = fs.readFileSync(path.join(sdkDir, 'tools', 'lib', 'build.template'), 'utf8');
- function writeBuildXml(projectPath) {
- var newData = buildTemplate.replace('PROJECT_NAME', extractProjectNameFromManifest(ROOT));
- fs.writeFileSync(path.join(projectPath, 'build.xml'), newData);
- if (!fs.existsSync(path.join(projectPath, 'local.properties'))) {
- fs.writeFileSync(path.join(projectPath, 'local.properties'), TEMPLATE);
- }
- }
- writeBuildXml(ROOT);
- var propertiesObj = readProjectProperties();
- var subProjects = propertiesObj.libs;
- for (var i = 0; i < subProjects.length; ++i) {
- writeBuildXml(path.join(ROOT, subProjects[i]));
- }
- if (propertiesObj.systemLibs.length > 0) {
- throw new Error('Project contains at least one plugin that requires a system library. This is not supported with ANT. Please build using gradle.');
- }
+ if (options.argv.ant || options.argv.gradle)
+ ret.buildMethod = options.argv.ant ? 'ant' : 'gradle';
- var propertiesFile = opts.buildType + SIGNING_PROPERTIES;
- var propertiesFilePath = path.join(ROOT, propertiesFile);
- if (opts.packageInfo) {
- fs.writeFileSync(propertiesFilePath, TEMPLATE + opts.packageInfo.toProperties());
- } else if(isAutoGenerated(propertiesFilePath)) {
- shell.rm('-f', propertiesFilePath);
- }
- });
- },
+ if (options.nobuild) ret.buildMethod = 'none';
- /*
- * Builds the project with ant.
- * Returns a promise.
- */
- build: function(opts) {
- // Without our custom_rules.xml, we need to clean before building.
- var ret = Q();
- if (!hasCustomRules()) {
- // clean will call check_ant() for us.
- ret = this.clean(opts);
- }
+ if (options.argv.versionCode)
+ ret.extraArgs.push('-PcdvVersionCode=' + options.argv.versionCode);
- var args = this.getArgs(opts.buildType == 'debug' ? 'debug' : 'release', opts);
- return check_reqs.check_ant()
- .then(function() {
- console.log('Executing: ant ' + args.join(' '));
- return spawn('ant', args);
- });
- },
-
- clean: function(opts) {
- var args = this.getArgs('clean', opts);
- return check_reqs.check_ant()
- .then(function() {
- return spawn('ant', args);
- });
- },
+ if (options.argv.minSdkVersion)
+ ret.extraArgs.push('-PcdvMinSdkVersion=' + options.argv.minSdkVersion);
- findOutputApks: function(build_type) {
- var binDir = path.join(ROOT, hasCustomRules() ? 'ant-build' : 'bin');
- return findOutputApksHelper(binDir, build_type, null);
- }
- },
- gradle: {
- getArgs: function(cmd, opts) {
- if (cmd == 'release') {
- cmd = 'cdvBuildRelease';
- } else if (cmd == 'debug') {
- cmd = 'cdvBuildDebug';
- }
- var args = [cmd, '-b', path.join(ROOT, 'build.gradle')];
- if (opts.arch) {
- args.push('-PcdvBuildArch=' + opts.arch);
- }
-
- // 10 seconds -> 6 seconds
- args.push('-Dorg.gradle.daemon=true');
- args.push.apply(args, opts.extraArgs);
- // Shaves another 100ms, but produces a "try at own risk" warning. Not worth it (yet):
- // args.push('-Dorg.gradle.parallel=true');
- return args;
- },
-
- // Makes the project buildable, minus the gradle wrapper.
- prepBuildFiles: function() {
- var projectPath = ROOT;
- // Update the version of build.gradle in each dependent library.
- var pluginBuildGradle = path.join(projectPath, 'cordova', 'lib', 'plugin-build.gradle');
- var propertiesObj = readProjectProperties();
- var subProjects = propertiesObj.libs;
- for (var i = 0; i < subProjects.length; ++i) {
- if (subProjects[i] !== 'CordovaLib') {
- shell.cp('-f', pluginBuildGradle, path.join(ROOT, subProjects[i], 'build.gradle'));
- }
- }
-
- var name = extractRealProjectNameFromManifest(ROOT);
- //Remove the proj.id/name- prefix from projects: https://issues.apache.org/jira/browse/CB-9149
- var settingsGradlePaths = subProjects.map(function(p){
- var realDir=p.replace(/[/\\]/g, ':');
- var libName=realDir.replace(name+'-','');
- var str='include ":'+libName+'"\n';
- if(realDir.indexOf(name+'-')!==-1)
- str+='project(":'+libName+'").projectDir = new File("'+p+'")\n';
- return str;
- });
-
- // Write the settings.gradle file.
- fs.writeFileSync(path.join(projectPath, 'settings.gradle'),
- '// GENERATED FILE - DO NOT EDIT\n' +
- 'include ":"\n' + settingsGradlePaths.join(''));
- // Update dependencies within build.gradle.
- var buildGradle = fs.readFileSync(path.join(projectPath, 'build.gradle'), 'utf8');
- var depsList = '';
- subProjects.forEach(function(p) {
- var libName=p.replace(/[/\\]/g, ':').replace(name+'-','');
- depsList += ' debugCompile project(path: "' + libName + '", configuration: "debug")\n';
- depsList += ' releaseCompile project(path: "' + libName + '", configuration: "release")\n';
- });
- // For why we do this mapping: https://issues.apache.org/jira/browse/CB-8390
- var SYSTEM_LIBRARY_MAPPINGS = [
- [/^\/?extras\/android\/support\/(.*)$/, 'com.android.support:support-$1:+'],
- [/^\/?google\/google_play_services\/libproject\/google-play-services_lib\/?$/, 'com.google.android.gms:play-services:+']
- ];
- propertiesObj.systemLibs.forEach(function(p) {
- var mavenRef;
- // It's already in gradle form if it has two ':'s
- if (/:.*:/.exec(p)) {
- mavenRef = p;
- } else {
- for (var i = 0; i < SYSTEM_LIBRARY_MAPPINGS.length; ++i) {
- var pair = SYSTEM_LIBRARY_MAPPINGS[i];
- if (pair[0].exec(p)) {
- mavenRef = p.replace(pair[0], pair[1]);
- break;
- }
- }
- if (!mavenRef) {
- throw new Error('Unsupported system library (does not work with gradle): ' + p);
- }
- }
- depsList += ' compile "' + mavenRef + '"\n';
- });
- buildGradle = buildGradle.replace(/(SUB-PROJECT DEPENDENCIES START)[\s\S]*(\/\/ SUB-PROJECT DEPENDENCIES END)/, '$1\n' + depsList + ' $2');
- var includeList = '';
- propertiesObj.gradleIncludes.forEach(function(includePath) {
- includeList += 'apply from: "' + includePath + '"\n';
- });
- buildGradle = buildGradle.replace(/(PLUGIN GRADLE EXTENSIONS START)[\s\S]*(\/\/ PLUGIN GRADLE EXTENSIONS END)/, '$1\n' + includeList + '$2');
- fs.writeFileSync(path.join(projectPath, 'build.gradle'), buildGradle);
- },
-
- prepEnv: function(opts) {
- var self = this;
- return check_reqs.check_gradle()
- .then(function() {
- return self.prepBuildFiles();
- }).then(function() {
- // Copy the gradle wrapper on each build so that:
- // A) we don't require the Android SDK at project creation time, and
- // B) we always use the SDK's latest version of it.
- var projectPath = ROOT;
- // check_reqs ensures that this is set.
- var sdkDir = process.env['ANDROID_HOME'];
- var wrapperDir = path.join(sdkDir, 'tools', 'templates', 'gradle', 'wrapper');
- if (process.platform == 'win32') {
- shell.rm('-f', path.join(projectPath, 'gradlew.bat'));
- shell.cp(path.join(wrapperDir, 'gradlew.bat'), projectPath);
- } else {
- shell.rm('-f', path.join(projectPath, 'gradlew'));
- shell.cp(path.join(wrapperDir, 'gradlew'), projectPath);
- }
- shell.rm('-rf', path.join(projectPath, 'gradle', 'wrapper'));
- shell.mkdir('-p', path.join(projectPath, 'gradle'));
- shell.cp('-r', path.join(wrapperDir, 'gradle', 'wrapper'), path.join(projectPath, 'gradle'));
-
- // If the gradle distribution URL is set, make sure it points to version we want.
- // 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 distributionUrl = 'distributionUrl=http\\://services.gradle.org/distributions/gradle-2.2.1-all.zip';
- var gradleWrapperPropertiesPath = path.join(projectPath, 'gradle', 'wrapper', 'gradle-wrapper.properties');
- shell.chmod('u+w', gradleWrapperPropertiesPath);
- shell.sed('-i', distributionUrlRegex, distributionUrl, gradleWrapperPropertiesPath);
-
- var propertiesFile = opts.buildType + SIGNING_PROPERTIES;
- var propertiesFilePath = path.join(ROOT, propertiesFile);
- if (opts.packageInfo) {
- fs.writeFileSync(propertiesFilePath, TEMPLATE + opts.packageInfo.toProperties());
- } else if (isAutoGenerated(propertiesFilePath)) {
- shell.rm('-f', propertiesFilePath);
- }
- });
- },
-
- /*
- * Builds the project with gradle.
- * Returns a promise.
- */
- build: function(opts) {
- var wrapper = path.join(ROOT, 'gradlew');
- var args = this.getArgs(opts.buildType == 'debug' ? 'debug' : 'release', opts);
- return Q().then(function() {
- console.log('Running: ' + wrapper + ' ' + args.join(' '));
- return spawn(wrapper, args);
- });
- },
-
- clean: function(opts) {
- var builder = this;
- var wrapper = path.join(ROOT, 'gradlew');
- var args = builder.getArgs('clean', opts);
- return Q().then(function() {
- console.log('Running: ' + wrapper + ' ' + args.join(' '));
- return spawn(wrapper, args);
- });
- },
-
- findOutputApks: function(build_type, arch) {
- var binDir = path.join(ROOT, 'build', 'outputs', 'apk');
- return findOutputApksHelper(binDir, build_type, arch);
- }
- },
-
- none: {
- prepEnv: function() {
- return Q();
- },
- build: function() {
- console.log('Skipping build...');
- return Q(null);
- },
- clean: function() {
- return Q();
- },
- findOutputApks: function(build_type, arch) {
- return sortFilesByDate(builders.ant.findOutputApks(build_type, arch).concat(builders.gradle.findOutputApks(build_type, arch)));
- }
+ if (options.argv.gradleArg) {
+ ret.extraArgs = ret.extraArgs.concat(options.argv.gradleArg);
}
-};
-module.exports.isBuildFlag = function(flag) {
- return /^--(debug|release|ant|gradle|nobuild|versionCode=|minSdkVersion=|gradleArg=|keystore=|alias=|password=|storePassword=|keystoreType=|buildConfig=)/.exec(flag);
-};
+ var packageArgs = {};
-function parseOpts(options, resolvedTarget) {
- // Backwards-compatibility: Allow a single string argument
- if (typeof options == 'string') options = [options];
+ if (options.argv.keystore)
+ packageArgs.keystore = path.relative(projectRoot, path.resolve(options.argv.keystore));
- var ret = {
- buildType: 'debug',
- buildMethod: process.env['ANDROID_BUILD'] || 'gradle',
- arch: null,
- extraArgs: []
- };
+ ['alias','storePassword','password','keystoreType'].forEach(function (flagName) {
+ if (options.argv[flagName])
+ packageArgs[flagName] = options.argv[flagName];
+ });
- var multiValueArgs = {
- 'versionCode': true,
- 'minSdkVersion': true,
- 'gradleArg': true,
- 'keystore' : true,
- 'alias' : true,
- 'password' : true,
- 'storePassword' : true,
- 'keystoreType' : true,
- 'buildConfig' : true
- };
- var packageArgs = {};
- var buildConfig;
- // Iterate through command line options
- for (var i=0; options && (i < options.length); ++i) {
- if (/^--/.exec(options[i])) {
- var keyValue = options[i].substring(2).split('=');
- var flagName = keyValue.shift();
- var flagValue = keyValue.join('=');
- if (multiValueArgs[flagName] && !flagValue) {
- flagValue = options[i + 1];
- ++i;
- }
- switch(flagName) {
- case 'debug':
- case 'release':
- ret.buildType = flagName;
- break;
- case 'ant':
- case 'gradle':
- ret.buildMethod = flagName;
- break;
- case 'device':
- case 'emulator':
- // Don't need to do anything special to when building for device vs emulator.
- // iOS uses this flag to switch on architecture.
- break;
- case 'prepenv' :
- ret.prepEnv = true;
- break;
- case 'nobuild' :
- ret.buildMethod = 'none';
- break;
- case 'versionCode':
- ret.extraArgs.push('-PcdvVersionCode=' + flagValue);
- break;
- case 'minSdkVersion':
- ret.extraArgs.push('-PcdvMinSdkVersion=' + flagValue);
- break;
- case 'gradleArg':
- ret.extraArgs.push(flagValue);
- break;
- case 'keystore':
- packageArgs.keystore = path.relative(ROOT, path.resolve(flagValue));
- break;
- case 'alias':
- case 'storePassword':
- case 'password':
- case 'keystoreType':
- packageArgs[flagName] = flagValue;
- break;
- case 'buildConfig':
- buildConfig = flagValue;
- break;
- default :
- console.warn('Build option --\'' + flagName + '\' not recognized (ignoring).');
- }
- } else {
- console.warn('Build option \'' + options[i] + '\' not recognized (ignoring).');
- }
- }
+ var buildConfig = options.buildConfig;
// If some values are not specified as command line arguments - use build config to supplement them.
// Command line arguemnts have precedence over build config.
@@ -497,16 +88,17 @@ function parseOpts(options, resolvedTarget) {
if (!fs.existsSync(buildConfig)) {
throw new Error('Specified build config file does not exist: ' + buildConfig);
}
- console.log('Reading build config file: '+ path.resolve(buildConfig));
- var config = JSON.parse(fs.readFileSync(buildConfig, 'utf8'));
+ events.emit('log', 'Reading build config file: '+ path.resolve(buildConfig));
+ var buildjson = fs.readFileSync(buildConfig, 'utf8');
+ var config = JSON.parse(buildjson.replace(/^\ufeff/, '')); // Remove BOM
if (config.android && config.android[ret.buildType]) {
var androidInfo = config.android[ret.buildType];
if(androidInfo.keystore && !packageArgs.keystore) {
- if(path.isAbsolute(androidInfo.keystore)) {
- packageArgs.keystore = androidInfo.keystore;
- } else {
- packageArgs.keystore = path.relative(ROOT, path.join(path.dirname(buildConfig), androidInfo.keystore));
+ if(androidInfo.keystore.substr(0,1) === '~') {
+ androidInfo.keystore = process.env.HOME + androidInfo.keystore.substr(1);
}
+ packageArgs.keystore = path.resolve(path.dirname(buildConfig), androidInfo.keystore);
+ events.emit('log', 'Reading the keystore from: ' + packageArgs.keystore);
}
['alias', 'storePassword', 'password','keystoreType'].forEach(function (key){
@@ -514,6 +106,7 @@ function parseOpts(options, resolvedTarget) {
});
}
}
+
if (packageArgs.keystore && packageArgs.alias) {
ret.packageInfo = new PackageInfo(packageArgs.keystore, packageArgs.alias, packageArgs.storePassword,
packageArgs.password, packageArgs.keystoreType);
@@ -521,10 +114,9 @@ function parseOpts(options, resolvedTarget) {
if(!ret.packageInfo) {
if(Object.keys(packageArgs).length > 0) {
- console.warn('\'keystore\' and \'alias\' need to be specified to generate a signed archive.');
+ events.emit('warn', '\'keystore\' and \'alias\' need to be specified to generate a signed archive.');
}
}
- ret.arch = resolvedTarget && resolvedTarget.arch;
return ret;
}
@@ -534,41 +126,39 @@ function parseOpts(options, resolvedTarget) {
* Returns a promise.
*/
module.exports.runClean = function(options) {
- var opts = parseOpts(options);
- var builder = builders[opts.buildMethod];
+ var opts = parseOpts(options, null, this.root);
+ var builder = builders.getBuilder(opts.buildMethod);
return builder.prepEnv(opts)
.then(function() {
return builder.clean(opts);
- }).then(function() {
- shell.rm('-rf', path.join(ROOT, 'out'));
-
- ['debug', 'release'].forEach(function(config) {
- var propertiesFilePath = path.join(ROOT, config + SIGNING_PROPERTIES);
- if(isAutoGenerated(propertiesFilePath)){
- shell.rm('-f', propertiesFilePath);
- }
- });
});
};
-/*
- * Builds the project with the specifed options
- * Returns a promise.
+/**
+ * Builds the project with the specifed options.
+ *
+ * @param {BuildOptions} options A set of options. See PlatformApi.build
+ * method documentation for reference.
+ * @param {Object} optResolvedTarget A deployment target. Used to pass
+ * target architecture from upstream 'run' call. TODO: remove this option in
+ * favor of setting buildOptions.archs field.
+ *
+ * @return {Promise<Object>} Promise, resolved with built packages
+ * information.
*/
module.exports.run = function(options, optResolvedTarget) {
- var opts = parseOpts(options, optResolvedTarget);
- var builder = builders[opts.buildMethod];
+ var opts = parseOpts(options, optResolvedTarget, this.root);
+ var builder = builders.getBuilder(opts.buildMethod);
return builder.prepEnv(opts)
.then(function() {
if (opts.prepEnv) {
- console.log('Build file successfully prepared.');
+ events.emit('verbose', 'Build file successfully prepared.');
return;
}
return builder.build(opts)
.then(function() {
var apkPaths = builder.findOutputApks(opts.buildType, opts.arch);
- console.log('Built the following apk(s):');
- console.log(' ' + apkPaths.join('\n '));
+ events.emit('log', 'Built the following apk(s): \n\t' + apkPaths.join('\n\t'));
return {
apkPaths: apkPaths,
buildType: opts.buildType,
@@ -578,46 +168,38 @@ module.exports.run = function(options, optResolvedTarget) {
});
};
-// Called by plugman after installing plugins, and by create script after creating project.
-module.exports.prepBuildFiles = function() {
- var builder = builders['gradle'];
- return builder.prepBuildFiles();
-};
-
/*
* Detects the architecture of a device/emulator
* Returns "arm" or "x86".
*/
module.exports.detectArchitecture = function(target) {
function helper() {
- return exec('adb -s ' + target + ' shell cat /proc/cpuinfo', os.tmpdir())
+ return Adb.shell(target, 'cat /proc/cpuinfo')
.then(function(output) {
- if (/intel/i.exec(output)) {
- return 'x86';
- }
- return 'arm';
+ return /intel/i.exec(output) ? 'x86' : 'arm';
});
}
// It sometimes happens (at least on OS X), that this command will hang forever.
// To fix it, either unplug & replug device, or restart adb server.
- return helper().timeout(1000, 'Device communication timed out. Try unplugging & replugging the device.')
+ return helper()
+ .timeout(1000, new CordovaError('Device communication timed out. Try unplugging & replugging the device.'))
.then(null, function(err) {
if (/timed out/.exec('' + err)) {
// adb kill-server doesn't seem to do the trick.
// Could probably find a x-platform version of killall, but I'm not actually
// sure that this scenario even happens on non-OSX machines.
- return exec('killall adb')
+ events.emit('verbose', 'adb timed out while detecting device/emulator architecture. Killing adb and trying again.');
+ return spawn('killall', ['adb'])
.then(function() {
- console.log('adb seems hung. retrying.');
return helper()
.then(null, function() {
// The double kill is sadly often necessary, at least on mac.
- console.log('Now device not found... restarting adb again.');
- return exec('killall adb')
+ events.emit('warn', 'adb timed out a second time while detecting device/emulator architecture. Killing adb and trying again.');
+ return spawn('killall', ['adb'])
.then(function() {
return helper()
.then(null, function() {
- return Q.reject('USB is flakey. Try unplugging & replugging the device.');
+ return Q.reject(new CordovaError('adb timed out a third time while detecting device/emulator architecture. Try unplugging & replugging the device.'));
});
});
});
@@ -632,16 +214,18 @@ module.exports.detectArchitecture = function(target) {
module.exports.findBestApkForArchitecture = function(buildResults, arch) {
var paths = buildResults.apkPaths.filter(function(p) {
+ var apkName = path.basename(p);
if (buildResults.buildType == 'debug') {
- return /-debug/.exec(p);
+ return /-debug/.exec(apkName);
}
- return !/-debug/.exec(p);
+ return !/-debug/.exec(apkName);
});
var archPattern = new RegExp('-' + arch);
var hasArchPattern = /-x86|-arm/;
for (var i = 0; i < paths.length; ++i) {
- if (hasArchPattern.exec(paths[i])) {
- if (archPattern.exec(paths[i])) {
+ var apkName = path.basename(paths[i]);
+ if (hasArchPattern.exec(apkName)) {
+ if (archPattern.exec(apkName)) {
return paths[i];
}
} else {
@@ -695,7 +279,7 @@ PackageInfo.prototype = {
};
module.exports.help = function() {
- console.log('Usage: ' + path.relative(process.cwd(), path.join(ROOT, 'cordova', 'build')) + ' [flags] [Signed APK flags]');
+ console.log('Usage: ' + path.relative(process.cwd(), path.join('../build')) + ' [flags] [Signed APK flags]');
console.log('Flags:');
console.log(' \'--debug\': will build project in debug mode (default)');
console.log(' \'--release\': will build project for release');