...
Page properties | ||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
...
But Maven plugins in the whole ecosystem (not only provided by Apache Maven team) sometimes add some variable parts that adds to the problem: timestamp text or username in MANIFEST.MF, ...
In 2015, reproducible-build-maven-plugin has been created to try to fix issues after packaging, by rewriting the archive and reworking content known for variable parts.
The goal of this proposal started in 2017 is to prepare a set of configuration and practices to have reproducible/verifiable builds at packaging time, both by enhancing java natural build behaviour and by removing some variability introduced by some Maven plugins (core plugins at first, but also in the Maven eco-system).
In parallel to this proposal, "Reproducible Maven Builds" site has been created to work on prototypes.
...
- Timestamps:
- Timestamps in ZIP/JAR files: file last modification time/date in central directory and file entry headers + possible optional fields "X5455_ExtendedTimestamp" (PLEXUS-ARCHIVER-48plexus-archiver PR #121)
- Timestamp in pom.properties generated by maven-archiver (MSHARED-494 )
- Timestamp in plugin.xml and plugin-help.xml descriptors generated by maven-plugin-tools-generator (MPLUGIN-326 )
- Timestamp in MANIFEST.MF (Bnd-LastModified) generated by Felix maven-bundle-plugin
- Timestamps in generated javadoc HTML files (can be disabled with javadoc options "notimestamp" and "bottom")
- Timestamps in bytecode generated from Groovy code (added by GroovyClassLoader.addTimeStamp())
- Username:
- UID/GID in tar file entries
- Username in MANIFEST.MF (Built-By) generated by maven-archiver (MSHARED-661 )
- Ordering:
- Order of the file entries in a ZIP/JAR file (depends on file system order)
- Order of the entries in the MANIFEST (MSHARED-511)
- Order of goals in plugin.xml generated by maven-plugin-tools (MPLUGIN-261)
- Order of the methods of the ObjectFactory.java file generated by JAXB/xjc (JAXB-598)
- Order of components in META-INF/plexus/components.xml generated by plexus metadata (issue #8)
- Tools Versions:
- exact JDK version used to build in MANIFEST.MF (Build-Jdk) generated by maven-archiver (MSHARED-797)
Notice that keeping the major version of the JDK used still makes sense, since it has an influence on generated bytecode: with the same source code and defined -target version, javac from JDK 6, 7, 8, ... do not produce the same bytecode. If we want to isolate the generated binary from JDK used, the compiler used will have to not be javac provided by running JDK (see Using Non-Javac Compilers) - exact Maven version used to build in MANIFEST.MF (Created-By) generated by maven-archiver (MSHARED-799)
- exact Maven version used to build in META-INF/.../pom.properties generated by maven-archiver (MSHARED-800)
- exact JDK version used to build in MANIFEST.MF (Build-Jdk) generated by maven-archiver (MSHARED-797)
...
Life would become easier if there was a dedicated POM element like ${project.build.outputTimestamp}
(with an ISO - 8601 formatted date+time) which could be used to specify the timestamp value once per entire project. Every plugin could use it as default value, like it has been done with source files encoding:
...
issue tracking | description | ||
---|---|---|---|
MSHARED-661 ( maven-archiver 3.4.0) |
| ||
MSHARED-796 ( maven-archiver-3.4.0) | META-INF/MANIFEST.MF | ||
MSHARED-494 ( maven-archiver 3.1.0) | META-INF/maven/$groupId/$artifactId/pom.properties | ||
MSHARED-800 | META-INF/maven/$groupId/$artifactId/pom.properties | ||
MPLUGIN-261 ( maven-plugin-plugin 3.3) | META-INF/maven/plugin.xml | ||
MPLUGIN-326 ( maven-plugin-plugin 3.5.1) | META-INF/maven/plugin.xml META-INF/maven/$groupId/$artifactId/plugin-help.xml | ||
plexus-containers issue #8 ( plexus-component-metadata 2.0.0) | META-INF/plexus/components.xml | ||
plexus-containers issue #27 ( plexus-component-metadata 2.1.0) | META-INF/plexus/components.xml | ||
bnd-maven-plugin #3521 ( bnd-maven-plugin configuration) | META-INF/MANIFEST.MF | ||
FELIX-6269 ( maven-bundle-plugin:manifest & bundle 4.2.2) | META-INF/MANIFEST.MF | ||
FELIX-6203 ( maven-bundle-plugin:bundle 4.2.2) | META-INF/maven/$groupId/$artifactId/pom.properties | ||
sisu-maven-plugin PR#5 5e2377c ( sisu.inject 0.3.4) | META-INF/sisu/javax.inject.Named | MRRESOURCES||
sisu- | 114 (maven | -remote-resources-plugin annotation processor 570e81 ( sisu.inject 0.9.0.M1) | META-INF/sisu/javax.inject.Named |
MRRESOURCES-114 ( maven-remote-resources-plugin 1.7.0 | 1.7.0) | projectTimespan, as often printed in META-INF/NOTICE | |
JDK-8240734 (JDK 15) | module-info.class | ||
zip entries timestamp and order | |||
COMPRESS-485 ( commons-compress 1.19) | keep entries order when gathering ParallelScatterZipCreator | ||
plexus-archiver issue #48, PR #49
0) : predefined timestamp | avoid timestamp issues in archives created by plexus-archiver (widely used avoid timestamp issues in archives created by plexus-archiver (widely used in Maven plugins creating jar, zip, war, tar... archives) | ||
plexus-archiver issue #114 ( plexus-archiver 4.2.0) | To enable reproducible builds `AbstractArchiver#addFileSet` should add the files in order | ||
MSHARED-837 ( maven-archiver 3.5.0) | support => see "Output Archive Entries Timestamp" section of the proposal | ||
plexus-archiver #271 ( plexus-archiver 2.7.0) | remove variation based on user's umask on Unixes (particularly group write) | ||
plexus-archiver #124 ( plexus-archiver 4.2.0) | remove variation based on uid/gid & userName/groupName in tar | ||
MSOURCES-120 ( maven-source-plugin 3.2.0) | apply reproducible zip (entries order and timestamp) to maven-source-plugin | ||
MSOURCES- | 921137 ( maven- | assemblysource-plugin 3.3.1) | apply 022 umask (to ease RB check: independent from env) |
MASSEMBLY-921 ( maven-assembly-plugin 3.2.0) | apply reproducible archive (entries order and timestamp) to maven-assembly-plugin | ||
MASSEMBLY-989 ( maven-assembly-plugin 3.6.0) | apply 022 umask (to ease RB check: independent from env) | ||
MJAR-263 ( maven-jar-plugin 3.2.0) | apply reproducible zip (entries order and timestamp) to maven-jar-plugin | ||
MSITE-851 ( maven-site-plugin 3.9.0) | apply reproducible zip (entries order and timestamp) to site:jar | ||
MJAVADOC-627 ( maven-javadoc-plugin 3.2.0) | apply reproducible zip (entries order and timestamp) to javadoc:*jar | ||
MSHADE-347 ( maven-shade-plugin 3.2.2) | apply reproducible zip (entries order and timestamp) to shade:shade | ||
MSHADE-352 ( maven-shade-plugin 3.2.3) | keep reproducible timestamp when shading with transformer | ||
MSHADE-420 | mtime from extra field data from shaded dependency makes result builder's timezone sensitive | ||
ARCHETYPE- | ARCHETYPE-590 ( maven-archetype-plugin 3.2.0) | apply reproducible zip (entries order and timestamp) to archetype:jar | |
MWAR-432 ( maven-war-plugin 3.3.0) | apply reproducible zip (entries order and timestamp) to war:jar | ||
MACR-53 ( maven-acr-plugin 3.2.0) | |||
MEAR-280 ( maven-ear-plugin 3.1.0) | |||
MEJB-128 ( maven-ejb-plugin 3.1.0) | |||
MRAR-86 ( maven-rar-plugin 3.0.0) | |||
MJLINK-75 ( maven-jlink-plugin 3.0.0) | apply reproducible zip to the zip file created by the plugin | ||
issues fixed in maven-archiver will have to be been picked by 9 other plugins managed by Apache Maven team (acr, ear, ejb, jlink, rar) and perhaps , probably other plugins creating zip/jar/tar archives managed outside Apache Maven team will require to do the same | |||
FELIX-6304 ( maven-bundle-plugin:bundle 5.1.1) | order and timestamp of jar entries for bundle goal | ||
FELIX-6404 ( maven-bundle-plugin 5.1.3) | regression in 5.1.2 | ||
FELIX-6495 ( maven-bundle-plugin 5.1.4) | bundle:manifest adds Bnd-LastModified even if outputTimestamp is defined | ||
FELIX-6496 ( maven-bundle-plugin 5.1.5) require bnd #5021(6.2) | non-reproducible Export-Package and Private-Package values | ||
FELIX-6602 ( maven-bundle-plugin 5.1.9) | non-reproducible Include-Resource entry | ||
FELIX-6681 | non-reproducible Export-Service entry | ||
spring- | spring-boot-maven-plugin:repackage #20176 ( 2.3.0-M4) | timestamp | |
org.jboss.jandex:jandex-maven-plugin #26 ( 1.1.1) | unsorted files (notice: not sure that sorting files at plugin level is sufficient: it seems Jandex indexer itself produces non-reproducible output) | ||
org.jboss.jandex:jandex-maven-plugin #35 | 1.2.3 replaced by io.smallrye:jandex-maven-plugin #286 ( 3.1.0) | jandex.idx output is | jandex.idx output isnot stable/reproducible |
MJAR-275 (maven-jar-plugin 3.3.0) | outputTimestamp not applied to module-info.class | ||
ServiceMix generate-depends | timestamp in generated depends.txt | ||
moditect-maven-plugin:add-module-info #185 ( 1.0.0.Final) | creates module-info.class with non-reproducible timestamp | ||
moditect #222 | timestamp is dependant on timezone | ||
SM-5021 ServiceMix depends-maven-plugin:generate-depends-file (1.5.0) | timestamp in generated depends.txt | ||
XBEAN-335 Geronimo maven-xbean-plugin | timestamp in generated /META-INF/spring-* (Properties format) | ||
KARAF-7367 karaf-maven-plugin:kar #1492 ( 4.3.7) | kardoes not take outputTimestamp into account | ||
quarkus-extension-maven-plugin #38364 | timestamp in generated properties META-INF/quarkus-extension.properties, META-INF/quarkus-javadoc.properties and sources *.jdp | ||
tracking of plugins with issues and fixes is now also done in artifact:check-buildplan |
Debian approach
Debian has a strong reproducible builds structure working on the topic for a few years: see BuildinfoFiles for environment info recording.
...