Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Using plugins in conventions #10

Closed
Chasson1992 opened this issue Dec 11, 2022 · 3 comments
Closed

Using plugins in conventions #10

Chasson1992 opened this issue Dec 11, 2022 · 3 comments
Labels

Comments

@Chasson1992
Copy link

Chasson1992 commented Dec 11, 2022

Hello Jendrik,

I hope this is the appropriate forum to ask this question.

We have a large multi-project build, following much of the best practices outlined here and in the Gradle User Guide but I am struggling to understand the best practices for applying plugins to our conventions.

There are two ways in which I've applied plugins to our projects:

  1. Create separate convention plugins for each variant of the plugins to apply, as this repository has done under gradle/plugins/java-library-plugins

       In this case, I could end up with a considerable amount of conventions such as:

java-library-with-text-fixtures
java-library-published
java-library-with-jmh
java-library-with-text-fixtures-and-jmh
java-library-published-and-jmh
java-library-publish-with-text-fixtures-and-jmh

  1. Apply all the common conventions to all java-library projects

       In this case, I would minimize the amount of conventions plugins I need to write and when a developer creates a new subproject, simply applying java-library will give you access to things like JMH and Test Fixtures already configured and ready to be used.

       The issue I've found with using this technique is that the configuration time can be dramatically increased throughout the project. There might be subprojects that don't use JMH or Test Fixtures even though these plugins are being applied needlessly increasing the configuration time.

       I've been using the incubating configuration on demand feature and that has improved our configuration time.



This seems to be a trade-off between ease of use and build speed. I'm wondering your thoughts on the best way to approach applying plugins to our conventions in a large multi-project build.
@Chasson1992 Chasson1992 changed the title Using community plugins in conventions Using plugins in conventions Dec 11, 2022
@jjohannes
Copy link
Owner

Hi Connor,

Yes this is the appropriate place to ask and discuss such questions. I'll link interesting discussions in the FAQ section of the Readme.

From my perspective, both approaches are fine. However, I prefer the second: one java-library convention that includes everything. And then not use certain aspects in projects where they are not needed. I think this can reduce complexity of the build setup a lot. So I would aim for this if possible.

Sometimes, there are reasons why you can't do that. For example, if conventions contradict each other, or if two plugins you need can't be combined.

If it is only about configuration time performance, I would still try to stick with the one convention plugin approach and investigate if the configuration time can somehow be improved. In theory, only adding a plugin that does nothing should not add that much noticeable overhead (but yeah, in theory...).

Here are a few things you can look at regarding configuration time:

  • You shouldn't use configure-on-demand. It's a discontinued feature, which is buggy in certain scenarios. Instead, you should use the new configuration cache feature. This might already be enough to accept the configuration time overhead, as configuration is not done for every single build anymore.
  • If it feels like adding a certain plugin creates unexpected high overhead, you can get more insights on how much time which plugin takes through a Build Scan (--scan). For example, this is how it looks like for this project: https://scans.gradle.com/s/5hzrsg3my4m4i/performance/configuration
  • One common issue that increases configuration time when you have many "inactive" plugins, is that something in your build configuration breaks task configuration avoidance. The effect here is that a lot of objects are created and configured for tasks that are never used. An indication that there is an issue here is if the tasks created during configuration is high. There are unfotunately a lot of old (and not yer deprecated) APIs that can break configuration avoidance. For example tasks.all { ... } or tasks.withType(SomeTask) { ... }.
  • If you use third-party plugins and it turns out that one of those is causing the configuration time slowdown, it would be great to report this to the plugin maintainer.

Hope these are some helpful pointers.

@Chasson1992
Copy link
Author

Thanks for the response! This is great information.

@jjohannes
Copy link
Owner

Note: Much of the discussion here is based on the original structure of the example (https://github.com/jjohannes/gradle-project-setup-howto/tree/2022_java).

After working with this in several projects, I found that it is unnecessary complex and hard to understand for folks not being so deep into Gradle. I found that reducing the "Gradle boilerplate" and replacing the hierarchy of plugins by a "flat" structure where we keep most convention plugins as independent as possible, is the better setup for many projects (and the easier to start with).

This does not mean that other structures are "wrong". As I wrote in the comment above both approaches are good. It depends on the concrete project/setup which has more advantages.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants