diff --git a/bin/templates/cordova/build b/bin/templates/cordova/build index 367bf7d2..3c3aee4e 100755 --- a/bin/templates/cordova/build +++ b/bin/templates/cordova/build @@ -33,7 +33,7 @@ if(args[2] == '--help' || build.help(); } else { reqs.run().done(function() { - return build.run.call(build.run, args.slice(2)); + return build.run(args.slice(2)); }, function(err) { console.error(err); process.exit(2); diff --git a/bin/templates/cordova/clean b/bin/templates/cordova/clean index 4e0808bf..d9a7d490 100755 --- a/bin/templates/cordova/clean +++ b/bin/templates/cordova/clean @@ -19,18 +19,26 @@ under the License. */ -var clean = require('./lib/clean'), +var build = require('./lib/build'), reqs = require('./lib/check_reqs'), args = process.argv; +var path = require('path'); -// Usage support for when args are given -if(args.length > 2) { - clean.help(); +// Support basic help commands +if(args[2] == '--help' || + args[2] == '/?' || + args[2] == '-h' || + args[2] == 'help' || + args[2] == '-help' || + args[2] == '/help') { + console.log('Usage: ' + path.relative(process.cwd(), process.argv[1])); + console.log('Cleans the project directory.'); + process.exit(0); } else { reqs.run().done(function() { - return clean.run(); + return build.runClean(args.slice(2)); }, function(err) { - console.error('ERROR: ' + err); + console.error(err); process.exit(2); }); } diff --git a/bin/templates/cordova/lib/build.js b/bin/templates/cordova/lib/build.js index 80e2282b..071990f6 100644 --- a/bin/templates/cordova/lib/build.js +++ b/bin/templates/cordova/lib/build.js @@ -69,7 +69,7 @@ function copyGradleWrapper() { shell.cp('-r', path.join(wrapperDir, 'gradle', 'wrapper'), path.join(projectPath, 'gradle')); } -module.exports.builders = { +var builders = { ant: { getArgs: function(cmd) { var args = [cmd, '-f', path.join(ROOT, 'build.xml')]; @@ -77,29 +77,45 @@ module.exports.builders = { if (hasCustomRules()) { args.push('-Dout.dir=ant-build', '-Dgen.absolute.dir=ant-gen'); } - try { - // Specify sdk dir in case local properties are missing - args.push('-Dsdk.dir='+path.join(which.sync('android'), '../..')); - } catch(e) { - // Can't find android; don't push arg: assume all is okay - } return args; }, + prepEnv: function() { + return check_reqs.check_ant() + .then(function() { + }); + }, + /* * Builds the project with ant. * Returns a promise. */ build: function(build_type) { + // 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(); + } + var builder = this; - var args = builder.getArgs(build_type == "debug" ? 'debug' : 'release'); - return Q().then(function() { + var args = this.getArgs(build_type == 'debug' ? 'debug' : 'release'); + return check_reqs.check_ant() + .then(function() { return spawn('ant', args); }).then(function() { return builder.getOutputFiles(); }); }, + clean: function() { + var args = this.getArgs('clean'); + return check_reqs.check_ant() + .then(function() { + return spawn('ant', args); + }); + }, + // Find the recently-generated output APK files // Ant only generates one output file; return it. getOutputFiles: function() { @@ -139,6 +155,10 @@ module.exports.builders = { return args; }, + prepEnv: function() { + return Q(); + }, + /* * Builds the project with gradle. * Returns a promise. @@ -155,6 +175,18 @@ module.exports.builders = { }); }, + clean: function() { + var builder = this; + var wrapper = path.join(ROOT, 'gradlew'); + var args = builder.getArgs('clean'); + copyGradleWrapper(); + return Q().then(function() { + return spawn(wrapper, args); + }).then(function() { + return builder.getOutputFiles(build_type); + }); + }, + // Find the recently-generated output APK files // Gradle can generate multiple output files; return all of them. getOutputFiles: function(build_type) { @@ -171,18 +203,31 @@ module.exports.builders = { }); return candidates; } + }, + + none: { + prepEnv: function() { + return Q(); + }, + build: function() { + console.log('Skipping build...'); + return Q(); + }, + clean: function() { + return Q(); + }, } }; -/* - * Builds the project with the specifed options - * Returns a promise. - */ -module.exports.run = function(options) { - +function parseOpts(options) { // Backwards-compatibility: Allow a single string argument if (typeof options == "string") options = [options]; + var ret = { + buildType: 'debug', + buildMethod: process.env['ANDROID_BUILD'] || 'ant' + }; + // Iterate through command line options for (var i=0; options && (i < options.length); ++i) { if (options[i].substring && options[i].substring(0,2) == "--") { @@ -190,21 +235,15 @@ module.exports.run = function(options) { switch(option) { case 'debug': case 'release': - if (build_type) { - return Q.reject('Multiple build types (' + build_type + ' and ' + option + ') specified.'); - } - build_type = option; + ret.buildType = option; break; case 'ant': case 'gradle': - if (build_method) { - return Q.reject('Multiple build methods (' + build_method + ' and ' + option + ') specified.'); - } - build_method = option; + ret.buildMethod = option; break; case 'nobuild' : - console.log('Skipping build...'); - return Q(); + ret.buildMethod = 'none'; + break; default : return Q.reject('Build option \'' + options[i] + '\' not recognized.'); } @@ -212,34 +251,36 @@ module.exports.run = function(options) { return Q.reject('Build option \'' + options[i] + '\' not recognized.'); } } - // Defaults - build_type = build_type || "debug"; - build_method = build_method || process.env.ANDROID_BUILD || "ant"; + return ret; +} - // Get the builder - var builder = module.exports.builders[build_method]; +/* + * Builds the project with the specifed options + * Returns a promise. + */ +module.exports.runClean = function(options) { + var opts = parseOpts(options); + var builder = builders[opts.buildMethod]; + return builder.prepEnv(opts.buildType) + .then(function() { + return builder.clean(); + }); +}; - // Without our custom_rules.xml, we need to clean before building. - var ret; - if (!hasCustomRules()) { - // clean will call check_ant() for us. - ret = require('./clean').run(); - } else { - ret = check_reqs.check_ant(); - } +/* + * Builds the project with the specifed options + * Returns a promise. + */ +module.exports.run = function(options) { + var opts = parseOpts(options); - // Return a promise for the actual build - return ret.then(function() { - return builder.build.call(builder, build_type); + var builder = builders[opts.buildMethod]; + return builder.prepEnv(opts.buildType) + .then(function() { + return builder.build(opts.buildType); }).then(function(apkFiles) { var outputDir = path.join(ROOT, 'out'); - try { - fs.mkdirSync(outputDir); - } catch (e) { - if (e.code != "EEXIST") { - throw e; - } - } + shell.mkdir('-p', outputDir); for (var i=0; i < apkFiles.length; ++i) { shell.cp('-f', apkFiles[i], path.join(outputDir, path.basename(apkFiles[i]))); } diff --git a/bin/templates/cordova/lib/clean.js b/bin/templates/cordova/lib/clean.js deleted file mode 100644 index f2158290..00000000 --- a/bin/templates/cordova/lib/clean.js +++ /dev/null @@ -1,43 +0,0 @@ -#!/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. -*/ - -var build = require('./build'), - spawn = require('./spawn'), - path = require('path'); -var check_reqs = require('./check_reqs'); - -/* - * Cleans the project using ant - * Returns a promise. - */ -module.exports.run = function() { - var args = build.getAntArgs('clean'); - return check_reqs.check_ant() - .then(function() { - return spawn('ant', args); - }); -} - -module.exports.help = function() { - console.log('Usage: ' + path.relative(process.cwd(), process.argv[1])); - console.log('Cleans the project directory.'); - process.exit(0); -}