Defining subproject dependencies for particular artifacts

Oh, wait, my solutions also do not have the necessary task dependency. :-/
Now the question is whether we stumbled upon a bug or whether something in alpha-beta is wrong.

I don’t see where it might be wrong.
This in :alpha:ee makes it work as expected with my three variants:

configurations.mainSourceElements {
        .find { == "transformed-sources" }
        ?.apply {
            this as ConfigurablePublishArtifact

But clean is different. :-/

Me again.

I thought I’d start over with a minimal repository that demonstrates the sorts of things I need to be able to do in the real repository. This has two advantages. First, it’s a whole lot simpler and I can work through the things one at a time. Second, I can publish it so you can look at it and laugh.

I’ve switched to Kotlin. I’ve tried to follow the advice given above in this thread. There’s no doubt a bit of weirdness here and there. All of the “real” Java sources are under java/src rather than distributed across java/he/src, etc. because they need to be (reasonably) easy to access “as is” for debugging.

My first baby steps were to get the three subproject builds working. That seems to work. Next, I thought I’d experiment with a source dependency between projects. The :java:keys subproject makes some Java files that :java:he needs. I tried to make my own artifact types for this, but it all sort of fell apart. I decided I could be just as happy relying on mainSourceSets so I reconfigured the keys build to make the constructed sources part of the main source set.

All well and good so far, the :java:keys:featureKeys task builds the output and if I then run :java:he:preprocessJava, it pulls those sources into the build. But if I delete java/keys/build and then re-run the java:he:preprocessJava task, it doesn’t run the keys task first.

I’ve tried to setup the dependencies, but I’ve clearly done something wrong. Is it obvious what?

Well, you ignore the bug I discovered during this thread. Just look at my last comment here for the bug and a workaround.

Overlooked, perhaps, or misunderstood. I’d never ignore you :slight_smile:

Thank you. That worked and I’m on to the next challenge…

1 Like

It turns out that I don’t want the keys project to be a java-library. Yes, it generates some Java code, and that seems to be fine in the test project, but in the real case, that code won’t compile indpendently. Okay, I thought, I can take what I’ve learned here, plus what’s in the “Sharing outputs…” page and figure this out. I was not successful.

In java/keys/build.gradle.kts,

  1. I tinkered with the script that generates the java so it won’t compile in situ.
  2. I’ve removed the java-library plugin and the machinery that relies on it.
  3. I added a featureKeys configuration along the lines outlined for sharing artifacts
  4. I made it extend a configuration that depends on the generated files.
  5. I changed the attempt to establish the build dependency:
// See:
configurations.named("featureKeys") {
        .find { == "java" }
        ?.apply {
            this as ConfigurablePublishArtifact

Now, in the java-library version that worked, that was configurations.mainSourceElements, but when I tried configurations.featureKeys, that didn’t work. I worry that there’s a detail there I don’t understand. I have no idea what makes mainSourceElements a “dottable” name.

I tried to explore the outgoing artifacts and it does appear that the outgoing artifact is still named “java”, but it’s not clear to me how or why.

Then in java/he, I updated the featureKeysBucket to have a mapping specifically to the featureKeys configuration in the :java:keys project.

If I explicitly run the :java:keys:featureKeys task, then run the :java:he:helloWorld task, I can see that the featureKeysSources are the files I expect them to be. But if I delete the :java:keys build directory and run the “hello world” task, Gradle doesn’t run the feature keys task, so the list is empty.

I’ve failed to get the dependency working. If you can see why…

(I have updated the GitHub project mentioned above to include this hackery.)

Yeah, I think you mix a few things together.

I have no idea what makes mainSourceElements a “dottable” name.

For things that are created by plugins you apply using the plugins { ... } block, you get type-safe accessors.
So e. g. if you apply the java-library plugin, this creates the mainSourceElements configuration, and so in your build script you can use the type-safe accessor configurations.mainSourceElements.
For configurations you create in your build script, Gradle cannot know which accessors to generate, so there are none.
But this is also not really necessary. You have the configuration in the variable featureKeys, so there is no need for a type-safe accessor or for using configurations.named("featureKeys"), you can just use your local variable featureKeys where you already have the configuration at hand.

Same for others like transform.

I don’t think your javaSources configuration makes much sense. You do not want to “depend on sources”, you want to publish the sources, so what you want is to define the sources as outgoing artifacts on the featureKeys configuration.

You can always also check the outgoing configurations and their artifacts using the task :java:he:outgoingVariants.

As you are on a recent Gradle version, you should also not use by configurations.creating.
Without any configuration of consumable and resolvable this is legacy, deprecated, and discouraged anyway, like you have for transform and javaSources. If you create configurations like that, you should always set one or both of the propertiest to false, according to the role of the configuration.

But as you are on a recent Gradle version, you can anyway use the new convenience methods to create properly roled-configurations as you do in the other files.

And you also do not need the #27578 work-around when not using mainSourceElements.

This should do what you want I think:

diff --git a/java/keys/build.gradle.kts b/java/keys/build.gradle.kts
index 6064343..dc9115c 100644
--- a/java/keys/build.gradle.kts
+++ b/java/keys/build.gradle.kts
@@ -11,25 +11,21 @@ repositories {
   maven { url = uri("") }

-val transform by configurations.creating
-val javaSources by configurations.creating
-val featureKeys by configurations.creating {
-  isCanBeConsumed = true
-  isCanBeResolved = false
-  extendsFrom(configurations["javaSources"])
+val transform by configurations.dependencyScope("transform")
+val transformClasspath by configurations.resolvable("transformClasspath") {
+    extendsFrom(transform)
+val featureKeys by configurations.consumable("featureKeys")

 dependencies {
-  javaSources(files(layout.buildDirectory.dir("java")))

 val featureKeysTask = tasks.register<JavaExec>("featureKeys") {
-  classpath = configurations.named("transform").get()
+  classpath = transformClasspath
   mainClass = "net.sf.saxon.Transform"
@@ -40,13 +36,4 @@ val featureKeysTask = tasks.register<JavaExec>("featureKeys") {

-// See:
-configurations.named("featureKeys") {
-    outgoing
-        .artifacts
-        .find { == "java" }
-        ?.apply {
-            this as ConfigurablePublishArtifact
-            builtBy(featureKeysTask)
-        }

Thank you. That’s worked and I’ve been able to make it work for some other things. It’s very frustrating that I’ve read the ‘Sharing outputs’ documentation page at least a dozen times and I could neither work out the recipe you provided nor really work out why it works. But perhaps I’m missing some crucial bit of context.

Thank you again!

Don’t worry, the whole variants, artifacts, and artifacts transform topic is quite complex and I also needed quite some time to wrap my head around it. But once you come over break-even, it is super useful and not that frustrating anymore. :smiley: But I also still want to hit my head to a wall sometimes like yesterday. :smiley: