I want to generate BuildConfig based on local.properties content. Also I want to do some checks on the values it contains. But I just doesn’t understand how to implement it properly and keep this logic out of my root build.gradle
I’m using the com.github.gmazzo.buildconfig plugin for BuildScript generation. I need to read the content of the local.properties file (or create a new one with default values), parse it, and then use it in the buildconfig configuration block. Here how I do it:
build.gradle:
plugins {
id("com.github.gmazzo.buildconfig") version "5.3.5"
/// ...
}
// ...
buildConfig {
Properties properties = new Properties()
try {
properties.load(tasks.loadLocalProperties.outputs.files.singleFile.newDataInputStream())
} catch(ignored) {
// e.g. File not found
}
buildConfigField(String, "SENTRY_DSN", provider { properties.getProperty("sentry-dsn") })
}
// ...
I thing this is not how it suppose to work. I want to store such logic in my buildSrc but how? At the moment only my custom tasks are stored there:
buildSrc/src/main/java/com/example/task/LoadLocalProperties.java:
// Load properties from file. Create file with default values if it doesn't exist.
public class LoadLocalProperties extends DefaultTask {
@TaskAction
void execute() throws Exception {
final File localPropertiesFile = getLocalPropertiesFile();
Properties localProperties = generateDefaultLocalProperties();
if (localPropertiesFile.exists()) {
localProperties.load(ResourceGroovyMethods.newDataInputStream(localPropertiesFile));
} else {
localProperties.store(ResourceGroovyMethods.newDataOutputStream(localPropertiesFile), "Provide these data in order to build the project");
}
}
@OutputFile
File getLocalPropertiesFile() {
return getProject().file("local.properties");
}
private static Properties generateDefaultLocalProperties() {
Properties localProperties = new Properties();
localProperties.put("sentry-dsn", "");
return localProperties;
}
}
buildSrc/src/main/java/com/example/task/ValidateLocalProperties.java:
// Check if properties contain valid URL
public class ValidateLocalProperties extends DefaultTask {
private static final String SENTRY_DSN_PROPERTY_KEY = "sentry-dsn";
@TaskAction
void execute() throws Exception {
final Properties localProperties = loadLocalProperties();
validateLocalProperties(localProperties);
}
private Properties loadLocalProperties() throws IOException {
final Properties result = new Properties();
File localPropertiesFile = getProject().file("local.properties");
result.load(ResourceGroovyMethods.newDataInputStream(localPropertiesFile));
return result;
}
private void validateLocalProperties(Properties localProperties) {
try {
validateSentryDsnProperty(localProperties);
} catch (IllegalArgumentException e) {
throw new IllegalArgumentException("Invalid value for the \"" + SENTRY_DSN_PROPERTY_KEY + "\" key", e);
}
}
private void validateSentryDsnProperty(Properties properties) throws IllegalArgumentException {
final String sentryDsn = Objects.requireNonNull(properties.get(SENTRY_DSN_PROPERTY_KEY)).toString();
try {
new URL(sentryDsn);
} catch (MalformedURLException e) {
throw new IllegalArgumentException("Incorrect Sentry DSN", e);
}
}
}
I register this tasks using custom Gradle plugin placed in buildSrc dir.
buildSrc/src/main/java/com/example/plugin/LocalPropertiesBuildConfig.java:
class LocalPropertiesBuildConfig implements Plugin<Project> {
@Override
public void apply(Project project) {
project.getTasks().register("loadLocalProperties", LoadLocalProperties.class);
project.getTasks().register("validateLocalProperties", ValidateLocalProperties.class);
}
}
buildSrc/build.gradle:
plugins {
id 'java-gradle-plugin'
}
gradlePlugin {
plugins {
myPlugins {
id = 'local-properties-build-config'
implementationClass = 'com.example.plugin.LocalPropertiesBuildConfig'
}
}
}
So there are answers I can’t find answers:
- How can I use loaded properties in
buildconfig {}configuration block of my rootbuild.gradlefile? Is it possible to executeLoadLocalPropertiesinside this block? How to achieve it in Gradle way? Please note I don’t want to keep any build inside the rootbuild.gradle. It suppose to be placed inbuildSrc, I think. - How to establish tasks dependencies for tasks placed in
buildSrcwithout definingdependsOninside the rootbuild.gradle? I wantLoadLocalPropertiesto run beforegenerateBuildConfigandValidateLocalPropertiesbeforebuild.
Please note that I don’t want to “just make it work”. I want to find out the right way to achieve such logic.