Hey folks! I have a convention plugin `tv.twitch.g...
# community-support
h
Hey folks! I have a convention plugin
tv.twitch.gradle.plugins.android-library
that defines all of our
android {}
defaults. It naturally depends on `com.android.library`: `tv.twitch.gradle.plugins.android-library.build.kts`:
Copy code
plugins {
    ...
    id("com.android.library")
    ...
}

android {
    ...
}
We have a similar convention plugin for
com.android.application
. We define the version for
com.android.application
in our `lib.versions.toml`:
Copy code
[versions]
...
agp = "8.5.2"
...
[plugins]
android-application = { id = "com.android.application", version.ref = "agp" }
...
I just noticed that we don’t define a version for
com.android.library
anywhere. How can I find its version? I tried using the
buildEnvironment
task:
Copy code
classpath
+--- com.android.test:com.android.test.gradle.plugin:8.5.2
...
+--- tv.twitch.gradle.plugins.android-app:tv.twitch.gradle.plugins.android-app.gradle.plugin:1.13
|    \--- tv.twitch:plugins:1.13
|         +--- org.jetbrains.kotlin:kotlin-gradle-plugin:1.9.23 -> 1.9.25 (*)
|         +--- com.android.tools.build:gradle:8.5.2 (*)
|         +--- org.jlleitschuh.gradle:ktlint-gradle:12.1.1
|         +--- org.gradle.android.cache-fix:org.gradle.android.cache-fix.gradle.plugin:3.0
|         |    \--- gradle.plugin.org.gradle.android:android-cache-fix-gradle-plugin:3.0
|         |         \--- com.google.guava:guava:32.1.3-jre (*)
|         +--- org.barfuin.texttree:text-tree:2.1.2 (*)
|         \--- org.jetbrains.kotlinx:kover:0.6.1
+--- tv.twitch.gradle.plugins.android-library:tv.twitch.gradle.plugins.android-library.gradle.plugin:1.13
|    \--- tv.twitch:plugins:1.13 (*)
And this makes sense because we these are the dependencies we declare in the
dependencies {}
of the
tv.twitch:plugins
project. How do I resolve the version of
com.android.library
that
tv.twitch.gradle.plugins.android-library:tv.twitch.gradle.plugins.android-library.gradle.plugin
will consume?
Follow-up: I noticed in our root
build.gradle
that we alias all of the plugins we use in the whole project including both our convention plugins and
com.android.application
(but not
com.android.library
!):
Copy code
plugins {
    ....
    alias(<http://libs.plugins.twitch.android.app|libs.plugins.twitch.android.app>) apply false
    alias(libs.plugins.twitch.android.lib) apply false
    ....
    alias(libs.plugins.android.application) apply false
}
I this redundant? Since we don’t alias
com.android.library
, I feel like we don’t need to alias
com.android.application
either
I asked this on stackoverflow as well if folks want to get public credit: https://stackoverflow.com/q/79382044/9636
v
You don't "alias" it in the sense of "to alias" of that is what you meant. With these lines (and the "apply false") you add these plugins to the build script class path of that project. Some plugins do not like it if they are applied to multiple projects in the build without being on a common class loader like the root project's one, and sometimes this is necessary to get proper conflict resolution for transitive dependencies of different plugins. The answer to the original question which should also answer the follow up is, that both of these plugins live in the same code artifact, and as your added this code artifact to the root project class loader, both will be the same version and "aliasing" both would just be redundant but also not hurt.
thank you 1
h
But then how do I figure out which version of
com.android.library
I’m using? I don’t see a version defined anywhere in my project. (I suspect I’m using
8.5.2
somehow since that’s the
agp
version I’m using.
v
As I said, it is the same, yes, both plugins are part of the AGP
h
Thanks. I think I understand now. To restate: within my convention plugin project’s dependencies, I list the
agp
dependency, but
agp
contains many gradle Plugin classes, which I can reference without a version because the version is locked to
agp
.
Is this something that I only get when using convention plugins? I would expect that if I was doing this directly, I would need to alias the specific plugins, and I wouldn’t be able to reference AGP as a library.
I found this stackoverflow answer that almost does what I want, but it doesn’t print the plugin version or the actual plugin coordinates (like the
dependencies
task does)
v
because the version is locked to
agp
You can say it like that, yes. But better would be "they are part of agp and thus that's their version". 🙂
Is this something that I only get when using convention plugins?
No. If you do
alias(libs.plugins.android.application) apply false
or
alias(libs.plugins.android.library) apply false
in the root project script or in the settings script you do exactly the same. You add the code artifact for that plugin to the classpath, the code artifact is the AGP, and so all the plugins are available in that version. You could also instead add the AGP to the classpath using a
buildscript { ... }
block, but that is the legacy way and not recommended.
I found this stackoverflow answer that almost does what I want, but it doesn’t print the plugin version or the actual plugin coordinates (like the
dependencies
task does)
What is it that you want to do? The
dependencies
task shows your dependencies. That SO answer just lists the files in the buildscript classpath, so basically what
buildEnvironment
also does but just showing the files. If you do not print
it.name
but
it
you have the full path which will then also include the coordinates usually. Or you could use
.incoming.resolutionResult
to get the resolved tree and print the coordinates just like the
buildEnvironment
task. Of course neither of these things (including the SO answer) will show the parent class loaders like the class loaders from ancestor project class paths, from
buildSrc
, from settings script classpath, ... which could also all bring plugins into scope. And neither of the solutions will tell you which plugin ids are used. Well, if you do not depend on AGP directly, but on the plugin marker artifact (e.g.
com.android.library:com.android.library.gradle.plugin:8.5.2
) you should see that in the
dependencies
tree or in the
.incoming.resolutionResult
or in the
buildEnvironment
output, but no in the file-based solutions like the SO answer as those do only have a dependency but no artifact. But you could then still somewhere use "the other Android plugin" and it would not be visible in that output. To get the plugins on the classpath, you would probably have to iterate over the files and look for the plugin definition files in them. But even then you would not get the ones from parent class loaders, ... So what do you actually want to achieve?
h
What does
code artifact
mean? I’ve only heard of dependencies and plugins. Dependencies get referenced with a
group:name:version
coordinate, and plugins with an
id
and
version
. I tried googling for
gradle "code artifact"
, but since AWS’s repo product uses that name, it polluted my search.
So what do you actually want to achieve?
I want to understand the versions of all the plugins I depend upon. It doesn’t seem like there’s a report I can generate that tells me that the
com.android.tools.build:gradle:8.5.2
library dependency in my convention plugin defines the version for my
com.android.application
version
8.5.2
and
com.android.library
version
8.5.2
v
What does
code artifact
mean?
A dependency that contains the code for the plugin(s). It is not a fixed term.
thank you 1
I want to understand the versions of all the plugins I depend upon.
The easiest would actually be a build
--scan
if that is possible for you: https://scans.gradle.com/s/6bfuqh5yxuocw/plugins
h
Yep. I can see that in my scans. I just figured there must be some way to dump all the plugins just like there’s a way to dump all the dependencies
v
Obviously there is, as the develocity plugin does it. :-D But could well be that it uses internal API. Or maybe it gets the applied plugins and searches for the plugin marker files on the class path, picking one to show (there can be multiple pointing to the same plugin class) and then guessing from the file name the version or something like that. 🤷‍♂️ You can try to check what it does, but afair it is obfuscated, so you might have a hard time doing so.
h
Obviously there is, as the develocity plugin does it. 😄
Since I’m paying for develocity. I’ll just ask them. You’ve already gone above and beyond for community support. ❤️
👌 1
I’ll update the thread here with Gradle’s official answer
👌 1
Gradle Support’s official answer: > The
buildEnvironment
command will return the dependencies on the classpath of the project on which it is invoked. > > However, Gradle has a hierarchy of classloaders at play for any given project, based on the project hierarchy. So, as an example, all projects will inherit the classpath of the root project. >
buildSrc
also plays a specific role as its classpath is also made available via a parent classloader to all projects. > > We are aware of user requests for getting a better picture of the build environment for a given project but we do not have a direct answer for now. > > In your case, if you search for
com.android.library
in a build scan in the “Build dependencies” tab, you should be able to see in which project it is resolved. And then confirm that other projects do see it through the project hierarchy. One exception there would be the use of
buildSrc
where you would find that information in the regular “Dependencies” tab.