diff --git a/bin/templates/cordova/lib/build.js b/bin/templates/cordova/lib/build.js index 9c4839d2..300d675a 100644 --- a/bin/templates/cordova/lib/build.js +++ b/bin/templates/cordova/lib/build.js @@ -174,7 +174,7 @@ var builders = { } }, gradle: { - getArgs: function(cmd, arch) { + getArgs: function(cmd, arch, extraArgs) { if (arch == 'arm' && cmd == 'debug') { cmd = 'assembleArmv7Debug'; } else if (arch == 'arm' && cmd == 'release') { @@ -191,6 +191,7 @@ var builders = { var args = [cmd, '-b', path.join(ROOT, 'build.gradle')]; // 10 seconds -> 6 seconds args.push('-Dorg.gradle.daemon=true'); + args.push.apply(args, extraArgs); // Shaves another 100ms, but produces a "try at own risk" warning. Not worth it (yet): // args.push('-Dorg.gradle.parallel=true'); return args; @@ -254,20 +255,22 @@ var builders = { * Builds the project with gradle. * Returns a promise. */ - build: function(build_type, arch) { + build: function(build_type, arch, extraArgs) { var builder = this; var wrapper = path.join(ROOT, 'gradlew'); - var args = this.getArgs(build_type == 'debug' ? 'debug' : 'release', arch); + var args = this.getArgs(build_type == 'debug' ? 'debug' : 'release', arch, extraArgs); return Q().then(function() { + console.log('Running: ' + wrapper + ' ' + extraArgs.join(' ')); return spawn(wrapper, args); }); }, - clean: function() { + clean: function(extraArgs) { var builder = this; var wrapper = path.join(ROOT, 'gradlew'); - var args = builder.getArgs('clean'); + var args = builder.getArgs('clean', null, extraArgs); return Q().then(function() { + console.log('Running: ' + wrapper + ' ' + extraArgs.join(' ')); return spawn(wrapper, args); }); }, @@ -302,7 +305,14 @@ function parseOpts(options, resolvedTarget) { var ret = { buildType: 'debug', buildMethod: process.env['ANDROID_BUILD'] || 'gradle', - arch: null + arch: null, + extraArgs: [] + }; + + var multiValueArgs = { + 'versionCode': true, + 'minSdkVersion': true, + 'gradleArg': true }; // Iterate through command line options @@ -311,7 +321,7 @@ function parseOpts(options, resolvedTarget) { var keyValue = options[i].substring(2).split('='); var flagName = keyValue[0]; var flagValue = keyValue[1]; - if ((flagName == 'versionCode' || flagName == 'minSdkVersion') && !flagValue) { + if (multiValueArgs[flagName] && !flagValue) { flagValue = options[i + 1]; ++i; } @@ -333,10 +343,13 @@ function parseOpts(options, resolvedTarget) { ret.buildMethod = 'none'; break; case 'versionCode': - process.env['ANDROID_VERSION_CODE'] = flagValue; + ret.extraArgs.push('-PcdvVersionCode=' + flagValue); break; case 'minSdkVersion': - process.env['ANDROID_MIN_SDK_VERSION'] = flagValue; + ret.extraArgs.push('-PcdvMinSdkVersion=' + flagValue); + break; + case 'gradleArg': + ret.extraArgs.push(flagValue); break; default : console.warn('Build option --\'' + flagName + '\' not recognized (ignoring).'); @@ -363,7 +376,7 @@ module.exports.runClean = function(options) { var builder = builders[opts.buildMethod]; return builder.prepEnv() .then(function() { - return builder.clean(); + return builder.clean(opts.extraArgs); }).then(function() { shell.rm('-rf', path.join(ROOT, 'out')); }); @@ -378,7 +391,7 @@ module.exports.run = function(options, optResolvedTarget) { var builder = builders[opts.buildMethod]; return builder.prepEnv() .then(function() { - return builder.build(opts.buildType, opts.arch); + return builder.build(opts.buildType, opts.arch, opts.extraArgs); }).then(function() { var apkPaths = builder.findOutputApks(opts.buildType, opts.arch); console.log('Built the following apk(s):'); @@ -468,5 +481,6 @@ module.exports.help = function() { 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.'); + console.log(' \'--gradleArg=\': Extra args to pass to the gradle command. Use one flag per arg. Ex. --gradleArg=-PcdvBuildMultipleApks=true'); process.exit(0); }; diff --git a/bin/templates/cordova/lib/plugin-build.gradle b/bin/templates/cordova/lib/plugin-build.gradle index f062588c..b345b90a 100644 --- a/bin/templates/cordova/lib/plugin-build.gradle +++ b/bin/templates/cordova/lib/plugin-build.gradle @@ -51,8 +51,8 @@ dependencies { } android { - compileSdkVersion cordova.cordovaSdkVersion - buildToolsVersion cordova.cordovaBuildToolsVersion + compileSdkVersion cdvCompileSdkVersion + buildToolsVersion cdvBuildToolsVersion publishNonDefault true compileOptions { diff --git a/bin/templates/cordova/lib/run.js b/bin/templates/cordova/lib/run.js index 12f178ce..db783d91 100644 --- a/bin/templates/cordova/lib/run.js +++ b/bin/templates/cordova/lib/run.js @@ -39,23 +39,18 @@ var path = require('path'), var list = false; for (var i=2; i } } -def getIntFromManifest(name) { - def manifestFile = file(android.sourceSets.main.manifest.srcFile) - def pattern = Pattern.compile(name + "=\"(\\d+)\"") - def matcher = pattern.matcher(manifestFile.getText()) - matcher.find() - return Integer.parseInt(matcher.group(1)) -} - def ensureValueExists(filePath, props, key) { if (props.get(key) == null) { throw new GradleException(filePath + ': Missing key required "' + key + '"') @@ -241,6 +243,8 @@ def addSigningProps(propsFilePath, signingConfig) { } } -if (file('build-extras.gradle').exists()) { - apply from: 'build-extras.gradle' +// This can be defined within build-extras.gradle as: +// ext.postBuildExtras = { ... code here ... } +if (hasProperty('postBuildExtras')) { + postBuildExtras() } diff --git a/bin/templates/project/cordova.gradle b/bin/templates/project/cordova.gradle index cf2dacad..8b371bf9 100644 --- a/bin/templates/project/cordova.gradle +++ b/bin/templates/project/cordova.gradle @@ -18,6 +18,8 @@ */ import java.util.regex.Pattern +import groovy.swing.SwingBuilder + String getProjectTarget(String defaultTarget) { def manifestFile = file("project.properties") @@ -37,7 +39,7 @@ String[] getAvailableBuildTools() { .sort { a, b -> compareVersions(b, a) } } -String latestBuildToolsAvailable(String minBuildToolsVersion) { +String findLatestInstalledBuildTools(String minBuildToolsVersion) { def availableBuildToolsVersions try { availableBuildToolsVersions = getAvailableBuildTools() @@ -115,6 +117,45 @@ String getAndroidSdkDir() { androidSdkDir } -ext.cordovaSdkVersion = System.env.MIN_SDK_VERSION ?: getProjectTarget("android-19") -ext.cordovaBuildToolsVersion = latestBuildToolsAvailable("19.1.0") +def extractIntFromManifest(name) { + def manifestFile = file(android.sourceSets.main.manifest.srcFile) + def pattern = Pattern.compile(name + "=\"(\\d+)\"") + def matcher = pattern.matcher(manifestFile.getText()) + matcher.find() + return Integer.parseInt(matcher.group(1)) +} + +def promptForPassword(msg) { + if (System.console() == null) { + def ret = null + new SwingBuilder().edt { + dialog(modal: true, title: 'Enter password', alwaysOnTop: true, resizable: false, locationRelativeTo: null, pack: true, show: true) { + vbox { + label(text: msg) + def input = passwordField() + button(defaultButton: true, text: 'OK', actionPerformed: { + ret = input.password; + dispose(); + }) + } + } + } + if (!ret) { + throw new GradleException('User canceled build') + } + return new String(ret) + } else { + return System.console().readPassword('\n' + msg); + } +} + +// Properties exported here are visible to all plugins. +ext { + // These helpers are shared, but are not guaranteed to be stable / unchanged. + privateHelpers = {} + privateHelpers.getProjectTarget = { defaultValue -> getProjectTarget(defaultValue) } + privateHelpers.findLatestInstalledBuildTools = { defaultValue -> findLatestInstalledBuildTools(defaultValue) } + privateHelpers.extractIntFromManifest = { name -> extractIntFromManifest(name) } + privateHelpers.promptForPassword = { msg -> promptForPassword(msg) } +} diff --git a/framework/build.gradle b/framework/build.gradle index f1585d3a..cace2042 100644 --- a/framework/build.gradle +++ b/framework/build.gradle @@ -47,8 +47,8 @@ buildscript { apply plugin: 'android-library' android { - compileSdkVersion cordova.cordovaSdkVersion - buildToolsVersion cordova.cordovaBuildToolsVersion + compileSdkVersion cdvCompileSdkVersion + buildToolsVersion cdvBuildToolsVersion publishNonDefault true compileOptions {