Copying files correctly

I use this task:

tasks {
    val deps by registering(Copy::class) {
        from(configurations.runtimeClasspath).include("*-all.jar")
        into("src/main/resources")
    }
    getByName("processResources").dependsOn(deps)
}

to copy a dependency jar to the resources file. Works, much to my amazement, given my minuscule Gradle-fu. But Gradle warns me that it has issues with how or what I am doing with this error message:


> Task :sourcesJar
Execution optimizations have been disabled for task ':sourcesJar' to ensure correctness due to the following reason:
  - Gradle detected a problem with the following location: '/Users/pmr/Projects/edgar/edgar-memoizer-launcher/src/main/resources'. Reason: Task ':sourcesJar' uses this output of task ':deps' without declaring an explicit or implicit dependency. This can lead to incorrect results being produced, depending on what order the tasks are executed. Please refer to https://docs.gradle.org/7.4.2/userguide/validation_problems.html#implicit_dependency for more details about this problem.

I read the linked material but am having great difficulty mapping it to a fix. Can someone explain/elaborate what is going on and what the fix is?

I also expect someone might be wondering what the the hell I am doing, as I think my approach might be unusual: I want my library to depend on a fat jar that can be runtime copied to a configuration folder and executed using “java -jar configuration/path/fat.jar”. If my approach is ham-fisted, I’m all ears for a better way.

Out of curiosity, why do you want to copy dependencies into the resources directory?

Anyhow, I think what you actually want is to add additional files to copy on the processResources task.

tasks.named<ProcessResources>("processResources") {
    from(configurations.runtimeClasspath) {
        include("*-all.jar")
    }
}

Thanks for offering another thought. I did try your suggestion but it had two new problems and did not work: 1) ‘org.gradle.language.jvm.tasks.ProcessResources’ is declared in unstable package ‘org.gradle.language.jvm.tasks’ marked with @Incubating; and 2) Execution failed for task ‘:processResources’.

Entry edgar-memoizer-app-0.9.1-all.jar is a duplicate but no duplicate handling strategy has been set. Please refer to Copy - Gradle DSL Version 7.4.2 for details.

As for your curiosity, I anticipated it in my original post and tried to explain my thinking, which is that I want to ensure that a required process is running without having the User install and start that program. “java -jar foo.jar” is about as simple as one can get to an automatic install and execute from a Java/Kotlin library. That said, someone may have a better idea and I am all ears for it.

You can ignore the warning about ProcessResources being in an unstable package. This message has been there for quite a long time. The worst thing that can happen is that someday you might have to make a minor change to your Gradle code when upgrading to some future version where that class is moved to a stable package.

As for the error about duplication strategy, you need to read the documentation in the link and do as the error message says to do. Keep in mind that ProcessResources extends the Copy class.

I was able to eliminate the warning and solve the error using this code:

tasks.processResources {
    duplicatesStrategy = org.gradle.api.file.DuplicatesStrategy.EXCLUDE
    from(configurations.runtimeClasspath).include("*-all.jar")
    into("src/main/resources")
}

Thank you for your help.

@pmr

You should not do into("src/main/resources"). You don’t want to add JARs to your source directory. What you actually want is that the JARs are copied as part of the compilation process. The processResources task already has a target directory into which things are copied during the compilation process, which is a nested directory under <project-root>/build. All you should do is add additional files to be copied with a from configuration (from(configurations.runtimeClasspath).include("*-all.jar")).

Yes, @EarthCitizen, you are correct. The final, full solution is the stunningly simple:

tasks.processResources {
    from(configuration.runtimeClasspath).include("*-all.jar")
}