# Allow tasks to be configured just before execution

**URL:** <https://discuss.gradle.org/t/allow-tasks-to-be-configured-just-before-execution/537>\
**Category:** Old Forum Archive\
**Created:** [September 4, 2012, 7:17pm UTC](https://discuss.gradle.org/t/allow-tasks-to-be-configured-just-before-execution/537 "2012-09-04T19:17:00Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![Attila\_Kelemen](https://sea1.discourse-cdn.com/gradle/user_avatar/discuss.gradle.org/attila_kelemen/32/12083_2.png) [@Attila\_Kelemen](https://discuss.gradle.org/u/Attila_Kelemen)\
**Post date:** [September 4, 2012, 7:17pm UTC](https://discuss.gradle.org/t/allow-tasks-to-be-configured-just-before-execution/537/1 "2012-09-04T19:17:00Z")

</div>

Sometimes you need to defer configuration to be done just before task execution because the information required for configuration is specified in other scripts (or by depenedent tasks). Consider the task when you want to create a javadoc from all the sources of every subprojects.

Currently the best solution I have found is this:

task mergedJavadoc(type: Javadoc, dependsOn: ‘mergedJavadocConfig’) {

}

task mergedJavadocConfig doLast {

project.subprojects {

mergedJavadoc.source(sourceSets.main.allSource);

}

mergedJavadoc.title = ‘All modules’;

mergedJavadoc.destinationDir = new File(project.buildDir, ‘merged-javadoc’);

}

I have tried the following but it does not work:

task mergedJavadoc(type: Javadoc) {

}

mergedJavadoc.doFirst {

project.subprojects {

mergedJavadoc.source(sourceSets.main.allSource);

}

mergedJavadoc.title = ‘All modules’;

mergedJavadoc.destinationDir = new File(project.buildDir, ‘merged-javadoc’);

}

The above code will not produce anything but attempting to execute ‘mergedJavadoc’ will simply report that it is “up to date”.

My prefered solution would be however if something like this would be possible:

task mergedJavadoc(type: Javadoc) configureLater {

project.subprojects {

mergedJavadoc.source(sourceSets.main.allSource);

}

mergedJavadoc.title = ‘All modules’;

mergedJavadoc.destinationDir = new File(project.buildDir, ‘merged-javadoc’);

}

Where ‘configureLater’ would simply defer the configuration until ‘mergedJavadoc’ is to be executed (and before it checks if it is up to date). Theoretically this could alse improve performance since tasks not executed does not need to be configured (although probably this performance gain is negligable).

---

<div class="post-metadata">

**Author:** ![Adrian](https://avatars.discourse-cdn.com/v4/letter/a/82dd89/32.png) [@Adrian](https://discuss.gradle.org/u/Adrian)\
**Post date:** [September 5, 2012, 4:07pm UTC](https://discuss.gradle.org/t/allow-tasks-to-be-configured-just-before-execution/537/2 "2012-09-05T16:07:00Z")

</div>

I’ve had to hack up something like this in my own build scripts. My packaging tasks actually have to scan a large directory structure to figure out what needs to go in the package, and I don’t want to take the hit if I’m not actually going to be packaging.

My tasks that require lazy configuration look like

```gradle
task foo(type: Jar) {
  quick_assignment = true
      ext.lazyConfiguration = {
    do_something_hard()
  }
}

```

Then, I define the following hook:

```gradle
gradle.taskGraph.beforeTask { Task task ->
  if (task.hasProperty('lazyConfiguration')) {
    if (task.lazyConfiguration instanceof List) {
      task.lazyConfiguration.each { task.configure it }
    } else {
      task.configure task.lazyConfiguration
    }
  }
}

```

Back in the M3 era, I was actually doing some meta-programming to implement a configureLater method to the Task class, which would append the block it was given to the lazyConfiguration property. At some point, Gradle improved its classloader separation, and my metaprogramming broke, so I had to go to straight variable assignment. This can probably be done in a plugin, but I haven’t taken the time to figure out how yet.

Of course, it would be nice if this were supported natively and I didn’t need to go through this.

---

<div class="post-metadata">

**Author:** ![luke\_daley](https://sea1.discourse-cdn.com/gradle/user_avatar/discuss.gradle.org/luke_daley/32/9890_2.png) [@luke\_daley](https://discuss.gradle.org/u/luke_daley)\
**Post date:** [September 5, 2012, 4:33pm UTC](https://discuss.gradle.org/t/allow-tasks-to-be-configured-just-before-execution/537/3 "2012-09-05T16:33:00Z")

</div>

When dealing with files, you can defer evaluation by using closures:

```gradle
task mergedJavadoc {
  source { subprojects*.sourceSets*.main*.allSource }
     …
 }

```

Our long term strategy is to support this kind of laziness for all properties.

However, there are times when it doesn’t work and something like you suggest would be useful.

---

<div class="post-metadata">

**Author:** ![Attila\_Kelemen](https://sea1.discourse-cdn.com/gradle/user_avatar/discuss.gradle.org/attila_kelemen/32/12083_2.png) [@Attila\_Kelemen](https://discuss.gradle.org/u/Attila_Kelemen)\
**Post date:** [September 5, 2012, 4:52pm UTC](https://discuss.gradle.org/t/allow-tasks-to-be-configured-just-before-execution/537/4 "2012-09-05T16:52:00Z")

</div>

Thank you, for the answer, this was actually helpful. But I find this somewhat counter-intuitive because everywhere in a gradle script closures are executed immediately, rather than lazily. But thanks anyway.

---

<div class="post-metadata">

**Author:** ![luke\_daley](https://sea1.discourse-cdn.com/gradle/user_avatar/discuss.gradle.org/luke_daley/32/9890_2.png) [@luke\_daley](https://discuss.gradle.org/u/luke_daley)\
**Post date:** [September 5, 2012, 4:54pm UTC](https://discuss.gradle.org/t/allow-tasks-to-be-configured-just-before-execution/537/5 "2012-09-05T16:54:00Z")

</div>

The majority might be, but there are plenty of cases where closures are not executed immediately.

---

<div class="post-metadata">

**Author:** ![Attila\_Kelemen](https://sea1.discourse-cdn.com/gradle/user_avatar/discuss.gradle.org/attila_kelemen/32/12083_2.png) [@Attila\_Kelemen](https://discuss.gradle.org/u/Attila_Kelemen)\
**Post date:** [June 23, 2013, 5:42pm UTC](https://discuss.gradle.org/t/allow-tasks-to-be-configured-just-before-execution/537/6 "2013-06-23T17:42:00Z")

</div>

While using Gradle I came across many problems which I couldn’t easily solve without using _afterEvaluate_. However, I have found _afterEvaluate_ to be a fragile solution. That is, in almost all cases, using _afterEvaluate_ was a dirty hack marking a failure of design in the build scripts.

In almost all cases, I have found that if I used the lazy task configuration proposed in the post, I could easily avoid using _afterEvaluate_. As an added benefit, this would make build script evaluation faster due to skipping configuration code not actually in use.

Why does lazy configuration solves the majority of problems? Because in Gradle most of the time you just need to configure tasks and then let Gradle run them. Using _afterEvaluate_ becomes necessary when you need a property configured somewhere outside of the control of the code needing the property. However, if a task needs to be configured, it can usually be expected that it does need properties only from tasks it depends on. This dependency can usually be easily enforced.

When cannot lazy configuration be used? When you need to affect the task graph. Obviously, it is too late to change the graph when the tasks are being executed. So this RFE does not intended to solve this case. I guess, there is no one tool fits all. (Well, maybe adding another graph - or many more - where tasks are just doing configuration, so configuration dependency can also be expressed the same way as task dependency)

Are there any plans for adding this kind of lazy task configuration in the forseeable future?

---

<div class="post-metadata">

**Author:** ![luke\_daley](https://sea1.discourse-cdn.com/gradle/user_avatar/discuss.gradle.org/luke_daley/32/9890_2.png) [@luke\_daley](https://discuss.gradle.org/u/luke_daley)\
**Post date:** [June 23, 2013, 5:48pm UTC](https://discuss.gradle.org/t/allow-tasks-to-be-configured-just-before-execution/537/7 "2013-06-23T17:48:00Z")

</div>

Hi Attilla,

This is one of our biggest “issues” at the moment. We haven’t fully mapped out a direction, but are in the process of doing so. You can have a look at the lazy configuration spec for what we have currently distilled from our conversations.

[https://github.com/gradle/gradle/blob/master/design-docs/lazy-configuration.md](https://github.com/gradle/gradle/blob/master/design-docs/lazy-configuration.md)

What’s in there is not set in stone, and probably will change going forward.

---

<div class="post-metadata">

**Author:** ![Attila\_Kelemen](https://sea1.discourse-cdn.com/gradle/user_avatar/discuss.gradle.org/attila_kelemen/32/12083_2.png) [@Attila\_Kelemen](https://discuss.gradle.org/u/Attila_Kelemen)\
**Post date:** [June 23, 2013, 6:30pm UTC](https://discuss.gradle.org/t/allow-tasks-to-be-configured-just-before-execution/537/8 "2013-06-23T18:30:00Z")

</div>

I have read through the doc you linked. As I understand you want domain objects to be lazily configured. This seems to be a good step forward to me. I would like to comment on them here:

- You say, that “Lazy data structures cannot be shared between threads for parallel execution.” But this is not necessarily true. The only thing which must be ensured is to have the data structure initialized before accessing. This can be done by callind an “ensureInitialized” method before getting the structure. - I feel that lazy configuration of tasks fits well with the goals set in the design doc. Although, it does not solve every problem described but could be an easy to use building block for 3rd party plugins.

However, whatever you do, I would like to ask you to not do something like making the configuration block of _publications_ lazy by default. That is, having some task eager configuration and others lazy is extremely confusing. So if you make it lazy, please make it something like:

publications lazy {

// do something.

}

Also if you allow lazy configuration for other things, this (or something like this) could be a convention, easily recognized even by users not intimately familiar with Gradle.

---

<div class="post-metadata">

**Author:** ![luke\_daley](https://sea1.discourse-cdn.com/gradle/user_avatar/discuss.gradle.org/luke_daley/32/9890_2.png) [@luke\_daley](https://discuss.gradle.org/u/luke_daley)\
**Post date:** [June 23, 2013, 6:55pm UTC](https://discuss.gradle.org/t/allow-tasks-to-be-configured-just-before-execution/537/9 "2013-06-23T18:55:00Z")

</div>

The forums don’t really work well for this type of “discussion”. If you want to inject your opinions, the most effective way to do so is via the dev list.
