1

I would simply like to run a separate application (exe) prior to Gradle beginning the build progress. My goal is have my exe (already written) auto-gen a dependancy file containing a build number, which I display in the UI. All of the above is easy, but I know almost nothing of Gradle.

This question has been asked, but the answers are terse snippets of Gradle, using Gradle tasks, and do not explain much.

I want to use the same exe in different projects, so it takes a command argument to specify the location of the auto-gen file;

"buildnum.exe /someworkspace/someproject/somefolder/version.java"

How to I get this to run? I'm using a typical build.gradle script;

buildscript {
    repositories {
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:1.1.0'
    }
}

allprojects {
    repositories {
        jcenter()
    }
}
Syntactics
  • 313
  • 4
  • 8

3 Answers3

4

You can use an Exec task:

task buildNum(type: Exec, description: 'My Build num exe') {
    commandLine 'buildnum.exe',
            '/someworkspace/someproject/somefolder/version.java'
}

tasks.withType(JavaCompile) {
    compileTask -> compileTask.dependsOn buildNum
}
weston
  • 54,145
  • 21
  • 145
  • 203
  • Ok, great, after a few tries I figured out which script to add the entries to, and where. But, I messed up, it's not exactly what I intended (although it answers the question I asked) What I really need is to only run the exe if Gradle determines the Module *needs* compiling ie. sme source or resource it is modified – Syntactics May 25 '15 at 18:48
  • Doing all this to inject a version number isn't really necessary. What's so special about the way your exe chooses the number? – weston May 25 '15 at 20:07
  • QA Department wants a traceable Build Number for Release purposes. My App is built up of multiple modules that are maintained separately, so each one has a Build Number that is incremented every time we re-compile it. It's how the rest of our Software (Non Droid) is tracked. – Syntactics May 26 '15 at 15:08
  • This breaks 'incremental build' support. This will cause java to build your project every time, even if the version does not change. You should add inputs and outputs to the task – Steve Vermeulen Aug 26 '20 at 20:21
3

For those unfamiliar with Gradle (like me), at the bottom is the full build.gradle script for my Module so you can see where and how the tool is integrated, as again we were just given snippets. The Exec command runs the exe in the same folder as the build.grade file, so use relative paths to the tool and source.

This is VersionUtils.java, a source file in my Module which contains the BuildNum for the Module.

package ca.mmist;

public class VersionUtils
{
    public static final int nSkyUtilsCRC = 1078887142;
    public static final int nSkyUtilsBuild = 228;
}

What I really wanted was for the BuildNum to only increment when a dependancy changed requiring a build. So, I modified BuildNum.exe to find the 'src' folder in the VersionUtils.java, and then recursively scan each subfolder looking for .java;.xml;.jar;.lib and generate a CRC32 using the FileWriteTime and FileSize of each source file. So when I re-write VersionUtils.java (first into VersionUtils.~java) to increment the BuildNo, I compare the CRCs and if they are the same, I can simply discard the temp file. Otherwise I swap (delete and rename) the files, thereby causing a rebuild of my Module with a new BuildNo. (Sounds more painful than it was to code up in an hour.)

Anyway, now QA is happy they can validate precisely what build of the Software shipped without relying on a human to remember to modify the Version tags in the Manifest.

apply plugin: 'com.android.library'

android {
    compileSdkVersion 16
    buildToolsVersion "19.1.0"

    task buildNum(type: Exec, description: 'BuildNum.exe') {
        commandLine '../../../Tools/Bin/buildnum.exe', 'src/main/java/ca/mmist/VersionUtils.java'
    }

    tasks.withType(JavaCompile) {
        compileTask -> compileTask.dependsOn buildNum
    }

    defaultConfig {
        minSdkVersion 10
        targetSdkVersion 16
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
        }
    }
}

dependencies {
    compile 'com.android.support:support-v4:18.+'
    compile files('libs/maplink.jar')
}
Syntactics
  • 313
  • 4
  • 8
  • If you use a version control system like git, you can capture the SHA for the current commit in the buildconfig, allowing you to access it from within the app's code. The U2020 example application's build.gradle does this: https://github.com/JakeWharton/u2020/blob/master/build.gradle – chwahoo Jul 28 '15 at 18:07
1

Example to run some console commands:


    task cleanApks(type: Delete) {
        sdkUpdate()    
    }

    def sdkUpdate() {
        println executeSdkCommand('javac -version')
        println executeSdkCommand('android list sdk --all')
    }

    String executeSdkCommand(String cmd) {
        new ByteArrayOutputStream().withStream { os ->
            ExecResult result = exec {
                executable = 'cmd'
                workingDir = "${System.getenv("ANDROID_HOME")}/tools"
                args = ['/c', cmd]
                standardOutput = os
            }
            return os.toString()

        }
    }

    dependencies {
        cleanApks.dependsOn 'clean'
        compile fileTree(dir: 'libs', include: ['*.jar'])    
    }