Clean task removes too much when using global fixed buildDir

I’m attempting to convert an existing project to Gradle, and one of the restrictions is that the buildDir for all projects be defined to an absolute path globally (so all jars end up in the same place).

This works fine, although running ‘clean’ from a subproject removes the global buildDir, instead of removing just the artifacts generated from that project.

Here’s a repro case:

$ find * -type f
build.gradle
proj1.1/src/main/java/org/gradle/example/simple/HelloWorld11.java
proj1.2/src/main/java/org/gradle/example/simple/HelloWorld12.java
proj2.1/src/main/java/org/gradle/example/simple/HelloWorld21.java
proj2.2/src/main/java/org/gradle/example/simple/HelloWorld22.java
settings.gradle
  $ cat settings.gradle
 include 'proj1.1'
include 'proj1.2'
include 'proj2.1'
include 'proj2.2'
  $ cat build.gradle
 subprojects {
    apply plugin: 'java'
    buildDir = new File(rootProject.projectDir, "/build-global")
}
  $ gradle -q jar
  $ find build-global -type f
build-global/classes/main/org/gradle/example/simple/HelloWorld11.class
build-global/classes/main/org/gradle/example/simple/HelloWorld12.class
build-global/classes/main/org/gradle/example/simple/HelloWorld21.class
build-global/classes/main/org/gradle/example/simple/HelloWorld22.class
build-global/libs/proj1.1.jar
build-global/libs/proj1.2.jar
build-global/libs/proj2.1.jar
build-global/libs/proj2.2.jar
build-global/tmp/jar/MANIFEST.MF
  $ (cd proj2.1 && gradle -q clean)
  $ find build-global -type f
find: build-global: No such file or directory

As you can see, the ‘clean’ task run from proj2.1 removed the entire buildDir.

I would like to achieve an effect where ‘clean’ just removes the files of the current project. Is this possible? Other approaches you might suggest?

Thanks for your help!

Hmm, I wouldn’t recommend what you’re trying. It’s going to break some other things (up-to-date checks and incremental builds), since we assume that the project’s buildDir isn’t shared like that.

If you just need all of the jars in one place at the end, could you just add that as a final build step? e.g.,

task publishToGlobal(type: Copy) {
   from (jar)
   into "$globalBuildDir/libs"
}

And run ‘gradle publishToGlobal’.

Are you using the global build dir for dependencies?

I’m not too surprised that isn’t recommended. :slight_smile:

The actual case involves the use of the GradleFX plugin, and producing .swc and .swf files in the global build dir for runtime interactive testing purposes. I just reduced this to a simple case above using jars instead.

As for dependencies, I am using the proper conventions by depending on other projects.

The publish step you’ve suggested looks reasonable, if the copied file can be removed when clean is issued for a project – got an idea how to accomplish that?

Thank you!

Ah, good :}

I think that the Copy task’s clean is going to want to delete the final directory, so I think you have to basically have a list of all the files that would have been copied (the final destination paths) and create a clean task of type Delete that would delete them.

Do you think I could perform the copy in a doLast() section? I want to make it automatic as opposed to a separate task.

I’m not sure how I’d locate the resulting archive file to copy though (still coming up to speed with Gradle/Groovy) – any suggestions?

Thanks for your help, -Marc

if you really want to customize your own clean task , why not just overwrite the core clean task

task clean (type: Delete, overwrite: true){
    delete "$buildDir/classes"
}

Please correct me if I misunderstood your mean.

Regards, Taymindis, Gradle FaNS

@marc

You could do it in a doLast {} on the build task (jar or whatever archive you have), but that means it’ll run every time the task runs and won’t run again if someone deletes the files from the global directory.

I was thinking that it was better to use a separate task because you’d want to only run that copy sometimes (e.g., as part of a CI build) vs on every developer’s workstation. So it’s “optional”.

Since you’re going a little backwards, you might try something like this (just typed this up off the top of my head, so apologies if it doesn’t work right away):

task publish(type: Copy) {
   from(archiveTask, archiveTask2)
   into globalDir
}
  task cleanPublish(type: Delete) {
   delete {
      // build list of file names that we create in the archive tasks
      def archiveFiles = [ archiveTask, archiveTask2 ].collect { it.outputs.files.singleFile.name }
      // build a file collection filtered to only contain files with the same name as above
      fileTree(dir: globalDir).filter({ it.name in archiveFiles })
   }
}

Thanks for the tips, Taymindis & Sterling!