I’m trying to make an <artifact transform> where I...
# plugin-development
c
I’m trying to make an artifact transform where I want to transform one single dependency/jar rather than than every jar in the configuration. I thought it would be possible to add the attribute to just one Dependency object in the Configuration - so then only that dependency/jar would get transformed - but `Dependency`s have immutable attributes:
Copy code
Caused by: java.lang.UnsupportedOperationException: Mutation of attributes is not allowed
	at org.gradle.api.internal.attributes.DefaultImmutableAttributes.attribute(DefaultImmutableAttributes.java:116)
Is there any way to do this?
ok, getAttributes returns an immutable copy - using
attributes(…
instead allows me to add it, but it still doesn’t run the transformation.
v
You should be able to modify the attributes if you do it the right way. But you could also just do a condition in your transform, so that for all other artifacts it just does an identity transform, adding the input artifact as output artifact directly and thus doing nothing.
If you want to get your attribute approach working, you probably have to provide an MCVE
👍 1
c
mmm, I was doing that before but I only get access to the filenames, which feels a bit fragile - also maybe a bit wasteful, even if it only is copying a small number of jars
v
It does not copy, it just takes the original file in an identity transform
But yeah, only having the file name and not the coordinates is tracked at https://github.com/gradle/gradle/issues/11831
👀 1
c
I think I’m missing some context about the identity transform - given my
TransformAction
only gives me a
TransformOutputs
, don’t I need to call
outputs.file(name)
then copy to that location?
for the jars I don’t actually want to change
v
outputs.file(inputArtifact)
, fullstop
c
oh nice
ah,
Object
heh
do you want me to make a github issue too?
v
For what?
Besides that I'm just a user like you
c
oh, I see 😆
v
In line 25 you are not setting the attribute to be
false
, you are requesting the attribute to be
false
for that dependency
To set it to
false
for all jars, you for example miss
Copy code
diff --git a/build.gradle b/build.gradle
index 5eba4c1..4b6e9de 100644
--- a/build.gradle
+++ b/build.gradle
@@ -20,12 +20,12 @@ dependencies {
         attribute fooAttribute
     }

-    annotationProcessor('com.google.guava:guava:31.0.1-jre') {
-        attributes {
-            attribute fooAttribute, false
-        }
+    artifactTypes.getByName("jar") {
+        attributes.attribute(fooAttribute, false)
     }

+    annotationProcessor('com.google.guava:guava:31.0.1-jre')
+
     registerTransform(TransformThrows) {
         def artifactType = Attribute.of("artifactType", String.class)
         from.attribute(fooAttribute, false).attribute(artifactType, 'jar')
@@ -44,4 +44,3 @@ task resolveConfigurationAndHopefullyRunTransformAndThrowException {
         configurations.annotationProcessor.resolve()
     }
 }
c
yep - but this ends up trying to run the transform on all the jars:
Copy code
Failed to transform checker-qual-3.12.0.jar
Failed to transform error_prone_annotations-2.7.1.jar
etc
rather than just on guava
it makes sense to set it all to
true
for all jars as we don’t want to transform them - code to do this (and then have guava with it’s own attribute set to
false
), which if we do here results in this exception:
Copy code
> Could not resolve all files for configuration ':annotationProcessor'.
   > No variants of com.google.guava:guava:31.0.1-jre match the consumer attributes:
       - com.google.guava:guava:31.0.1-jre configuration runtime declares a library for use during runtime, packaged as a jar:
           - Incompatible because this component declares a component, as well as attribute 'foo' with value 'true' and the consumer needed a component, as well as attribute 'foo' with value 'false'
which is a better error - but it hasn’t actually run the transform to move to the correct attribute
(I imagine this is a gradle bug)
v
Again, setting the attribute like in your MCVE says "I want this dependency with the attribute set to false", not "right now it is false, now run an artifact transform".
c
ah
similar to on the configuration, I guess that makes sense
v
Exactly
c
a “requesting attribute” rather than a “providing attribute”?
v
If you want to say it like that
You might maybe be able to use a component metadata rule to set it to
false
for only that dependency. But I'm not sure whether this will be considered for input to the artifact transform.
If not, you might need to pump all jars through the transform and just make it an identity transform for all other jars as stated way up in the thread.
c
yeah, I think I’ll just do that, thanks for all your help!
👌 1
v
Ah, no component metadata rule will not work, as that sets the attribute on the component, not on the artifact. And then it cannot be resolved up-front and thus no artifact transform can be done. For that you would need https://github.com/gradle/gradle/issues/8386