-
-
Notifications
You must be signed in to change notification settings - Fork 14.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Tracking issue: non-deterministic java apps #278518
Comments
yes please! |
Excellent work. |
Changes: - use `finalAttrs` instead of `rec` - use `canonicalize-jars-hook` (related issue: NixOS#278518) - patch `.desktop` files to find icons - add `meta.mainProgram`
Changes: - use `finalAttrs` instead of `rec` - use `canonicalize-jars-hook` (related issue: #278518) - patch `.desktop` files to find icons - add `meta.mainProgram`
* use finalAttrs instead of rec * shorten url * use hash instead of sha256 * use canonicalize-jars-hook (related issue: NixOS#278518) * add meta.mainProgram
* use finalAttrs instead of rec * shorten url * use hash instead of sha256 * use canonicalize-jars-hook (related issue: #278518) * add meta.mainProgram
I was looking around on nixpkgs and it looks like nixpkgs/pkgs/by-name/jo/jogl/package.nix Lines 80 to 82 in daafb12
It's adding a fixed modificationtime attribute to the jar task.Docs of the jar ant task: https://ant.apache.org/manual/Tasks/jar.html
After some more looking, it turns out that even the
This will create a jar file with all files inside having the set timestamp. Though this is not in the older versions of java. The first version to have this inside nixpkgs is After some more searching, it looks like
So, in conclusion, it looks like every major way of packaging has a built-in solution for fixed timestamps. I am a bit sad that I did not look into this more thoroughly earlier. |
I went with the general solution instead anyways |
It might also be helpful to have a tool to detect common pitfalls in making Java packages deterministic. For example, we could find all jar files in the outputs and inspect them for timestamps that suggest non-determinism. We could then cause that build to fail unless some sort of "allowNondetermism = true" flag is set. This could be a setuphook but at some point we may want a |
A new thing I discovered was the existance of |
There are several ways to package a Java app inside Nixpkgs, and most of those package the final app into a
.jar
file. However,.jar
files are not reproducible/deterministic by default.How to check for reproducibility?
Why are
.jar
files not deterministic?When creating a
.jar
file Java will place aMETA-INF/MANIFEST.MF
file inside the archive which will have the current date as its creation date, so it's non-deterministic.There also might be a problem with the fact that changing a
.properties
file during the build process will put the current timestamp inside the file as a comment. These can usually be patched out without too much of a hassle.One could just download the pre-built
.jar
-s and not worry about this, but I think it's important to build stuff from source.Here are some ways java packages/apps are built inside Nixpkgs:
javac
+jar
by themselves (not too common)ant
(usually using bundled jars for dependencies)maven
(there's a generic builder:maven.buildMavenPackage
)gradle
(there's no generic builder for it yet, but some packages have found a way to patch it properly)Possible solutions to achieve determinism
There was a setup-hook called
canonicalize-jars-hook
which aimed to solve this problem by unwrapping and rewrapping jars with the creation dates set to a fixed time. However, this process had some flawsMANIFEST.MF
A after #296549,
canonicalize-jars-hook
lives on asstripJavaArchivesHook
, usingstrip-nondeterminism
as the backend.My previous attempts at fixing this:
If we don't want to or can't use
stripJavaArchivesHook
for some reason, we could use the tools provided by the build systems:Apache Ant
You can set
modificationtime
for the<jar>
(and possibly<war>
) tasks, usually in thebuild.xml
filesLike this:
<jar modificationtime="0" ...>...</jar>
To automate this you could use a script like this inside
postPatch
(Note, that this also matches a space character after the
jar
word, so that it doesn't accidentally match other tasks starting withjar
, though there's not likely to be one anyway)You could also use a dedicated
xml
modification tool likexmlstarlet
I tried to create
setup-hook
which does this automatically: #294516However this would only work for
ant
projectsMaven
You can set the
project.build.outputTimestamp
propertyYou can do this by adding
-Dproject.build.outputTimestamp=1980-01-01T00:00:02Z
to the args given to themvn
commandor by patching the
pom.xml
file to have this:Gradle
If the project uses Groovy, you can add the following lines to
build.gradle
or if the project uses Kotlin you can add the following to
build.gradle.kts
Without a build system
If the packaging script of an app uses the
jar
command directly, you could use the--date
flag to specify a build date. Note, this flag does not exist on versions beforejdk17
.Example:
Though I'd say that using
stripJavaArchivesHook
is your best bet, because it should work with any build toolProgress with making everything deterministic:
was already deterministic before opening this issue
ant
but doesn't create any jar filesFixed
stripJavaArchivesHook
for determinism #298562)attempted, seems difficult
Arc
library.<servlet>
order inside.xml
files in the.war
files)could be done
not attempted
The text was updated successfully, but these errors were encountered: