I have an issue relating to failing to generate Ko...
# dependency-management
k
I have an issue relating to failing to generate Kotlin accessors, owing to some kind of dependency issue. It's rooted in code that looks like this
Copy code
val configuration = configurations.register("something") {
  defaultDependencies {
    add(project.dependencies.create("foo:bar:1.0"))
  }
}

ant.taskdef("someAnt", "my.ant.AntType", configuration.get())
The error is resulting from a
ModuleNotFoundException
, saying
Copy code
Cannot resolve external dependency foo:bar:1.0 because no repositories are defined.
Yet, the plugin is being applied (transitively) to a project for which repositories are defined. Anyone have any insight?
v
To generate the kotlin accessors the
plugins { ... }
block is transplanted to a dummy project, configured, and then inspected for the stuff that was added by those plugins to generate accessors for them. If applying to that dummy project fails, accessor generation fails. And as that piece of configuration is executed at configuration time with no repositories defined in that dummy project, the resolution of that configuration failed. The question is, why that taskdef is done at configuration time. It should probably be done at execution time of a specific plugin task so that it also is not done without needing. That would also cause the configuration to not be evaluated prematurely. Besides that it also makes little sense to create a configuration in user-space with default dependencies when resolving it right away during configuration phase. Then also a detached configuration could have been used. Not that that would change anything regarding missing repositories during accessor generation
k
That's a design oversight on my end, since I couldn't figure out a way to implement
AntBuilder.taskdef()
without jumping the gun (ie. resolving the configuration only as needed).
v
Well, if you need to call it at configuration time you probably cannot. But if you don't need the task at configuration time, you probably also shouldn't do the taskdef at configuration time. 🙂
I played with it myself not too long ago and iirc found out when I use
Copy code
"classpath" to antTaskClasspath,
"loaderref" to antTaskClasspath,
it does not hurt to do it on each task invocation as the same instance will be reused as long as the full classpath stays the same
k
Interesting. I was fearing duplicate taskdef would create issues, but as long as I have a plugin that creates the configuration and provides a Kotlin extension function to idiotproof the taskdef (and more extension functions to invoke the ant task), it should be fine, then.
v
It was worse for me as I wanted to use ant within a worker api task. And unfortunately there you cannot yet get the Gradle ant builder. So I'm forced to use the groovy ant builder which misses some Gradle optimizations. Also in the very beginning with just creating a new one on each task, immediately the RAM busted. Then I created one thread-local ant builder per classpath to not have task defined multiple times from different class loaders. And recently I gave the whole situation a new evaulation and played some more with it and found out iirc, that a thread-local Groovy ant builder with using
loaderref
is sufficient to achieve what is necessary in an efficient way.
You can easily check by outputting the ant tasks classloader to see whether it is the same from multiple invocations, or not