bndtools / bnd

Bnd/Bndtools. Tooling to build OSGi bundles including Eclipse, Maven, and Gradle plugins.
https://bndtools.org
Other
527 stars 305 forks source link

Builder Gradle plugin does not support Gradle's new configuration cache #4682

Closed chrisr3 closed 2 years ago

chrisr3 commented 3 years ago

I have tried to use Gradle's new configuration cache with Bnd's builder plugin. However, Gradle complains that the plugin is invoking Task.getProject() during Gradle's task execution phase. This is incompatible with the configuration cache:

org.gradle.api.InvalidUserCodeException: Invocation of 'Task.project' by task ':jar' at execution time is unsupported.
        ...
    at aQute.bnd.gradle.BundleTaskConvention$_buildBundle_closure3.doCall(BundleTaskConvention.groovy:234)
        ...
        at aQute.bnd.gradle.BundleTaskConvention.buildBundle(BundleTaskConvention.groovy:228)
        ...
        at aQute.bnd.gradle.BndBuilderPlugin$_apply_closure1$_closure2$_closure6.doCall(BndBuilderPlugin.groovy:59)

I am using Bnd 5.3 with Gradle 6.9 here, and it looks like the problem is the project property:

    task.configure {
      def projectDir = unwrap(layout.getProjectDirectory())
      def buildDir = unwrap(layout.getBuildDirectory())
      // create Builder
      Properties gradleProperties = new PropertiesWrapper()
      gradleProperties.put('task', task)
      gradleProperties.put('project', project)

Could the configure closure be accidentally hiding the convention's own project property by changing the meaning of this?

bjhargrave commented 3 years ago

TL;DR: The Bnd Gradle plugins will not support the gradle configuration cache.

I have put significant effort into attempting to support gradle's configuration cache for Bnd 6.0 including more use of gradle properties and other changes. However, after all the work, Bnd still needs live objects to build, baseline, export, resolve, etc. Gradle's configuration caching requires all object to be serializeable into the cache and deserializable out of the cache and Bnd's object model is not serializable and cannot be made so without significant effort. That effort would not benefit Bnd use in Maven or Eclipse, so I do not see such an effort happening. So the Bnd Gradle plugins will not support gradle configuration caching.

I am using Bnd 5.3 with Gradle 6.9 here, and it looks like the problem is the project property:

In this instance, we need the Gradle Project and Task objects to be able to resolve ${project.xxx} and ${task.xxx} properties in the bnd file. Such property references can be mapped into method calls on the Gradle Project or Task object. For example,

https://github.com/bndtools/bnd/blob/fe81f50bec892f2db530b59e7744d0156a5204cb/biz.aQute.bnd.gradle/testresources/builderplugin1/bnd.bnd#L6-L7

https://github.com/bndtools/bnd/blob/fe81f50bec892f2db530b59e7744d0156a5204cb/biz.aQute.bnd.gradle/testresources/builderplugin2/build.gradle#L49-L51

See PropertiesWrapper which uses Groovy's dynamic method invocation to obtain properties via bean-like method calls. To remove the reference to the Gradle Project object at execution time, we would need to remove support for ${project.xxx} properties in the bnd file. This is just one example of the issues here. Other Bnd Gradle plugins will have other issues which require access to Bnd live objects. So there is no easy solution here and therefore, Bnd Gradle plugins will not support configuration caching.

bjhargrave commented 2 years ago

A fix is coming for 6.1.

bjhargrave commented 2 years ago

See https://github.com/bndtools/bnd/blob/master/gradle-plugins/README.md#gradle-configuration-cache-support for information on how to configure the Builder plugin for the Configuration Cache.