arnaucube
arnaucube/commonroutesServerPublic Self-hosted repository
commonroutesServer/www/platforms/android/cordova/lib/builders/AntBuilder.js
www/platforms/android/cordova/lib/builders/AntBuilder.jsRaw
  1/*
  2       Licensed to the Apache Software Foundation (ASF) under one
  3       or more contributor license agreements.  See the NOTICE file
  4       distributed with this work for additional information
  5       regarding copyright ownership.  The ASF licenses this file
  6       to you under the Apache License, Version 2.0 (the
  7       "License"); you may not use this file except in compliance
  8       with the License.  You may obtain a copy of the License at
  9
 10         http://www.apache.org/licenses/LICENSE-2.0
 11
 12       Unless required by applicable law or agreed to in writing,
 13       software distributed under the License is distributed on an
 14       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 15       KIND, either express or implied.  See the License for the
 16       specific language governing permissions and limitations
 17       under the License.
 18*/
 19
 20var Q = require('q');
 21var fs = require('fs');
 22var path = require('path');
 23var util = require('util');
 24var shell = require('shelljs');
 25var spawn = require('cordova-common').superspawn.spawn;
 26var CordovaError = require('cordova-common').CordovaError;
 27var check_reqs = require('../check_reqs');
 28
 29var SIGNING_PROPERTIES = '-signing.properties';
 30var MARKER = 'YOUR CHANGES WILL BE ERASED!';
 31var TEMPLATE =
 32    '# This file is automatically generated.\n' +
 33    '# Do not modify this file -- ' + MARKER + '\n';
 34
 35var GenericBuilder = require('./GenericBuilder');
 36
 37function AntBuilder (projectRoot) {
 38    GenericBuilder.call(this, projectRoot);
 39
 40    this.binDirs = {ant: this.binDirs.ant};
 41}
 42
 43util.inherits(AntBuilder, GenericBuilder);
 44
 45AntBuilder.prototype.getArgs = function(cmd, opts) {
 46    var args = [cmd, '-f', path.join(this.root, 'build.xml')];
 47    // custom_rules.xml is required for incremental builds.
 48    if (hasCustomRules(this.root)) {
 49        args.push('-Dout.dir=ant-build', '-Dgen.absolute.dir=ant-gen');
 50    }
 51    if(opts.packageInfo) {
 52        args.push('-propertyfile=' + path.join(this.root, opts.buildType + SIGNING_PROPERTIES));
 53    }
 54    return args;
 55};
 56
 57AntBuilder.prototype.prepEnv = function(opts) {
 58    var self = this;
 59    return check_reqs.check_ant()
 60    .then(function() {
 61        // Copy in build.xml on each build so that:
 62        // A) we don't require the Android SDK at project creation time, and
 63        // B) we always use the SDK's latest version of it.
 64        /*jshint -W069 */
 65        var sdkDir = process.env['ANDROID_HOME'];
 66        /*jshint +W069 */
 67        var buildTemplate = fs.readFileSync(path.join(sdkDir, 'tools', 'lib', 'build.template'), 'utf8');
 68        function writeBuildXml(projectPath) {
 69            var newData = buildTemplate.replace('PROJECT_NAME', self.extractRealProjectNameFromManifest());
 70            fs.writeFileSync(path.join(projectPath, 'build.xml'), newData);
 71            if (!fs.existsSync(path.join(projectPath, 'local.properties'))) {
 72                fs.writeFileSync(path.join(projectPath, 'local.properties'), TEMPLATE);
 73            }
 74        }
 75        writeBuildXml(self.root);
 76        var propertiesObj = self.readProjectProperties();
 77        var subProjects = propertiesObj.libs;
 78        for (var i = 0; i < subProjects.length; ++i) {
 79            writeBuildXml(path.join(self.root, subProjects[i]));
 80        }
 81        if (propertiesObj.systemLibs.length > 0) {
 82            throw new CordovaError('Project contains at least one plugin that requires a system library. This is not supported with ANT. Use gradle instead.');
 83        }
 84
 85        var propertiesFile = opts.buildType + SIGNING_PROPERTIES;
 86        var propertiesFilePath = path.join(self.root, propertiesFile);
 87        if (opts.packageInfo) {
 88            fs.writeFileSync(propertiesFilePath, TEMPLATE + opts.packageInfo.toProperties());
 89        } else if(isAutoGenerated(propertiesFilePath)) {
 90            shell.rm('-f', propertiesFilePath);
 91        }
 92    });
 93};
 94
 95/*
 96 * Builds the project with ant.
 97 * Returns a promise.
 98 */
 99AntBuilder.prototype.build = function(opts) {
100    // Without our custom_rules.xml, we need to clean before building.
101    var ret = Q();
102    if (!hasCustomRules(this.root)) {
103        // clean will call check_ant() for us.
104        ret = this.clean(opts);
105    }
106
107    var args = this.getArgs(opts.buildType == 'debug' ? 'debug' : 'release', opts);
108    return check_reqs.check_ant()
109    .then(function() {
110        return spawn('ant', args, {stdio: 'pipe'});
111    }).progress(function (stdio){
112        if (stdio.stderr) {
113            process.stderr.write(stdio.stderr);
114        } else {
115            process.stdout.write(stdio.stdout);
116        }
117    }).catch(function (error) {
118        if (error.toString().indexOf('Unable to resolve project target') >= 0) {
119            return check_reqs.check_android_target(error).then(function() {
120                // If due to some odd reason - check_android_target succeeds
121                // we should still fail here.
122                return Q.reject(error);
123            });
124        }
125        return Q.reject(error);
126    });
127};
128
129AntBuilder.prototype.clean = function(opts) {
130    var args = this.getArgs('clean', opts);
131    var self = this;
132    return check_reqs.check_ant()
133    .then(function() {
134        return spawn('ant', args, {stdio: 'inherit'});
135    })
136    .then(function () {
137        shell.rm('-rf', path.join(self.root, 'out'));
138
139        ['debug', 'release'].forEach(function(config) {
140            var propertiesFilePath = path.join(self.root, config + SIGNING_PROPERTIES);
141            if(isAutoGenerated(propertiesFilePath)){
142                shell.rm('-f', propertiesFilePath);
143            }
144        });
145    });
146};
147
148module.exports = AntBuilder;
149
150function hasCustomRules(projectRoot) {
151    return fs.existsSync(path.join(projectRoot, 'custom_rules.xml'));
152}
153
154function isAutoGenerated(file) {
155    return fs.existsSync(file) && fs.readFileSync(file, 'utf8').indexOf(MARKER) > 0;
156}