0

I have a settings plugin that is multi-project aware. It currently applies itself to every project identified in settings.gradle. However, this is a problem because each subproject doesn't have the same configuration, and I control some plugin behavior through project properties set on the command-line via -P.

The problem is that this fails on projects that don't have the configuration necessary to use that property, and I know of know way to apply a property to a specific subproject via the command-line.

Instead of iterating over settings.gradle.allprojects, is there a way to know what projects have actually been included as part of the build? For example when I do:

gradle :subproject-name:build :other-subproject-name:build -PsomeProperty

I would like to know that only subproject-name and other-subproject-name were called so that I can apply the settings plugin to only those projects.

Or is there a way to "scope" project properties somehow, to only a particular project?

Vivin Paliath
  • 94,126
  • 40
  • 223
  • 295

1 Answers1

0

... is there a way to know what projects have actually been included as part of the build?

This is a misconception. All projects are part of the build when settings.gradle includes them, and they'll all get configured so they have an associated Project.

What you're ultimately looking for is, given the tasks that will execute, what are the subprojects who own those tasks? To do that, you can grab Gradle's task graph, and for all of the tasks that will execute, find the project that owns each task.

gradle.taskGraph.whenReady { graph ->
    def projects = graph.allTasks.collect { it.project }.toSet()
    projects.each {
        println "Project is being used in this build: " + it
    }
}
nickb
  • 59,313
  • 13
  • 108
  • 143
  • I was afraid that this would be the case; unfortunately, the plugin I have is a versioning plugin and I need to configure the project version before any tasks are configured, because by then it would be too late. I wish there was a way to specify that a project property should only be applied to a specific project. – Vivin Paliath Jul 11 '17 at 17:29
  • @VivinPaliath I'm not 100% clear on why the project version needs to be set before tasks get configured. Ultimately you may want to reconsider your approach. There is very limited information known about the build during the initialization phase, which is when you're attempting to apply your plugin. `project.version` can be set during the configuration phase, and you'll have more information available to you. Your tasks, assuming you're also defining them, could be set up to read the value of `project.version` at execution time. – nickb Jul 11 '17 at 17:55
  • You start running into late configuration issues. The jar plugin and the maven-publish plugin are good examples. My plugin sets the version based on git tags and you pass in certain properties to control the versioning; i..e, bumping the major, minor, patch, or pre-release. If I wait for tasks to be ready, then tasks that use project versions won't get the correct version, and then you end up having to re-configure the tasks in an `afterEvaluate`; this increases the burden on users since they now have to aware of which tasks set the version at config time. – Vivin Paliath Jul 11 '17 at 18:26
  • Yes, `afterEvaluate` is definitely not the avenue you'd like to go down. However, running with your example, the java plugin which configures the default JAR task should be set up with convention mapping so it receives the value of `project.version` during execution. I just tried `gradle.taskGraph.whenReady { project.version = "1.2.3" }` in a test build, which produced a JAR named `test-1.2.3.jar`. – nickb Jul 11 '17 at 18:56
  • Yes, that approach works and I've used that before. But in general, waiting for the task graph to be ready leads to surprising behavior, and makes it necessary to update the version in `whenReady`. With many artifacts, this can be a pain (example [#1](https://github.com/vivin/gradle-semantic-build-versioning/issues/30), [#2](https://github.com/vivin/gradle-semantic-build-versioning/issues/29)). The purpose behind the versioning plugin was to make it easy to set the version and not have to worry about it, but having to fix the version in a `whenReady` block ends up defeating the purpose. :( – Vivin Paliath Jul 12 '17 at 00:59
  • 1
    I understand better now. Users who expect to be able to readily use `project.version` are in for a surprise when they can't use it immediately but need to lazily evaluate it. Perhaps with Gradle 4.0 and the introduction of PropertyState, you'll be able to use a modified version of that as the Object that backs `project.version`. – nickb Jul 12 '17 at 17:33