A build config is a generated class holding constants set by the build script. It can be accessed within the Java or Groovy application, thus providing a way to transport information about version, project name or debug flags or a lot more info that otherwise will not be available or has to to be transported via complicated workarounds.
buildscript {
repositories {
maven {
url 'https://plugins.gradle.org/m2/'
}
}
dependencies {
classpath 'gradle.plugin.de.fuerstenau:BuildConfigPlugin:1.1.0'
}
}
/* this example is for a Java project */
apply plugin: 'java'
apply plugin: 'de.fuerstenau.buildconfig'
/* ... some other stuff like dependencies */
/* closure needs to be present for build config to be created, build config is
* created for "main" source set that way */
buildConfig {
/* these set the values of the two default fields VERSION and NAME */
version = '1.0.1' // default: project.version
appName = 'some app name' // default: project.name
/* the package can be set */
packageName = 'org.sample.buildconfig' // default: project.group or "de.fuerstenau.buildconfig"
/* the class name can also be changed */
clsName = 'MyBuildConfig' // default: BuildConfig
/* additional fields are possible, garbage can be put, careful, no checking
* except compiler, simple templating really */
buildConfigField 'boolean', IS_DEBUG', 'true'
}
and the usage of the generated class
package org.sample.buildconfig;
public class Main {
public static void main (String[] args) {
/* the build config is accessible from the app */
System.out.println (MyBuildConfig.NAME + ' ' + MyBuildConfig.VERSION +
"(debug: " + MyBuildConfig.IS_DEBUG ? "enabled" : "disabled" + ')');
}
}
Build script snippet for use in all Gradle versions:
buildscript {
repositories {
maven {
url 'https://plugins.gradle.org/m2/'
}
}
dependencies {
classpath 'gradle.plugin.de.fuerstenau:BuildConfigPlugin:1.1.0'
}
}
apply plugin: 'de.fuerstenau.buildconfig'
Build script snippet for new, incubating, plugin mechanism introduced in Gradle 2.1:
plugins {
id 'de.fuerstenau.buildconfig' version '1.1.0'
}
The plugin provides a buildConfig
closure to set general properties. If not present in the build script, nothing will happen, no build config is generated or compiled. If at least an empty buildConfig
closure is present, a build config for the main
source set will be created upon compilation (of course with default values).
A build config class by default has the name BuildConfig
and will have to constants that are always present. These are
NAME
, (type:java.lang.String
) the name of the application or lib or project (default:project.name
),VERSION
(type:java.lang.String
), the version of the project (default:project.version
).
As written above the class name defaults to BuildConfig
and the package defaults to project.group
or if not set to de.fuerstenau.buildconfig
.
The basic properties of the buildConfig
closure are
appName
, sets the value ofNAME
,version
, sets the value ofVERSION
,clsName
, sets the class name,packageName
, sets the package name.
There are two tasks that are created for a build config. One generates the java source code the other compiles it. The generating task is named generateBuildConfig
and the compiling task name is named compileBuildConfig
. The compiling task depends upon the generating task output and the configuration compile
is made dependent on the outputs of compileBuildConfig
task.
- configuration
compile
depends ongenerateBuildConfig
, generateBuildConfig
depends ongenerateBuildConfig
.
Example: A simple buildConfig
closure, overriding only the version
:
project.name = 'MyProject'
project.group = 'de.fuerstenau.myproject'
...
buildConfig {
version = '1.0-SPECIAL'
}
results in a build config class:
package de.fuerstenau.myproject;
public final class BuildConfig {
private BuildConfig () {}
public static final String NAME = "MyProject";
public static final String VERSION = "1.0-SPECIAL";
}
which could be used like this:
/* Note: we are in the same package as the BuildConfig class */
package de.fuerstenau.myproject;
public class Main {
public static void main (String[] args) {
System.out.println (BuildConfig.NAME + ' ' + BuildConfig.VERSION);
}
Example: A buildConfig
closure, overriding everything:
buildConfig {
version = '0.0.1'
appName = 'MySuperApp'
clsName = 'MySuperBuildConfig'
packageName = 'org.my.sample'
}
results in a build config class:
package org.my.sample;
public final class MySuperBuildConfig {
private MySuperBuildConfig () {}
public static final String NAME = "MySuperApp";
public static final String VERSION = "0.0.1";
}
As stated above the general buildConfig
closure creates a build config for the main
source set. The sourceSets
nested closure allows to add build config classes for multiple source sets.
buildConfig {
sourceSets {
main
otherSourceSet
}
}
will create build configs for both source sets. As no value is defined in the buildConfig
closure the default values will be used.
Note: If the sourceSets
closure is used the build config for main
is no more automatically added. Adding a non-existing source set will fail the build. Omitting an existing source set will not create a build config for this source set.
Example: A buildconfig
closure, that only creates a build config for source set otherSourceSet
:
buildConfig {
version = '1.0-alpha'
sourceSets {
otherSourceSet
}
}
Properties can be set for each source set and in general. Specific properties will override general properties:
buildConfig {
version = '1.0-alpha'
sourceSets {
main {
clsName = 'MainConfig'
}
otherSourceSet {
version = '2.0-beta'
}
}
}
The tasks created for source sets other than main
will be named generate<SourceSet>BuildConfig
and compile<SourceSet>BuildConfig
(<sourceSet>
being the name of the source set). The configuration used for dependency will be compile<SourceSet>
(<SourceSet>
as above).
The buildConfigField (String, String, String)
method allows for additional fields. First parameter is the type (Java type to be exact), second parameter is the name (use uppercase these fields are defined as static final
), and the third is value. Any type is allowed but the plugin uses simple templating therefore entering any garbage will result in build failure.
It can be used inside the general closure or a specific source set closure:
buildConfig {
version = '1.0'
/* using Java style parentheses */
buildConfigField ('String', 'MY_STRING', 'some string value')
/* primitives can be used, too,
* Note: no parentheses as Gradle is Groovy */
buildConfigField 'int', 'MY_INT', '23'
/* assume there is an enum "org.sample.Option" with constant "SIMPLE"
* it can be used as long as fully qualified path is provided because there are
* no imports */
buildConfigField 'org.sample.Option', 'MY_ENUM', 'org.sample.Option.SIMPLE'
sourceSets {
main
/* assume there is another source set */
otherSourceSet {
buildConfigField 'String', 'SECRET_STR', 'haha secret'
buildConfigField 'int', 'MY_INT', '42'
}
}
}
The result will be a build config for main
source set like
/* assume there is no "project.group" defined */
package de.fuerstenau.buildconfig;
public final class BuildConfig {
private BuildConfig () {};
public static final String NAME = "..."; /* project.name */
public static final String VERSION = "1.0";
public static final String MY_STRING = "some string value";
public static final String MY_INT = 23;
public static final org.sample.Option MY_ENUM = org.sample.Option.SIMPLE;
}
and a build config for otherSourceSet
:
/* assume there is no "project.group" defined */
package de.fuerstenau.buildconfig;
public final class BuildConfig {
private BuildConfig () {};
...
/* everything from the general closure plus the one from the specific
* source set closure and the "MY_INT" value is overridden */
public static final org.sample.Option MY_ENUM = org.sample.Option.SIMPLE;
public static final String MY_INT = 42;
}
The plugin is a bit smart here and checks for types String
and char
and adds ""
or ''
respectively.
The configuration compile
or any other compile<SourceSet>
configuration must not be resolved before the buildConfig
closure or else the build fails because a resolved configuration may not have a dependency added. Try moving the buildConfig
closure a bit up in the build script.
As stated above the tasks of de.fuerstenau.gradle.buildconfig.GenerateBuildConfigTask
as created and configured by the plugin default to ${buildDir}/gen/buildconfig/<sourceSetName>/src
for sources and ${buildDir}/gen/buildconfig/<SourceSet>/classes
for the compiled generated sources (with <SourceSet>
being the name of the source set).
If buildConfig
closure is not present, no tasks are created automatically and tasks can be created manually as it seems convenient.
task generateBuildConfig (type: de.fuerstenau.gradle.buildconfig.GenerateBuildConfigTask) {
appName = 'SuperTrooperStarshipApp'
version = '1.1.2'
clsName = 'MainConfig'
packageName = 'org.sample'
outputDir = new File ("${buildDir}/gen/buildconfig/src/main/")
}
task compileBuildConfig(type:JavaCompile, dependsOn: generateBuildConfig) {
classpath = files () /* empty files suffices */
destinationDir = new File ("${buildDir}/gen/buildconfig/classes/main/")
source = generateBuildConfig.outputDir
}
afterEvaluate {
dependencies {
compile compileBuildConfig.outputs.files
}
}