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}