2013-08-13 08:07:23 +08:00
#!/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 shell = require ( 'shelljs' ) ,
2014-01-16 00:41:03 +08:00
spawn = require ( './spawn' ) ,
Q = require ( 'q' ) ,
2013-08-13 08:07:23 +08:00
path = require ( 'path' ) ,
fs = require ( 'fs' ) ,
2014-10-27 22:14:35 +08:00
os = require ( 'os' ) ,
2013-08-13 08:07:23 +08:00
ROOT = path . join ( _ _dirname , '..' , '..' ) ;
2014-08-16 01:58:53 +08:00
var check _reqs = require ( './check_reqs' ) ;
2014-09-16 02:23:26 +08:00
var exec = require ( './exec' ) ;
2013-08-13 08:07:23 +08:00
2014-08-19 11:21:26 +08:00
var LOCAL _PROPERTIES _TEMPLATE =
'# This file is automatically generated.\n' +
'# Do not modify this file -- YOUR CHANGES WILL BE ERASED!\n' ;
2014-08-18 21:44:00 +08:00
2014-09-23 02:23:30 +08:00
function findApks ( directory ) {
var ret = [ ] ;
2014-08-18 21:44:00 +08:00
if ( fs . existsSync ( directory ) ) {
2014-09-23 02:23:30 +08:00
fs . readdirSync ( directory ) . forEach ( function ( p ) {
if ( path . extname ( p ) == '.apk' ) {
ret . push ( path . join ( directory , p ) ) ;
2014-09-17 02:59:43 +08:00
}
2014-09-23 02:23:30 +08:00
} ) ;
2014-08-18 21:44:00 +08:00
}
2014-09-23 02:23:30 +08:00
return ret ;
}
function sortFilesByDate ( files ) {
return files . map ( function ( p ) {
return { p : p , t : fs . statSync ( p ) . mtime } ;
} ) . sort ( function ( a , b ) {
var timeDiff = b . t - a . t ;
return timeDiff === 0 ? a . p . length - b . p . length : timeDiff ;
} ) . map ( function ( p ) { return p . p ; } ) ;
}
2014-09-25 04:07:31 +08:00
function findOutputApksHelper ( dir , build _type , arch ) {
2014-09-23 02:23:30 +08:00
var ret = findApks ( dir ) . filter ( function ( candidate ) {
// Need to choose between release and debug .apk.
if ( build _type === 'debug' ) {
return /-debug/ . exec ( candidate ) && ! /-unaligned|-unsigned/ . exec ( candidate ) ;
}
if ( build _type === 'release' ) {
return /-release/ . exec ( candidate ) && ! /-unaligned/ . exec ( candidate ) ;
}
return true ;
} ) ;
ret = sortFilesByDate ( ret ) ;
if ( ret . length === 0 ) {
return ret ;
}
2015-01-20 10:51:57 +08:00
// Assume arch-specific build if newest api has -x86 or -arm.
2014-09-23 02:23:30 +08:00
var archSpecific = ! ! /-x86|-arm/ . exec ( ret [ 0 ] ) ;
2015-01-20 10:51:57 +08:00
// And show only arch-specific ones (or non-arch-specific)
2014-09-25 04:07:31 +08:00
ret = ret . filter ( function ( p ) {
2014-09-23 02:23:30 +08:00
return ! ! /-x86|-arm/ . exec ( p ) == archSpecific ;
} ) ;
2015-01-20 10:51:57 +08:00
if ( arch && ret . length > 1 ) {
2014-09-25 04:07:31 +08:00
ret = ret . filter ( function ( p ) {
return p . indexOf ( '-' + arch ) != - 1 ;
} ) ;
}
return ret ;
2014-08-18 21:44:00 +08:00
}
2014-01-22 04:09:15 +08:00
function hasCustomRules ( ) {
return fs . existsSync ( path . join ( ROOT , 'custom_rules.xml' ) ) ;
}
2014-08-18 21:44:00 +08:00
2014-08-19 11:21:26 +08:00
function extractProjectNameFromManifest ( projectPath ) {
var manifestPath = path . join ( projectPath , 'AndroidManifest.xml' ) ;
var manifestData = fs . readFileSync ( manifestPath , 'utf8' ) ;
var m = /<activity[\s\S]*?android:name\s*=\s*"(.*?)"/i . exec ( manifestData ) ;
if ( ! m ) {
throw new Error ( 'Could not find activity name in ' + manifestPath ) ;
}
return m [ 1 ] ;
}
function extractSubProjectPaths ( ) {
var data = fs . readFileSync ( path . join ( ROOT , 'project.properties' ) , 'utf8' ) ;
var ret = { } ;
var r = /^\s*android\.library\.reference\.\d+=(.*)(?:\s|$)/mg
var m ;
while ( m = r . exec ( data ) ) {
ret [ m [ 1 ] ] = 1 ;
2014-08-19 02:51:10 +08:00
}
2014-08-19 11:21:26 +08:00
return Object . keys ( ret ) ;
2014-08-19 02:51:10 +08:00
}
2014-08-19 04:19:40 +08:00
var builders = {
2014-08-18 21:44:00 +08:00
ant : {
getArgs : function ( cmd ) {
var args = [ cmd , '-f' , path . join ( ROOT , 'build.xml' ) ] ;
// custom_rules.xml is required for incremental builds.
if ( hasCustomRules ( ) ) {
args . push ( '-Dout.dir=ant-build' , '-Dgen.absolute.dir=ant-gen' ) ;
}
return args ;
} ,
2014-08-19 04:19:40 +08:00
prepEnv : function ( ) {
return check _reqs . check _ant ( )
. then ( function ( ) {
2014-08-19 11:21:26 +08:00
// Copy in build.xml on each build so that:
// A) we don't require the Android SDK at project creation time, and
// B) we always use the SDK's latest version of it.
var sdkDir = process . env [ 'ANDROID_HOME' ] ;
var buildTemplate = fs . readFileSync ( path . join ( sdkDir , 'tools' , 'lib' , 'build.template' ) , 'utf8' ) ;
function writeBuildXml ( projectPath ) {
var newData = buildTemplate . replace ( 'PROJECT_NAME' , extractProjectNameFromManifest ( ROOT ) ) ;
fs . writeFileSync ( path . join ( projectPath , 'build.xml' ) , newData ) ;
if ( ! fs . existsSync ( path . join ( projectPath , 'local.properties' ) ) ) {
fs . writeFileSync ( path . join ( projectPath , 'local.properties' ) , LOCAL _PROPERTIES _TEMPLATE ) ;
}
}
var subProjects = extractSubProjectPaths ( ) ;
writeBuildXml ( ROOT ) ;
for ( var i = 0 ; i < subProjects . length ; ++ i ) {
writeBuildXml ( path . join ( ROOT , subProjects [ i ] ) ) ;
}
2014-08-19 04:19:40 +08:00
} ) ;
} ,
2014-08-18 21:44:00 +08:00
/ *
* Builds the project with ant .
* Returns a promise .
* /
build : function ( build _type ) {
2014-08-19 04:19:40 +08:00
// 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 ( ) ;
}
2014-08-18 21:44:00 +08:00
var builder = this ;
2014-08-19 04:19:40 +08:00
var args = this . getArgs ( build _type == 'debug' ? 'debug' : 'release' ) ;
return check _reqs . check _ant ( )
. then ( function ( ) {
2014-08-18 21:44:00 +08:00
return spawn ( 'ant' , args ) ;
} ) ;
} ,
2014-08-19 04:19:40 +08:00
clean : function ( ) {
var args = this . getArgs ( 'clean' ) ;
return check _reqs . check _ant ( )
. then ( function ( ) {
return spawn ( 'ant' , args ) ;
} ) ;
} ,
2014-09-23 02:23:30 +08:00
findOutputApks : function ( build _type ) {
var binDir = path . join ( ROOT , hasCustomRules ( ) ? 'ant-build' : 'bin' ) ;
2014-09-25 04:07:31 +08:00
return findOutputApksHelper ( binDir , build _type , null ) ;
2014-08-18 21:44:00 +08:00
}
} ,
gradle : {
2015-01-07 04:56:09 +08:00
getArgs : function ( cmd , arch , extraArgs ) {
2015-01-20 10:56:46 +08:00
if ( cmd == 'release' ) {
cmd = 'cdvBuildRelease' ;
2014-09-25 04:07:31 +08:00
} else if ( cmd == 'debug' ) {
2015-01-20 10:56:46 +08:00
cmd = 'cdvBuildDebug' ;
2014-09-17 02:13:49 +08:00
}
2014-08-18 21:44:00 +08:00
var args = [ cmd , '-b' , path . join ( ROOT , 'build.gradle' ) ] ;
2015-01-20 10:56:46 +08:00
if ( arch ) {
args . push ( '-PcdvBuildArch=' + arch ) ;
}
2014-08-19 02:16:27 +08:00
// 10 seconds -> 6 seconds
args . push ( '-Dorg.gradle.daemon=true' ) ;
2015-01-07 04:56:09 +08:00
args . push . apply ( args , extraArgs ) ;
2014-08-19 02:16:27 +08:00
// Shaves another 100ms, but produces a "try at own risk" warning. Not worth it (yet):
// args.push('-Dorg.gradle.parallel=true');
2014-08-18 21:44:00 +08:00
return args ;
} ,
2014-08-19 04:19:40 +08:00
prepEnv : function ( ) {
2014-08-19 11:21:26 +08:00
return check _reqs . check _gradle ( )
. then ( function ( ) {
// Copy the gradle wrapper on each build so that:
// A) we don't require the Android SDK at project creation time, and
// B) we always use the SDK's latest version of it.
var projectPath = ROOT ;
// check_reqs ensures that this is set.
var sdkDir = process . env [ 'ANDROID_HOME' ] ;
var wrapperDir = path . join ( sdkDir , 'tools' , 'templates' , 'gradle' , 'wrapper' ) ;
if ( process . platform == 'win32' ) {
shell . cp ( '-f' , path . join ( wrapperDir , 'gradlew.bat' ) , projectPath ) ;
} else {
shell . cp ( '-f' , path . join ( wrapperDir , 'gradlew' ) , projectPath ) ;
}
shell . rm ( '-rf' , path . join ( projectPath , 'gradle' , 'wrapper' ) ) ;
shell . mkdir ( '-p' , path . join ( projectPath , 'gradle' ) ) ;
shell . cp ( '-r' , path . join ( wrapperDir , 'gradle' , 'wrapper' ) , path . join ( projectPath , 'gradle' ) ) ;
2014-09-23 09:35:39 +08:00
2014-12-23 00:37:06 +08:00
// If the gradle distribution URL is set, make sure it points to version we want.
2014-09-23 04:04:24 +08:00
// If it's not set, do nothing, assuming that we're using a future version of gradle that we don't want to mess with.
2014-12-10 01:57:29 +08:00
// For some reason, using ^ and $ don't work. This does the job, though.
var distributionUrlRegex = /distributionUrl.*zip/ ;
2014-12-23 00:37:06 +08:00
var distributionUrl = 'distributionUrl=http\\://services.gradle.org/distributions/gradle-2.2.1-all.zip' ;
2014-09-23 04:04:24 +08:00
var gradleWrapperPropertiesPath = path . join ( projectPath , 'gradle' , 'wrapper' , 'gradle-wrapper.properties' ) ;
shell . sed ( '-i' , distributionUrlRegex , distributionUrl , gradleWrapperPropertiesPath ) ;
2014-09-23 09:35:39 +08:00
// Update the version of build.gradle in each dependent library.
var pluginBuildGradle = path . join ( projectPath , 'cordova' , 'lib' , 'plugin-build.gradle' ) ;
var subProjects = extractSubProjectPaths ( ) ;
for ( var i = 0 ; i < subProjects . length ; ++ i ) {
2014-12-31 11:56:43 +08:00
if ( subProjects [ i ] !== 'CordovaLib' ) {
shell . cp ( '-f' , pluginBuildGradle , path . join ( ROOT , subProjects [ i ] , 'build.gradle' ) ) ;
}
2014-09-23 09:35:39 +08:00
}
2014-09-24 09:03:00 +08:00
var subProjectsAsGradlePaths = subProjects . map ( function ( p ) { return ':' + p . replace ( /[/\\]/g , ':' ) } ) ;
// Write the settings.gradle file.
fs . writeFileSync ( path . join ( projectPath , 'settings.gradle' ) ,
'// GENERATED FILE - DO NOT EDIT\n' +
'include ":"\n' +
'include "' + subProjectsAsGradlePaths . join ( '"\ninclude "' ) + '"\n' ) ;
// Update dependencies within build.gradle.
var buildGradle = fs . readFileSync ( path . join ( projectPath , 'build.gradle' ) , 'utf8' ) ;
var depsList = '' ;
subProjectsAsGradlePaths . forEach ( function ( p ) {
depsList += ' debugCompile project(path: "' + p + '", configuration: "debug")\n' ;
depsList += ' releaseCompile project(path: "' + p + '", configuration: "release")\n' ;
} ) ;
buildGradle = buildGradle . replace ( /(SUB-PROJECT DEPENDENCIES START)[\s\S]*(\/\/ SUB-PROJECT DEPENDENCIES END)/ , '$1\n' + depsList + ' $2' ) ;
fs . writeFileSync ( path . join ( projectPath , 'build.gradle' ) , buildGradle ) ;
2014-08-19 11:21:26 +08:00
} ) ;
2014-08-19 04:19:40 +08:00
} ,
2014-08-18 21:44:00 +08:00
/ *
* Builds the project with gradle .
* Returns a promise .
* /
2015-01-07 04:56:09 +08:00
build : function ( build _type , arch , extraArgs ) {
2014-08-18 21:44:00 +08:00
var builder = this ;
var wrapper = path . join ( ROOT , 'gradlew' ) ;
2015-01-07 04:56:09 +08:00
var args = this . getArgs ( build _type == 'debug' ? 'debug' : 'release' , arch , extraArgs ) ;
2014-08-18 21:44:00 +08:00
return Q ( ) . then ( function ( ) {
2015-01-20 10:53:08 +08:00
console . log ( 'Running: ' + wrapper + ' ' + args . concat ( extraArgs ) . join ( ' ' ) ) ;
2014-08-18 21:44:00 +08:00
return spawn ( wrapper , args ) ;
} ) ;
} ,
2015-01-07 04:56:09 +08:00
clean : function ( extraArgs ) {
2014-08-19 04:19:40 +08:00
var builder = this ;
var wrapper = path . join ( ROOT , 'gradlew' ) ;
2015-01-07 04:56:09 +08:00
var args = builder . getArgs ( 'clean' , null , extraArgs ) ;
2014-08-19 04:19:40 +08:00
return Q ( ) . then ( function ( ) {
2015-01-20 10:53:08 +08:00
console . log ( 'Running: ' + wrapper + ' ' + args . concat ( extraArgs ) . join ( ' ' ) ) ;
2014-08-19 04:19:40 +08:00
return spawn ( wrapper , args ) ;
} ) ;
} ,
2014-09-25 04:07:31 +08:00
findOutputApks : function ( build _type , arch ) {
2014-09-17 01:00:27 +08:00
var binDir = path . join ( ROOT , 'build' , 'outputs' , 'apk' ) ;
2014-09-25 04:07:31 +08:00
return findOutputApksHelper ( binDir , build _type , arch ) ;
2014-08-18 21:44:00 +08:00
}
2014-08-19 04:19:40 +08:00
} ,
none : {
prepEnv : function ( ) {
return Q ( ) ;
} ,
build : function ( ) {
console . log ( 'Skipping build...' ) ;
2014-09-23 02:23:30 +08:00
return Q ( null ) ;
2014-08-19 04:19:40 +08:00
} ,
clean : function ( ) {
return Q ( ) ;
} ,
2014-09-25 04:07:31 +08:00
findOutputApks : function ( build _type , arch ) {
return sortFilesByDate ( builders . ant . findOutputApks ( build _type , arch ) . concat ( builders . gradle . findOutputApks ( build _type , arch ) ) ) ;
2014-09-23 02:23:30 +08:00
}
2014-01-22 04:09:15 +08:00
}
} ;
2014-09-25 04:07:31 +08:00
function parseOpts ( options , resolvedTarget ) {
2014-08-18 21:44:00 +08:00
// Backwards-compatibility: Allow a single string argument
if ( typeof options == "string" ) options = [ options ] ;
2014-08-19 04:19:40 +08:00
var ret = {
buildType : 'debug' ,
2014-12-03 23:12:31 +08:00
buildMethod : process . env [ 'ANDROID_BUILD' ] || 'gradle' ,
2015-01-07 04:56:09 +08:00
arch : null ,
extraArgs : [ ]
} ;
var multiValueArgs = {
'versionCode' : true ,
'minSdkVersion' : true ,
'gradleArg' : true
2014-08-19 04:19:40 +08:00
} ;
2014-08-18 21:44:00 +08:00
// Iterate through command line options
for ( var i = 0 ; options && ( i < options . length ) ; ++ i ) {
2014-09-23 02:23:30 +08:00
if ( /^--/ . exec ( options [ i ] ) ) {
2014-12-24 05:26:43 +08:00
var keyValue = options [ i ] . substring ( 2 ) . split ( '=' ) ;
2015-01-20 10:54:29 +08:00
var flagName = keyValue . shift ( ) ;
var flagValue = keyValue . join ( '=' ) ;
2015-01-07 04:56:09 +08:00
if ( multiValueArgs [ flagName ] && ! flagValue ) {
2014-12-24 05:26:43 +08:00
flagValue = options [ i + 1 ] ;
++ i ;
}
switch ( flagName ) {
2014-08-18 21:44:00 +08:00
case 'debug' :
case 'release' :
2014-12-24 05:26:43 +08:00
ret . buildType = flagName ;
2014-08-18 21:44:00 +08:00
break ;
case 'ant' :
case 'gradle' :
2014-12-24 05:26:43 +08:00
ret . buildMethod = flagName ;
2014-08-18 21:44:00 +08:00
break ;
2014-12-11 09:30:59 +08:00
case 'device' :
case 'emulator' :
// Don't need to do anything special to when building for device vs emulator.
// iOS uses this flag to switch on architecture.
break ;
2014-08-18 21:44:00 +08:00
case 'nobuild' :
2014-08-19 04:19:40 +08:00
ret . buildMethod = 'none' ;
break ;
2014-12-24 05:26:43 +08:00
case 'versionCode' :
2015-01-07 04:56:09 +08:00
ret . extraArgs . push ( '-PcdvVersionCode=' + flagValue ) ;
2014-12-24 05:26:43 +08:00
break ;
case 'minSdkVersion' :
2015-01-07 04:56:09 +08:00
ret . extraArgs . push ( '-PcdvMinSdkVersion=' + flagValue ) ;
break ;
case 'gradleArg' :
ret . extraArgs . push ( flagValue ) ;
2014-12-24 05:26:43 +08:00
break ;
2014-08-18 21:44:00 +08:00
default :
2014-12-24 05:26:43 +08:00
console . warn ( 'Build option --\'' + flagName + '\' not recognized (ignoring).' ) ;
2014-08-18 21:44:00 +08:00
}
} else {
2014-12-11 10:16:18 +08:00
console . warn ( 'Build option \'' + options [ i ] + '\' not recognized (ignoring).' ) ;
2014-08-18 21:44:00 +08:00
}
2013-08-13 08:07:23 +08:00
}
2014-09-25 04:07:31 +08:00
2015-01-20 10:56:46 +08:00
ret . arch = resolvedTarget && resolvedTarget . arch ;
2014-09-25 04:07:31 +08:00
2014-08-19 04:19:40 +08:00
return ret ;
}
2014-08-18 21:44:00 +08:00
2014-08-19 04:19:40 +08:00
/ *
* Builds the project with the specifed options
* Returns a promise .
* /
module . exports . runClean = function ( options ) {
var opts = parseOpts ( options ) ;
var builder = builders [ opts . buildMethod ] ;
2014-08-19 11:21:26 +08:00
return builder . prepEnv ( )
2014-08-19 04:19:40 +08:00
. then ( function ( ) {
2015-01-07 04:56:09 +08:00
return builder . clean ( opts . extraArgs ) ;
2014-08-19 11:21:26 +08:00
} ) . then ( function ( ) {
shell . rm ( '-rf' , path . join ( ROOT , 'out' ) ) ;
2014-08-19 04:19:40 +08:00
} ) ;
} ;
/ *
* Builds the project with the specifed options
* Returns a promise .
* /
2014-09-25 04:07:31 +08:00
module . exports . run = function ( options , optResolvedTarget ) {
var opts = parseOpts ( options , optResolvedTarget ) ;
2014-08-19 04:19:40 +08:00
var builder = builders [ opts . buildMethod ] ;
2014-08-19 11:21:26 +08:00
return builder . prepEnv ( )
2014-08-19 04:19:40 +08:00
. then ( function ( ) {
2015-01-07 04:56:09 +08:00
return builder . build ( opts . buildType , opts . arch , opts . extraArgs ) ;
2014-09-23 02:23:30 +08:00
} ) . then ( function ( ) {
2014-09-25 04:07:31 +08:00
var apkPaths = builder . findOutputApks ( opts . buildType , opts . arch ) ;
2014-09-23 02:23:30 +08:00
console . log ( 'Built the following apk(s):' ) ;
console . log ( ' ' + apkPaths . join ( '\n ' ) ) ;
return {
apkPaths : apkPaths ,
buildType : opts . buildType ,
buildMethod : opts . buildMethod
} ;
2014-01-22 04:09:15 +08:00
} ) ;
2014-08-18 21:44:00 +08:00
} ;
2013-08-13 08:07:23 +08:00
2014-09-16 02:23:26 +08:00
/ *
* Detects the architecture of a device / emulator
* Returns "arm" or "x86" .
* /
module . exports . detectArchitecture = function ( target ) {
2014-12-04 22:58:00 +08:00
function helper ( ) {
2014-10-27 22:14:35 +08:00
return exec ( 'adb -s ' + target + ' shell cat /proc/cpuinfo' , os . tmpdir ( ) )
2014-12-04 22:58:00 +08:00
. then ( function ( output ) {
if ( /intel/i . exec ( output ) ) {
return 'x86' ;
}
return 'arm' ;
} ) ;
}
// It sometimes happens (at least on OS X), that this command will hang forever.
// To fix it, either unplug & replug device, or restart adb server.
return helper ( ) . timeout ( 1000 , 'Device communication timed out. Try unplugging & replugging the device.' )
. then ( null , function ( err ) {
if ( /timed out/ . exec ( '' + err ) ) {
// adb kill-server doesn't seem to do the trick.
// Could probably find a x-platform version of killall, but I'm not actually
// sure that this scenario even happens on non-OSX machines.
return exec ( 'killall adb' )
. then ( function ( ) {
console . log ( 'adb seems hung. retrying.' ) ;
return helper ( )
. then ( null , function ( ) {
// The double kill is sadly often necessary, at least on mac.
console . log ( 'Now device not found... restarting adb again.' ) ;
return exec ( 'killall adb' )
. then ( function ( ) {
return helper ( )
. then ( null , function ( ) {
return Q . reject ( 'USB is flakey. Try unplugging & replugging the device.' ) ;
} ) ;
} ) ;
} ) ;
} , function ( ) {
// For non-killall OS's.
return Q . reject ( err ) ;
} )
2014-09-16 02:23:26 +08:00
}
2014-12-04 22:58:00 +08:00
throw err ;
2014-09-16 02:23:26 +08:00
} ) ;
} ;
2014-09-23 02:23:30 +08:00
module . exports . findBestApkForArchitecture = function ( buildResults , arch ) {
var paths = buildResults . apkPaths . filter ( function ( p ) {
if ( buildResults . buildType == 'debug' ) {
return /-debug/ . exec ( p ) ;
}
return ! /-debug/ . exec ( p ) ;
} ) ;
var archPattern = new RegExp ( '-' + arch ) ;
var hasArchPattern = /-x86|-arm/ ;
for ( var i = 0 ; i < paths . length ; ++ i ) {
if ( hasArchPattern . exec ( paths [ i ] ) ) {
if ( archPattern . exec ( paths [ i ] ) ) {
return paths [ i ] ;
}
} else {
return paths [ i ] ;
}
2013-08-13 08:07:23 +08:00
}
2014-09-23 02:23:30 +08:00
throw new Error ( 'Could not find apk architecture: ' + arch + ' build-type: ' + buildResults . buildType ) ;
2014-08-18 21:44:00 +08:00
} ;
2013-08-13 08:07:23 +08:00
module . exports . help = function ( ) {
2014-12-24 05:26:43 +08:00
console . log ( 'Usage: ' + path . relative ( process . cwd ( ) , path . join ( ROOT , 'cordova' , 'build' ) ) + ' [flags]' ) ;
console . log ( 'Flags:' ) ;
console . log ( ' \'--debug\': will build project in debug mode (default)' ) ;
2014-08-18 21:44:00 +08:00
console . log ( ' \'--release\': will build project for release' ) ;
2014-12-25 02:35:17 +08:00
console . log ( ' \'--ant\': will build project with ant' ) ;
console . log ( ' \'--gradle\': will build project with gradle (default)' ) ;
2014-12-24 05:26:43 +08:00
console . log ( ' \'--nobuild\': will skip build process (useful when using run command)' ) ;
console . log ( ' \'--versionCode=#\': Override versionCode for this build. Useful for uploading multiple APKs. Requires --gradle.' ) ;
console . log ( ' \'--minSdkVersion=#\': Override minSdkVersion for this build. Useful for uploading multiple APKs. Requires --gradle.' ) ;
2015-01-07 04:56:09 +08:00
console . log ( ' \'--gradleArg=<gradle command line arg>\': Extra args to pass to the gradle command. Use one flag per arg. Ex. --gradleArg=-PcdvBuildMultipleApks=true' ) ;
2013-08-13 08:07:23 +08:00
process . exit ( 0 ) ;
2014-08-18 21:44:00 +08:00
} ;