Better alternative for "preserveFileTimestamps = false"?

I have a task like this:

task transformJarFromOtherProject(type: JavaExec) {
	main = 'org.myCompany.MyTransformer'
	classpath = configurations.otherProject + configurations.runtimeClasspath
	args '--outout-dir', someOutputDir

	inputs.files({ zipTree(configurations.otherProject.singleFile).sort() })
			.withPathSensitivity(PathSensitivity.RELATIVE)
	outputs.dir someOutputdir
	outputs.cacheIf { true }
}

While this does cache the build output, it feels hacky. Or is it okay like that? I don’t know if I break anything with the .sort() call. One thing for sure it’s a small jar so the sorting has no significant overhead.

I know you can just add this in the other project:

jar {
    preserveFileTimestamps = false
    reproducibleFileOrder = true
    // ...
}

But then the timestamps in the jar look weird, so that solution also feels hacky. So what can I do to enable build caching, keep best Gradle practices, and not change the build output in a way that can confuse my project team?

Thanks in advance.

Hi,

it looks like your input is actually something resembling a classpath? So maybe you want to use

inputs.files(configurations.otherProject).withNormalizer(ClasspathNormalizer)

The classpath normalizer already will then only care about the contents of the JAR file.

Since you already added configurations.otherProject to the classpath of the JavaExec task you actually don’t need to add it again as an input via input.files, since the classpath is already an (@Classpath) input.

So no need to use reproducible JARs.

Cheers,
Stefan

1 Like

Thanks for the tips, @Stefan_Wolf. In my real code, the jar is not added to the task classpath actually, but passed as an argument, long story, nevermind, just wanted to simplify my example, anyway I’m grateful that you told me about both options. I will try the normalizer.

Update: Worked wonderfully.

@Stefan_Wolf, sorry for pinging you again. Now I got a similar problem but with annotations:

class MyTransformerTask extends DefaultTask {
    @InputFiles
    @PathSensitive(PathSensitivity.RELATIVE)
    FileCollection inputFiles
}

And I use the task like this:

task myTransformer(Type: MyTransformer) {
    inputFiles = zipTree configurations.myJar.singleFile
}

Is there any way to normalize this too? I am using Gradle 5.6, checked the documentation deeply. The @Classpath annotation didn’t work.

Edit: Sorry, actually I was using Gradle 5.5. After upgrading to 5.6, it worked.

There currently isn’t a way to normalize this. There may be at some point in the future.