How to access the properties of the base extension?

Up to now, I have always used project’s archivesBaseName property to set, well, the base name of the generated archives. Now I get a warning about this being removed. So I have replaced it with

base {
    archivesName = ...
}

However, in another task I read the value of archivesBaseName:

publishing {
    publications {
        maven(MavenPublication) {
            artifactId archivesBaseName        
...

Here it is not possible to replace archivesBaseName with base.archivesName:

> Failed to apply plugin 'org.jdrupes.java-library-conventions'.
   > org.gradle.internal.metaobject.AbstractDynamicObject$CustomMessageMissingMethodException: Could not find method artifactId() for arguments [extension 'base' property 'archivesName'] on object of type org.gradle.api.publish.maven.internal.publication.DefaultMavenPublication.

Of course, I do not want to maintain the name at two places. How can I access the value configured in the base extension?

I’ve found a solution:

publishing {
    publications {
        maven(MavenPublication) {
            def pub = it
            from components.java
  
            project.afterEvaluate {
                pub.setArtifactId(base.archivesName.get())

To be honest, this makes me having doubts about gradle being a good choice for a build automation tool.

To be honest, this makes me having doubts about gradle being a good choice for a build automation tool.

Why? Because you sprinkle in highly discouraged bad practices and then don’t like the look? I’d say that is expected. :smiley:
It imho is the best build tool that exists, but that is of course always a matter of taste.

As a start I’d highly recommend you switch to Kotlin DSL. By now it is the default DSL, you immediately get type-safe build scripts, actually helpful error messages if you mess up the syntax, and amazingly better IDE support if you use a good IDE like IntelliJ IDEA or Android Studio.

Using afterEvaluate { ... } is highly discouraged bad practice and should be avoided at almost any cost, because the main earnings you get from using it are timing problems, ordering problems, and race conditions. Unfortunately, as artifactId is not yet a Property but a String you might need to use afterEvaluate if you cannot control that it is set before it is read there.
But even then you only increase the likeliness that you get the correct value, but not a guarantee at all.
Hopefully with the great Property-isation in Gradle 9 this will improve.

But actually, it is also discouraged that you set the artifactId at all, because you mainly earn quirks from it later. As one example, if you (ore someone else) want to use the build in a composite build later, you will not be able to without then doing manual substitution rules which you would not need if you would simply use a proper project setup where the default works. (same for group and version)

So my recommendation would be to rename the project so that you simply neither need to set the archive base name nor the artifact id and all your problems are gone. If your reason is, that you don’t can or want to rename the directories on disk, that would not be a problem, as you the relation between project name and directory name is just the conventional default but is configurable in the settings script.

This reflects exactly my problems with where gradle goes. When I started using it, things were easy and simple to understand (e.g. set archivesBaseName on the project and everything works). By now, things have become so complicated (set base.archivesName but be aware that this cannot be read back until after the lifecycle has progessed and even then you have to add a .get() which is not intuitive at all) that “best practices” come down to a corset. If I wanted that, I would have used maven in the first place.

Stating that I should name the subprojects like the artifacts, else problems will simply be considered as something I have to live with because I’m not following “best practices” is not what I expect from a flexible build tool.

The specific problem here is that I’m building OSGi bundles. OSGi considers it “best practice” to name directories like the bundle names, which regrettably happen not to be the best artifact names (“maven artifact naming best practices”). See the problem?

I consider a build tool good if it allows me to use whatever naming, directory etc. schemes I think are appropriate for my project. Else, well, see above: maven…

Well, your view is exactly perpendicular to mine.

things were easy and simple to understand (e.g. set archivesBaseName on the project and everything works).

That was exactly not the case.
If you had plugin A which reads archivesBaseName,
plugin B which reads archivesBaseName,
applied plugin A, then changed the value, then applied plugin B,
then plugin A got the old value while plugin B got the new value.
Unless plugin A used afterEvaluate { ... } to read the value then it might have gotten the new value too.
Unless you for some reason used afterEvaluate { ... } to set it, then A and B go the old value even with plugin A using afterEvaluate { ... } to read it.

With archivesName being a Property<String> it can be wired to other properties that need the archives name and can then at execution time - where no configuration change can be done anymore - safely read the value and know that it got the ultimate correct value.

Unfortunately not all built-in API is yet changed to Property, but as I said in Gradle 9 this should hopefully improve extremely if not fully. But in this concrete case it is anyway a bad idea to manipulate the publishing coordinates manually.

So imho “where gradle goes” is the easier to use and understand behaviour, and the more safe and reliable behavior.

set base.archivesName but be aware that this cannot be read back until after the lifecycle has progessed

That’s not correct, you can “read it back” any time.
You just should not do it as you might miss later changes, exactly the thing I just described in this reply.
But just as before, if you have set it, you can immediately read the value again, no problem, it is just bad practice.

If I wanted that, I would have used maven in the first place.

No, you would use maven if you would want to not have power but be forced opinion on you and having a really hard time getting the build tool to do what you need or extend it.

With Gradle you have the power to easily do what you want and need to do.
But if you don’t like the way it evolves, feel free to use any of the other alternatives. :slight_smile:
No tool can ever satisfy the taste of every developer in the worlds unfortunately.
Would also be boring without a good holy war from time to time. :smiley:

Stating that I should name the subprojects like the artifacts, else problems will simply be considered as something I have to live with because I’m not following “best practices” is not what I expect from a flexible build tool.

It’s not what the build tool is telling you, it is what I and my experience are telling you.
If Gradle would not be flexible, you couldn’t set those values.
But as I said, great flexibility and power comes with great responsibility.
Just because you can shoot with a gun at a dog if you need to because it attacks you,
doesn’t mean you should shoot at any dog just because you can do it.
Same with features in any tool. Just because they are there and could be used if really needed because of some strange edge cases doesn’t mean you should use them in normal usage.
And if you do, you have to live with the consequences like having to pay compensation to the dog’s owner and being hated by all pet-lovers.
But if you are fine with the consequences, do whatever pleases you most, I’m just sharing my experience with you as that is what you are in this forum for.

See the problem?

Not really.
I never had problems with building OSGi bundles.
And I never named any directory after an OSGi bundle name or heard that you should do that.
At least not when building it with Gradle.
You basically just apply the biz.aQute.bnd.builder plugin and if you are not happy with the conventional bundle name, you set one property and be good.

I consider a build tool good if it allows me to use whatever naming, directory etc. schemes I think are appropriate for my project.

Well, it does.
See above. :wink: