commonroutesServer/www/platforms/android/cordova/lib/builders/GenericBuilder.js
www/platforms/android/cordova/lib/builders/GenericBuilder.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 shell = require('shelljs');
24var events = require('cordova-common').events;
25var CordovaError = require('cordova-common').CordovaError;
26
27function GenericBuilder (projectDir) {
28 this.root = projectDir || path.resolve(__dirname, '../../..');
29 this.binDirs = {
30 ant: path.join(this.root, hasCustomRules(this.root) ? 'ant-build' : 'bin'),
31 gradle: path.join(this.root, 'build', 'outputs', 'apk')
32 };
33}
34
35function hasCustomRules(projectRoot) {
36 return fs.existsSync(path.join(projectRoot, 'custom_rules.xml'));
37}
38
39GenericBuilder.prototype.prepEnv = function() {
40 return Q();
41};
42
43GenericBuilder.prototype.build = function() {
44 events.emit('log', 'Skipping build...');
45 return Q(null);
46};
47
48GenericBuilder.prototype.clean = function() {
49 return Q();
50};
51
52GenericBuilder.prototype.findOutputApks = function(build_type, arch) {
53 var self = this;
54 return Object.keys(this.binDirs)
55 .reduce(function (result, builderName) {
56 var binDir = self.binDirs[builderName];
57 return result.concat(findOutputApksHelper(binDir, build_type, builderName === 'ant' ? null : arch));
58 }, [])
59 .sort(apkSorter);
60};
61
62GenericBuilder.prototype.readProjectProperties = function () {
63 function findAllUniq(data, r) {
64 var s = {};
65 var m;
66 while ((m = r.exec(data))) {
67 s[m[1]] = 1;
68 }
69 return Object.keys(s);
70 }
71
72 var data = fs.readFileSync(path.join(this.root, 'project.properties'), 'utf8');
73 return {
74 libs: findAllUniq(data, /^\s*android\.library\.reference\.\d+=(.*)(?:\s|$)/mg),
75 gradleIncludes: findAllUniq(data, /^\s*cordova\.gradle\.include\.\d+=(.*)(?:\s|$)/mg),
76 systemLibs: findAllUniq(data, /^\s*cordova\.system\.library\.\d+=(.*)(?:\s|$)/mg)
77 };
78};
79
80GenericBuilder.prototype.extractRealProjectNameFromManifest = function () {
81 var manifestPath = path.join(this.root, 'AndroidManifest.xml');
82 var manifestData = fs.readFileSync(manifestPath, 'utf8');
83 var m = /<manifest[\s\S]*?package\s*=\s*"(.*?)"/i.exec(manifestData);
84 if (!m) {
85 throw new CordovaError('Could not find package name in ' + manifestPath);
86 }
87
88 var packageName=m[1];
89 var lastDotIndex = packageName.lastIndexOf('.');
90 return packageName.substring(lastDotIndex + 1);
91};
92
93module.exports = GenericBuilder;
94
95function apkSorter(fileA, fileB) {
96 // De-prioritize unsigned builds
97 var unsignedRE = /-unsigned/;
98 if (unsignedRE.exec(fileA)) {
99 return 1;
100 } else if (unsignedRE.exec(fileB)) {
101 return -1;
102 }
103
104 var timeDiff = fs.statSync(fileA).mtime - fs.statSync(fileB).mtime;
105 return timeDiff === 0 ? fileA.length - fileB.length : timeDiff;
106}
107
108function findOutputApksHelper(dir, build_type, arch) {
109 var shellSilent = shell.config.silent;
110 shell.config.silent = true;
111
112 var ret = shell.ls(path.join(dir, '*.apk'))
113 .filter(function(candidate) {
114 var apkName = path.basename(candidate);
115 // Need to choose between release and debug .apk.
116 if (build_type === 'debug') {
117 return /-debug/.exec(apkName) && !/-unaligned|-unsigned/.exec(apkName);
118 }
119 if (build_type === 'release') {
120 return /-release/.exec(apkName) && !/-unaligned/.exec(apkName);
121 }
122 return true;
123 })
124 .sort(apkSorter);
125
126 shellSilent = shellSilent;
127
128 if (ret.length === 0) {
129 return ret;
130 }
131 // Assume arch-specific build if newest apk has -x86 or -arm.
132 var archSpecific = !!/-x86|-arm/.exec(path.basename(ret[0]));
133 // And show only arch-specific ones (or non-arch-specific)
134 ret = ret.filter(function(p) {
135 /*jshint -W018 */
136 return !!/-x86|-arm/.exec(path.basename(p)) == archSpecific;
137 /*jshint +W018 */
138 });
139
140 if (archSpecific && ret.length > 1 && arch) {
141 ret = ret.filter(function(p) {
142 return path.basename(p).indexOf('-' + arch) != -1;
143 });
144 }
145
146 return ret;
147}