tags:

views:

1119

answers:

5

It seems like building a jar or zip from the exact same source files will always yield a different file. I tried this both using the java jar command, and the jar and zip tasks in ant.

It appears to be due to the fact that new jars/zips have the timestamp set to the current time on each stored file.

Is there a way to force a zip tool to simply use the timestamp on the file on the filesystem to ensure that a jar built from the exact same source will appear exactly the same?

+1  A: 

What happens when you set update="true" to tell Ant to only update the file, and not re-create it from scratch? Does that change the file creation timestamp?

matt b
note that update="true" corresponds to the -u option to zip
pjz
This does work. It isn't exactly what I had in mind, since I wanted a way to regenerate the exact same file given the original source, and not have to hang on to the packed binaries.
Mike Miller
A: 

I don't think there's a way to make zip do that, but you could certainly hammer the timestamps on the files on the filesystem to a known date (using the 'touch' command under unix - I dunno what under Windows) before you create the jar.

pjz
there are touch utils available on Windows. But this would not solve the problem, as I understand it. The question seems to say that the entries within the zip get the CURRENT TIME, rather than the time on the file. Touch won't fix that.
Cheeso
No, the real problem is that if you regen a file - even if you generate it with the same contents - it gets an mtime timestamp of the last regeneration, so if you then zip that file, since the zip stores the mtime, it will be different even though the contents are the same.
pjz
Cheeso is correct. Even taking the exact same source files and building a jar twice will cause the timestamps inside the jar to change.
Mike Miller
A: 

I had a similar problem and, as pjz suggests, I solved it by 'touch'-ing the files before adding them to the jar (so, it worked for me :-) ). You can find touch for Windows, if you need it, either in the GNU Windows Utilities, core utils: http://gnuwin32.sourceforge.net/packages/coreutils.htm , but it's a big package for just this single one (though there are many other useful utilities there you may like), or alternatively, download something like http://www.softpedia.com/progClean/Touch-for-Windows-Clean-41086.html .

Gadi
I tried this first, sadly, this does not work. See Cheeso's comment above.
Mike Miller
A: 

Ok, a coworker and I came up with a solution that works for us.

Instead of reengineering our entire build process to not delete any class or jar files, we use this procedure:

  1. Build new artifacts.
  2. Use jardiff (part of jnlp) to compare changes from previous build.
  3. If the diff jar that jardiff produces has no changes, get artifact from previous build.

Yeah, I know it sounds kludgy, but it sure beats rewriting build script to take this into account. Also, we can do a completely clean build on a fresh machine (in the case of server failure), and this process will ensure that only actually updated jars are produced.

Mike Miller
A: 

The binary difference is because of the timestamp of the manifest files. If you let jar create a manifest itself it will create a manifest on the fly and set the created manifest to currentTimeMillis.

You can solve it by:
1. Do not add a manifest (if your using ant you must use zip instead of jar)
2. Add the manifest like you add normal files. (So the manifest is a file on your filesystem and it isn't created on the fly)

Kees