Exec Task is UP-TO-DATE when it shouldn't be


I’ve been working on getting our builds gradle-ized, and a coworker ran into this problem, and now I’ve hit it too. Here’s what we have:

def pullCommonDir = new File(buildDir, 'repo')
task pullCommon(type:Exec) {
    outputs.file "${pullCommonDir.path}/versions
    executable = 'perl'
    args = ['pull_common.pl', '-f']

The reason we have this Perl script is mostly for legacy but what you need to know is:

  • The script creates a file called ‘versions’ in the ‘repo’ folder, each time it’s run
  • Other things are in the repo folder too, but not really important to the question

Here’s the result of doing clean then pullCommon:

C:\Project> gradlew clean pullCommon
:pullCommon UP-TO-DATE

How does that work? Clean clears out the buildDir, but it says we’re still up to date?

I suspect that pull_common.pl sometimes doesn’t create ‘build/repo/versions’, but doesn’t fail either. In that case, the output file does not exist and the task completed successfully, so that looks like the output of the task is for ‘build/repo/versions’ to not exist. If that’s the case, just running gradlew pullCommon should also be up-to-date.

I’d check if pull_common.pl creates the path to the versions file, if it doesn’t, then I think perl silently fails to write anything.

If you don’t want to touch pull_common.pl, you could wrap this into a custom task (roughly something like this):

class PerlVersions extends DefaultTask {
   File getOutputFile() { 
      return new File(buildDir, "repo/versions") 
   def exec() {
      project.exec { // do perl thing 

And I think Gradle will automatically create the path to the output file this way.

Yup, I think you’re right on the money. I changed the pullCommon script to return 1 when there’s an error (it was returning 0 before for some reason), so hopefully I won’t run into this anymore. Sounds like I just have to force the task again, and I won’t run into this problem.