Artifact builder task not invoked when resolving configuration

Hi,
I’m trying to do something similar to this ( Artifact builtBy task is not called when resolving a configuration ), where a project exposes artifacts through a configuration that is consumed by another project as a dependency, using

implementation(project(":builder"), configuration = "builderConfig")

From linked question, I understand that the artifact builtBy task is not automatically invoked (I don’t understand why it couldn’t, but let’s skip on this).

However, I create the artifact using outputs from the builtBy task, with lazy evaluation:

val builderTask = tasks.register("builderTask") {
    outputs.file("some_file")
    doLast { /* produce the file */ }
}

artifacts {
    add("builderConfig", builderTask.map { it.outputs.files.singleFile() }) {
        builtBy(builderTask)
    }
}

This artifact notation (a Provider that resolves to a File) is listed in ArtifactHandler as legit, and the javadocs there explicitly say:

A {@link org.gradle.api.provider.Provider} of {@link java.io.File}, {@link org.gradle.api.file.RegularFile} or {@link org.gradle.api.file.Directory}. The information for publishing the artifact is extracted from the file or directory name. When the provider represents an output of a particular task, that task will be executed if the artifact is required.

Shouldn’t my task be executed when the configuration is resolved by the consuming project? If not why, and how can I achieve what I want - executing the task automatically when resolving the configuration?

The configuration is consumed in another project by a plugin (Android Gradle Plugin), so there’s no task that I could add a “dependsOn” to builderTask. For those who know AGP, it fails in the jetifier step.

Caused by: java.io.FileNotFoundException: /my/file/path/some_file (No such file or directory)
at kotlin.io.FilesKt__FileReadWriteKt.readBytes(FileReadWrite.kt:63)
at com.android.tools.build.jetifier.processor.Processor.transform2(Processor.kt:257)
at com.android.build.gradle.internal.dependency.JetifyTransform.transform(JetifyTransform.kt:129)
… 86 more

In general this should work. two remarks regarding your snippets.

in your dependency declaration there’s a typo.

instead of

implementation(project(":builder"), configuration = "builderConfig")

it should be

implementation(project(":builder", configuration = "builderConfig"))

Also you need to declare the builderConfig and singleFile should be accessed like a property

// declare a "configuration" named "builderConfig"
val builderConfig by configurations.creating

val builderTask = tasks.register("builderTask") {
    outputs.file("some_file")
    doLast { /* produce the file */ }
}

artifacts {
        // you don't need the builtBy as gradle figures that out itself
        add("builderConfig", builderTask.map { it.outputs.files.singleFile })
}

cheers,
René

Thanks, that was a typo and I also create the configuration. But still it doesn’t work.

I have spent a lot of time on this and I am starting to feel confident there’s a bug somewhere, just not sure whether in Gradle or in the Android Gradle Plugin. The Android Gradle Plugin registers an artifact transform called JetifyTransform which receives a list of files like this

@get:InputArtifact
abstract val inputArtifact: Provider<FileSystemLocation>

Yet my specific file does not exist when the transform is invoked, because the source task was not executed. What can I do to investigate more? Does gradle deal correctly with artifact transform in this case?

I have also posted:

but I don’t expect any answer from them before the usual three weeks or so. Any hints @Rene ?

I have created a simple repro project here: https://github.com/natario1/gradle-transform-bug
You can see that consumer:consumeAar fails unless you call producer:produceAar first.

consumeAar should declare an input on something that resolves the implementation configuration. For example, inputs.files(configurations.compileClasspath) (I have no idea if the kotlin syntax looks different).

@Chris_Dore thanks for your answer - I have added a “consume task” just for demonstration, but in practice I don’t have one, the file is meant to be consumed by the Android Gradle Plugin internally.

Even the “Gradle sync” option in Android Studio / Intellij (not sure what it means in Gradle terms, I guess it simply evaluates projects) fails, so before you could even run your own task.

Basically when applied on top of the build file, the AGP (com.android.application) registers the artifact transform I mentioned earlier and this fails when executed. Am I missing something? Shouldn’t the artifact transform be passed a list of resolved files, thus invoke my task?