X. Wo Satuk
X. Wo Satuk

Reputation: 1003

How to generate a resource file in Gradle

One of my Gradle project has 10 subprojects. For each of these projects from Gradle task I want to generate a Java properties file which will specify the project name, because I need to know project name during runtime. The properties file should go to resources directory of each project. Because the number of projects might grow over time, I thought to not add a resource file for each of them, but generate it via Gradle.

For example, for project :custom:a I need to have a project-info.properties file in resources directory with contents:

project=a

For project :custom:b I want a similar project-info.properties files:

project=b

How can I generate a file and put it to Java resources directory?

I tried to add the following rule in all projects but it doesn't seem to generate these files anymore (maybe I've introduced some breaking changes):

processResources {
    def resourcesDir = sourceSets.main.output.resourcesDir
    resourcesDir.mkdirs()
    def contents = "projectInfo.project=$project.name"
    new File(resourcesDir, "project-info.properties").text = contents
}

Edit: Files should be generated in build directory, not in source.

Upvotes: 7

Views: 12540

Answers (2)

Peter Ledbrook
Peter Ledbrook

Reputation: 4462

I strongly advise against generating files in normal source directories, i.e. those that are checked into source control (SCM). It's far better to generate the files under the build directory somewhere and add the location to the relevant source set.

The first step is to create a task that generates the properties file:

ext.genOutputDir = file("$buildDir/generated-resources")

task generatePropInfo {
    ext.outputFile = file("$genOutputDir/project-info.properties")
    outputs.file(outputFile)
    doLast {
        outputFile.text = "projectInfo.project=${project.name}"
    }
}

You might even want to consider making this a custom task type so you don't have to use extra properties and the runtime API for incremental build.

With that done, you just need to configure the source set so that the files in the generated-resources directory are included as outputs of the source set. Put this line after the task definition:

sourceSets.main.output.dir genOutputDir, builtBy: generatePropInfo

If you want to have multiple tasks that generate "output" files for a source set, then create an aggregate task that depends on all of them — say generateResources — and update the builtBy argument to that task — buildBy: generateResources.

Feel free to ask any questions about the solution.

Upvotes: 17

Stanislav
Stanislav

Reputation: 28096

Try to run it in the execution phase, not configuration:

processResources {
    doFirst {
        def resourcesDir = sourceSets.main.output.resourcesDir
        resourcesDir.mkdirs()
        def contents = "projectInfo.project=$project.name"
        new File(resourcesDir, "project-info.properties").text = contents
    }
}

doFirst should do the trick and make a file creation just before this task is running

Upvotes: 4

Related Questions