CB-3445 Add gradle support clean command (plus some code cleanup)

* Don't run ant clean for gradle ever
* Don't set sdk.dir since ANDROID_HOME is not always set
* Don't export builders
This commit is contained in:
Andrew Grieve 2014-08-18 16:19:40 -04:00
parent c91b272648
commit d56ea25816
4 changed files with 104 additions and 98 deletions

View File

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

View File

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

View File

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

View File

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