5

Consider the following buildscript where

configurations {
    myConfig
}
task addToMyConfig {
    doLast {
        println "Doing some work"
        dependencies {
            myConfig 'log4j:log4j:1.2.17'
        }
    }
}
task useMyConfig {
    doLast {
        println "myConfig = $configurations.myConfig.files"
    }
}

Question: Is there a way to fire addToMyConfig every time configurations.myConfig is resolved without adding a task dependency where useMyConfig depends on addToMyConfig?

I would like to say:

configurations.myConfig.builtBy addToMyConfig

** I do NOT want to say **

useMyConfig.dependsOn addToMyConfig 

I want to avoid useMyConfig.dependsOn addToMyConfig because there may be many tasks which consume configurations.myConfig

Note: There is a ConfigurableFileCollection.builtBy(Object... tasks) method which would solve my problem, if only it existed on the Configuration interface (configuration extends FileCollection)

aSemy
  • 5,485
  • 2
  • 25
  • 51
lance-java
  • 25,497
  • 4
  • 59
  • 101

3 Answers3

3

Do you really need a task to populate the configuration with dependencies?

Configuration#withDependencies can be used to add dependencies during resolution. Like this:

configurations {
  myConfig
}

configurations.myConfig.withDependencies {deps ->
  println "Resolving dependencies"
  dependencies {
    myConfig "log4j:log4j:1.2.17"
  }
}

task useMyConfig {
    doLast {
        println "myConfig = $configurations.myConfig.files"
    }
}
Eloff
  • 668
  • 7
  • 22
  • Thanks for your answer. Whilst this might seem to solve the problem, there is "work" involved with resolving the dependencies. I'd like to take advantage of Gradle's input/output hashing so that I can benefit from `UP-TO_DATE` checking. I want to split this into two tasks, the first task does some "work" and creates a gradle script. The second "applies" the gradle script. – lance-java Mar 23 '18 at 08:37
1

Not possible out-of-the-box. A task runs at most once.

When you call configurations.myConfig, you are calling a dynamic property added to the ConfigurationContainer

Using groovy, it should be possible to override the configurationContainers' behavior via the metaClass. You would be invoking a function here, not a task.

trevorism
  • 411
  • 2
  • 7
  • The "task runs at most once" rule is absolutely fine. I want the task to run only once per build (assuming configuration resolution required in the build). As with @eloff's answer I don't want to run a function, I want to run a task which does some "work" so I want to use input/output hashing and `UP-TO-DATE` functionality provided by tasks – lance-java Mar 26 '18 at 11:57
1

this is what you want i think:

def files = project.files(your,produced,files)
files.builtBy addToMyConfig
myConfig.dependencies.add(project.dependencies.create(files))
Lanchon
  • 343
  • 3
  • 7
  • sorry i'm one year late lol... however you solve it, it's individual dependencies -not configurations- that are builtBy. makes sense because deps are units of production while configs are units of consumption. thank you! – Lanchon Mar 29 '19 at 18:12
  • @Lanchon have you tried this code? I cannot get it working (Gradle 5.4.1). The `addToMyConfig` task is not executed when `myConfig` is requested. – Igor Melnichenko May 08 '19 at 10:16
  • Finally, I've discovered an interesting thing: configuration resolution itself doesn't take configuration dependencies into account. But if `useMyConfig.dependsOn configurations.myConfig`, dependency on `addToMyConfig` is propagated to `useMyConfig` and all works as expected. – Igor Melnichenko May 08 '19 at 10:39
  • with `useMyConfig.dependsOn configurations.myConfig` you are explicitly telling gradle to resolve myConfig before executing task useMyConfig. this is an unusual thing to do; why it is needed in your case depends on how you wrote useMyConfig. not to imply that something is 'wrong', but there is probably a more idiomatic way to write the task. if the task inputs depend on the config in a gradle-traceable way, gradle will create an implicit dependsOn relationship for you. – Lanchon Jun 26 '19 at 17:37
  • however, this matter is unrelated the original question on how to trigger a task on config resolution. (TL;DR you can't, AFAIK, but you can trigger a task on dependency resolution instead.) please mark as answered if applicable, thanks! – Lanchon Jun 26 '19 at 17:37