GNU bug report logs - #55751
[PATCH 0/8] Towards reproducible openjdk

Previous Next

Package: guix-patches;

Reported by: dannym <at> scratchpost.org

Date: Wed, 1 Jun 2022 12:59:01 UTC

Severity: normal

Tags: patch

Done: Vagrant Cascadian <vagrant <at> reproducible-builds.org>

To reply to this bug, email your comments to 55751 AT debbugs.gnu.org.
There is no need to reopen the bug first.

Toggle the display of automated, internal messages from the tracker.

View this report as an mbox folder, status mbox, maintainer mbox


Report forwarded to guix-patches <at> gnu.org:
bug#55751; Package guix-patches. (Wed, 01 Jun 2022 12:59:01 GMT) Full text and rfc822 format available.

Acknowledgement sent to dannym <at> scratchpost.org:
New bug report received and forwarded. Copy sent to guix-patches <at> gnu.org. (Wed, 01 Jun 2022 12:59:01 GMT) Full text and rfc822 format available.

Message #5 received at submit <at> debbugs.gnu.org (full text, mbox):

From: dannym <at> scratchpost.org
To: guix-patches <at> gnu.org
Cc: Danny Milosavljevic <dannym <at> scratchpost.org>
Subject: [PATCH 0/8] Towards reproducible openjdk
Date: Wed,  1 Jun 2022 14:57:41 +0200
From: Danny Milosavljevic <dannym <at> scratchpost.org>

This patchseries improves the reproducibility of openjdk.

After it:
* openjdk9 is reproducible.
* openjdk10 has only a few non-reproducible parts.
* openjdk11 has a number of non-reproducible parts.
* openjdk12's "doc" output is still not reproducible ("Generated by javadoc" comment with timestamp in it)
* openjdk13 still has non-reproducible parts (jmod, modules, classes.jsa, src.zip)
* openjdk14 still has very few non-reproducible parts (jmod, modules, classes.jsa)
* openjdk15 still has a number of non-reproducible parts (diz files only).
* openjdk16 still has one non-reproducible part (classes*.jsa)

Danny Milosavljevic (8):
  gnu: openjdk9: Make build reproducible.
  gnu: openjdk10: Make more reproducible.
  gnu: openjdk11: Make more reproducible.
  gnu: openjdk12: Make reproducible.
  gnu: openjdk13: Make reproducible.
  gnu: openjdk14: Make reproducible.
  gnu: openjdk15: Make reproducible.
  gnu: openjdk16: Make reproducible.

 gnu/local.mk                                  |  16 +
 gnu/packages/java.scm                         | 123 ++++++-
 .../openjdk-10-char-reproducibility.patch     |  12 +
 ...openjdk-10-classlist-reproducibility.patch |  27 ++
 .../openjdk-10-corba-reproducibility.patch    |  12 +
 .../openjdk-10-jar-reproducibility.patch      | 103 ++++++
 .../openjdk-10-jtask-reproducibility.patch    |  53 +++
 .../openjdk-10-module-reproducibility.patch   | 305 ++++++++++++++++++
 .../openjdk-10-module3-reproducibility.patch  |  34 ++
 .../openjdk-10-module4-reproducibility.patch  |  14 +
 ...openjdk-11-classlist-reproducibility.patch |  11 +
 ...openjdk-13-classlist-reproducibility.patch |  11 +
 .../openjdk-9-classlist-reproducibility.patch |  31 ++
 .../openjdk-9-idlj-reproducibility.patch      |  37 +++
 .../openjdk-9-jar-reproducibility.patch       | 107 ++++++
 .../openjdk-9-module-reproducibility.patch    | 296 +++++++++++++++++
 .../openjdk-9-module2-reproducibility.patch   | 125 +++++++
 .../openjdk-9-module3-reproducibility.patch   |  36 +++
 18 files changed, 1342 insertions(+), 11 deletions(-)
 create mode 100644 gnu/packages/patches/openjdk-10-char-reproducibility.patch
 create mode 100644 gnu/packages/patches/openjdk-10-classlist-reproducibility.patch
 create mode 100644 gnu/packages/patches/openjdk-10-corba-reproducibility.patch
 create mode 100644 gnu/packages/patches/openjdk-10-jar-reproducibility.patch
 create mode 100644 gnu/packages/patches/openjdk-10-jtask-reproducibility.patch
 create mode 100644 gnu/packages/patches/openjdk-10-module-reproducibility.patch
 create mode 100644 gnu/packages/patches/openjdk-10-module3-reproducibility.patch
 create mode 100644 gnu/packages/patches/openjdk-10-module4-reproducibility.patch
 create mode 100644 gnu/packages/patches/openjdk-11-classlist-reproducibility.patch
 create mode 100644 gnu/packages/patches/openjdk-13-classlist-reproducibility.patch
 create mode 100644 gnu/packages/patches/openjdk-9-classlist-reproducibility.patch
 create mode 100644 gnu/packages/patches/openjdk-9-idlj-reproducibility.patch
 create mode 100644 gnu/packages/patches/openjdk-9-jar-reproducibility.patch
 create mode 100644 gnu/packages/patches/openjdk-9-module-reproducibility.patch
 create mode 100644 gnu/packages/patches/openjdk-9-module2-reproducibility.patch
 create mode 100644 gnu/packages/patches/openjdk-9-module3-reproducibility.patch

-- 
2.36.1





Information forwarded to guix-patches <at> gnu.org:
bug#55751; Package guix-patches. (Wed, 01 Jun 2022 13:01:02 GMT) Full text and rfc822 format available.

Message #8 received at 55751 <at> debbugs.gnu.org (full text, mbox):

From: dannym <at> scratchpost.org
To: 55751 <at> debbugs.gnu.org
Cc: Danny Milosavljevic <dannym <at> scratchpost.org>
Subject: [PATCH 1/8] gnu: openjdk9: Make build reproducible.
Date: Wed,  1 Jun 2022 15:00:04 +0200
From: Danny Milosavljevic <dannym <at> scratchpost.org>

* gnu/packages/patches/openjdk-9-classlist-reproducibility.patch: New file.
* gnu/packages/patches/openjdk-9-jar-reproducibility.patch: New file.
* gnu/packages/patches/openjdk-9-module-reproducibility.patch: New file.
* gnu/packages/patches/openjdk-9-module2-reproducibility.patch: New file.
* gnu/packages/patches/openjdk-9-module3-reproducibility.patch: New file.
* gnu/packages/patches/openjdk-9-idlj-reproducibility.patch: New file.
* gnu/packages/java.scm (openjdk9)[source]: Add patches.
[arguments]<#:phases>[strip-zip-timestamps]: Modify.
* gnu/local/mk (dist_patch_DATA): Add patches.
---
 gnu/local.mk                                  |   6 +
 gnu/packages/java.scm                         |  61 +++-
 .../openjdk-9-classlist-reproducibility.patch |  31 ++
 .../openjdk-9-idlj-reproducibility.patch      |  37 +++
 .../openjdk-9-jar-reproducibility.patch       | 107 +++++++
 .../openjdk-9-module-reproducibility.patch    | 296 ++++++++++++++++++
 .../openjdk-9-module2-reproducibility.patch   | 125 ++++++++
 .../openjdk-9-module3-reproducibility.patch   |  36 +++
 8 files changed, 692 insertions(+), 7 deletions(-)
 create mode 100644 gnu/packages/patches/openjdk-9-classlist-reproducibility.patch
 create mode 100644 gnu/packages/patches/openjdk-9-idlj-reproducibility.patch
 create mode 100644 gnu/packages/patches/openjdk-9-jar-reproducibility.patch
 create mode 100644 gnu/packages/patches/openjdk-9-module-reproducibility.patch
 create mode 100644 gnu/packages/patches/openjdk-9-module2-reproducibility.patch
 create mode 100644 gnu/packages/patches/openjdk-9-module3-reproducibility.patch

diff --git a/gnu/local.mk b/gnu/local.mk
index bc82c5ba9f..5ba5af94a6 100644
--- a/gnu/local.mk
+++ b/gnu/local.mk
@@ -1567,6 +1567,12 @@ dist_patch_DATA =						\
   %D%/packages/patches/openboardview-use-system-utf8.patch	\
   %D%/packages/patches/opencascade-oce-glibc-2.26.patch		\
   %D%/packages/patches/openfoam-4.1-cleanup.patch			\
+  %D%/packages/patches/openjdk-9-classlist-reproducibility.patch	\
+  %D%/packages/patches/openjdk-9-idlj-reproducibility.patch	\
+  %D%/packages/patches/openjdk-9-jar-reproducibility.patch	\
+  %D%/packages/patches/openjdk-9-module-reproducibility.patch	\
+  %D%/packages/patches/openjdk-9-module2-reproducibility.patch	\
+  %D%/packages/patches/openjdk-9-module3-reproducibility.patch	\
   %D%/packages/patches/openjdk-10-idlj-reproducibility.patch	\
   %D%/packages/patches/openjdk-15-xcursor-no-dynamic.patch	\
   %D%/packages/patches/openmpi-mtl-priorities.patch		\
diff --git a/gnu/packages/java.scm b/gnu/packages/java.scm
index 336e84e3e5..3d36849f7d 100644
--- a/gnu/packages/java.scm
+++ b/gnu/packages/java.scm
@@ -1526,7 +1526,16 @@ (define-public openjdk9
               (sha256
                (base32
                 "01ihmyf7k5z17wbr7xig7y40l9f01d5zjgkcmawn1102hw5kchpq"))
-              (modules '((guix build utils)))
+              (patches
+                (search-patches "openjdk-9-classlist-reproducibility.patch"
+                                "openjdk-9-jar-reproducibility.patch"
+                                "openjdk-9-module-reproducibility.patch"
+                                "openjdk-9-module2-reproducibility.patch"
+                                "openjdk-9-module3-reproducibility.patch"
+                                "openjdk-9-idlj-reproducibility.patch"))
+              (modules '((guix build utils)
+                         (srfi srfi-35)
+                         (ice-9 binary-ports)))
               (snippet
                `(begin
                   (for-each delete-file
@@ -1539,6 +1548,7 @@ (define-public openjdk9
        #:make-flags '("all")
        #:imported-modules
        ((guix build syscalls)
+        (srfi srfi-35)
         ,@%gnu-build-system-modules)
 
        #:disallowed-references ,(list (gexp-input icedtea-8)
@@ -1658,18 +1668,55 @@ (define (icedtea-or-openjdk? path)
              (for-each (lambda (zip)
                          (let ((dir (mkdtemp! "zip-contents.XXXXXX")))
                            (with-directory-excursion dir
-                             (invoke "unzip" zip))
+                             (let ((code (system* "unzip" "--" zip)))
+                               (write code)
+                               (newline)
+                               (when (> (status:exit-val code) 1) ; 1 is just a warning
+                                 (raise (condition (&invoke-error
+                                                    (program "unzip")
+                                                    (arguments (list "--" zip))
+                                                    (exit-status (status:exit-val code))
+                                                    (term-signal (status:term-sig code))
+                                                    (stop-signal (status:stop-sig code))))))))
                            (delete-file zip)
                            (for-each (lambda (file)
                                        (let ((s (lstat file)))
-                                         (unless (eq? (stat:type s) 'symlink)
                                            (format #t "reset ~a~%" file)
-                                           (utime file 0 0 0 0))))
+                                           (utime file 1 1 0 0
+                                                       AT_SYMLINK_NOFOLLOW)))
                                      (find-files dir #:directories? #t))
                            (with-directory-excursion dir
-                             (let ((files (find-files "." ".*" #:directories? #t)))
-                               (apply invoke "zip" "-0" "-X" zip files)))))
-                       (find-files (assoc-ref outputs "doc") ".*.zip$"))
+                             (let ((files (cons "./META-INF/MANIFEST.MF"
+                                                (append (find-files "./META-INF" ".*")
+                                                        ;; for jmod:
+                                                        (list "./classes/module-info.class")
+                                                        (find-files "." ".*")))))
+                               (apply invoke "zip" "--symlinks" "-0" "-X" zip files)
+                               (when (string-suffix? ".jmod" zip)
+                                 (let ((new-zip (string-append zip "n"))
+                                       (contents (call-with-input-file zip
+                                                   (@ (ice-9 binary-ports) get-bytevector-all))))
+                                   (call-with-output-file new-zip
+                                     (lambda (output-port)
+                                       ((@ (ice-9 binary-ports) put-bytevector) output-port
+                                                       #vu8(#x4a #x4d #x01 #x00)) ; JM
+                                       ((@ (ice-9 binary-ports) put-bytevector) output-port
+                                                       contents)))
+                                   (rename-file new-zip zip)))))))
+                       (append (find-files (string-append
+                                            (assoc-ref outputs "doc")
+                                            "/api")
+                                           "\\.zip$")
+                               (find-files (assoc-ref outputs "doc") "src\\.zip$")
+                               (find-files (assoc-ref outputs "jdk") "src\\.zip$")
+                               (find-files (assoc-ref outputs "jdk") "\\.jmod$")
+                               (find-files (assoc-ref outputs "jdk") "\\.diz$")
+                               (find-files (assoc-ref outputs "out") "\\.diz$")
+
+                               (list (string-append (assoc-ref outputs "jdk") "/lib/jrt-fs.jar"))
+                               (find-files (string-append (assoc-ref outputs "jdk")
+                                                          "/demo")
+                                           "\\.jar$")))
              #t)))))
     (inputs
      `(("alsa-lib" ,alsa-lib)
diff --git a/gnu/packages/patches/openjdk-9-classlist-reproducibility.patch b/gnu/packages/patches/openjdk-9-classlist-reproducibility.patch
new file mode 100644
index 0000000000..d0ce7bc4d6
--- /dev/null
+++ b/gnu/packages/patches/openjdk-9-classlist-reproducibility.patch
@@ -0,0 +1,31 @@
+From: Danny Milosavljevic <dannym <at> scratchpost.org>
+Date: Wed, 18 Apr 2022 18:38:28 +0100
+Subject: Make classlist reproducible
+
+--- jdk-09/make/GenerateLinkOptData.gmk.orig	2022-04-05 10:05:35.892134188 +0200
++++ jdk-09/make/GenerateLinkOptData.gmk	2022-04-05 10:06:07.885003056 +0200
+@@ -61,11 +61,12 @@
+ 	$(call MakeDir, $(LINK_OPT_DIR))
+ 	$(call LogInfo, Generating $(patsubst $(OUTPUT_ROOT)/%, %, $@))
+ 	$(call LogInfo, Generating $(patsubst $(OUTPUT_ROOT)/%, %, $(JLI_TRACE_FILE)))
+-	$(FIXPATH) $(INTERIM_IMAGE_DIR)/bin/java -XX:DumpLoadedClassList=$@ \
++	$(FIXPATH) $(INTERIM_IMAGE_DIR)/bin/java -XX:DumpLoadedClassList=$@.tmp \
+ 	    -Djava.lang.invoke.MethodHandle.TRACE_RESOLVE=true \
+ 	    -cp $(SUPPORT_OUTPUTDIR)/classlist.jar \
+ 	    build.tools.classlist.HelloClasslist \
+ 	    $(LOG_DEBUG) 2>&1 > $(JLI_TRACE_FILE)
++	sort $@.tmp >$@
+ 
+ # The jli trace is created by the same recipe as classlist. By declaring these
+ # dependencies, make will correctly rebuild both jli trace and classlist
+--- jdk-09/langtools/make/gendata/Gendata-jdk.compiler.gmk.orig	2022-04-08 22:04:05.784424812 +0200
++++ jdk-09/langtools/make/gendata/Gendata-jdk.compiler.gmk	2022-04-08 22:09:36.333575143 +0200
+@@ -79,6 +79,8 @@
+ 	    $(CT_MODULESOURCEPATH) \
+ 	    $(CT_MODULES) \
+ 	    >$(@D)/9/system-modules
++	# Make files reproducible
++	find $(@D) -exec $(TOUCH) -h -c -t 197001010000.01 {} \;
+ 	$(TOUCH) $@
+ 
+ # Can't generate ct.sym directly into modules libs as the SetupJarArchive macro
diff --git a/gnu/packages/patches/openjdk-9-idlj-reproducibility.patch b/gnu/packages/patches/openjdk-9-idlj-reproducibility.patch
new file mode 100644
index 0000000000..30dcdf2496
--- /dev/null
+++ b/gnu/packages/patches/openjdk-9-idlj-reproducibility.patch
@@ -0,0 +1,37 @@
+From: Danny Milosavljevic <dannym <at> scratchpost.org>
+Date: Wed, 18 Apr 2022 19:28:00 +0100
+Subject: Make IDL reproducible
+
+--- jdk-09/corba/src/java.corba/share/classes/com/sun/tools/corba/se/idl/toJavaPortable/Util.java.orig	2022-04-05 02:46:26.805340292 +0200
++++ jdk-09/corba/src/java.corba/share/classes/com/sun/tools/corba/se/idl/toJavaPortable/Util.java	2022-04-05 02:48:23.152494213 +0200
+@@ -1146,7 +1146,7 @@
+     else
+       formatter.setTimeZone (java.util.TimeZone.getDefault ());
+ 
+-    stream.println ("* " + formatter.format (new Date ()));
++    stream.println ("* " + formatter.format (System.getenv("SOURCE_DATE_EPOCH") == null ? new Date () : new Date(1000 * Long.parseLong(System.getenv("SOURCE_DATE_EPOCH")))));
+ 
+     // <daz>
+     ///////////////
+--- jdk-09/corba/make/src/classes/build/tools/logutil/MC.java.orig	2022-04-05 11:09:43.824720493 +0200
++++ jdk-09/corba/make/src/classes/build/tools/logutil/MC.java	2022-04-05 11:10:46.518435511 +0200
+@@ -154,7 +154,7 @@
+                   groupName);
+     pw.println("//");
+     pw.printMsg("// Generated by MC.java version @, DO NOT EDIT BY HAND!", VERSION);
+-    pw.printMsg("// Generated from input file @ on @", inFile, new Date());
++    pw.printMsg("// Generated from input file @ on @", inFile, System.getenv("SOURCE_DATE_EPOCH") == null ? new Date() : new Date(1000 * Long.parseLong(System.getenv("SOURCE_DATE_EPOCH"))));
+     pw.println();
+   }
+ 
+--- jdk-09/jdk/make/src/classes/build/tools/generatecharacter/GenerateCharacter.java.orig	2022-04-05 11:14:29.228526408 +0200
++++ jdk-09/jdk/make/src/classes/build/tools/generatecharacter/GenerateCharacter.java	2022-04-05 11:15:32.658260748 +0200
+@@ -693,7 +693,7 @@
+         PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(theOutputFileName)));
+         out.println(commentStart +
+             " This file was generated AUTOMATICALLY from a template file " +
+-            new java.util.Date() + commentEnd);
++            (System.getenv("SOURCE_DATE_EPOCH") == null ? new java.util.Date() : new java.util.Date(1000 * Long.parseLong(System.getenv("SOURCE_DATE_EPOCH")))) + commentEnd);
+         int marklen = commandMarker.length();
+         LOOP: while(true) {
+             try {
diff --git a/gnu/packages/patches/openjdk-9-jar-reproducibility.patch b/gnu/packages/patches/openjdk-9-jar-reproducibility.patch
new file mode 100644
index 0000000000..130eacd867
--- /dev/null
+++ b/gnu/packages/patches/openjdk-9-jar-reproducibility.patch
@@ -0,0 +1,107 @@
+From: Danny Milosavljevic <dannym <at> scratchpost.org>
+Date: Wed, 18 Apr 2022 20:10:01 +0100
+Subject: Make JARs reproducible
+
+--- jdk-09/make/common/JarArchive.gmk.orig	2022-04-08 21:56:04.075111687 +0200
++++ jdk-09/make/common/JarArchive.gmk	2022-04-11 00:49:16.809140388 +0200
+@@ -249,12 +249,16 @@
+ 	    $(ECHO) "Main-Class: $$(strip $$($1_JARMAIN))" >> $$($1_MANIFEST_FILE) $$(NEWLINE)) \
+ 	  $$(if $$($1_EXTRA_MANIFEST_ATTR), \
+ 	    $(PRINTF) "$$($1_EXTRA_MANIFEST_ATTR)\n" >> $$($1_MANIFEST_FILE) $$(NEWLINE)) \
+-	  $(ECHO) Creating $$($1_NAME) $$(NEWLINE) \
++	  $(TOUCH) -h -c -t 197001010000.00 $$($1_MANIFEST_FILE) $$(NEWLINE) \
++	  $(ECHO) XCreating $$($1_NAME) $(JAR) $$($1_JAR_CREATE_OPTIONS) $$@ $$($1_MANIFEST_FILE) $$(NEWLINE) \
+ 	  $(JAR) $$($1_JAR_CREATE_OPTIONS) $$@ $$($1_MANIFEST_FILE) $$(NEWLINE) \
+ 	  $$($1_SCAPTURE_CONTENTS) \
+ 	  $$($1_SCAPTURE_METAINF) \
+ 	  $$($1_SUPDATE_CONTENTS) \
+-	  $$($1_JARINDEX) && true \
++	  $$($1_JARINDEX) && true $$(NEWLINE) \
++	  $(ECHO) Kreppel2 $$@ $$(NEWLINE) \
++	  unzip -v $$@ $$(NEWLINE) \
++	  d="`mktemp -d`" && $(CP) -f $$@ "$$$$d/a.jar" && (cd "$$$$d" && unzip a.jar META-INF/MANIFEST.MF && $(TOUCH) -h -c -t 197001010000.00 META-INF &&  $(TOUCH) -h -c -t 197001010000.00 META-INF/MANIFEST.MF && (zip --symlinks -0 -X a.jar META-INF META-INF/MANIFEST.MF; zip --symlinks -0 -X a.jar META-INF META-INF/MANIFEST.MF)) && $(CP) -f "$$$$d/a.jar" $$@ \
+ 	, \
+ 	  $(ECHO) Modifying $$($1_NAME) $$(NEWLINE) \
+ 	  $$($1_CAPTURE_CONTENTS) \
+--- jdk-09/make/JrtfsJar.gmk.orig	2022-04-10 13:48:57.385120008 +0200
++++ jdk-09/make/JrtfsJar.gmk	2022-04-10 13:58:04.688158538 +0200
+@@ -57,13 +57,18 @@
+ # file will not be copied unless META-INF/services would also be added to the INCLUDES.
+ # Adding META-INF/services would include all files in that directory when only the one
+ # is needed, which is why this explicit copy is defined instead.
+-$(eval $(call SetupCopyFiles, COPY_JIMAGE_SERVICE_PROVIDER, \
++$(eval $(call SetupCopyFiles, COPY_JIMAGE_SERVICE_PROVIDER1, \
+     SRC := $(JDK_TOPDIR)/src/java.base/share/classes, \
+     DEST := $(SUPPORT_OUTPUTDIR)/jrtfs_classes, \
+     FILES := META-INF/services/java.nio.file.spi.FileSystemProvider))
+ 
++.PHONY: jrtfsfixtimestamps47
++jrtfsfixtimestamps47: $(COPY_JIMAGE_SERVICE_PROVIDER1)
++	find $(SUPPORT_OUTPUTDIR)/jrtfs_classes -exec $(TOUCH) -h -c -t 197001010000.00 {} \;
++	$(TOUCH) -h -c -t 197001010000.00 $(SUPPORT_OUTPUTDIR)/java-main-manifest.mf
++
+ $(eval $(call SetupJarArchive,BUILD_JRTFS_JAR, \
+-    DEPENDENCIES := $(BUILD_JRTFS) $(COPY_JIMAGE_SERVICE_PROVIDER), \
++    DEPENDENCIES := $(BUILD_JRTFS) jrtfsfixtimestamps47, \
+     SRCS := $(SUPPORT_OUTPUTDIR)/jrtfs_classes, \
+     JAR := $(SUPPORT_OUTPUTDIR)/modules_libs/java.base/jrt-fs.jar, \
+     MANIFEST := $(SUPPORT_OUTPUTDIR)/java-main-manifest.mf, \
+--- jdk-09/jdk/src/jdk.jartool/share/classes/sun/tools/jar/Main.java.orig	2022-04-10 02:05:50.983247794 +0200
++++ jdk-09/jdk/src/jdk.jartool/share/classes/sun/tools/jar/Main.java	2022-04-10 02:13:01.638960337 +0200
+@@ -850,12 +850,18 @@
+                     output(getMsg("out.added.manifest"));
+                 }
+                 ZipEntry e = new ZipEntry(MANIFEST_DIR);
+-                e.setTime(System.currentTimeMillis());
++                if (System.getenv("SOURCE_DATE_EPOCH") != null)
++                    e.setTime(1000 * Long.parseLong(System.getenv("SOURCE_DATE_EPOCH")));
++                else
++                    e.setTime(System.currentTimeMillis());
+                 e.setSize(0);
+                 e.setCrc(0);
+                 zos.putNextEntry(e);
+                 e = new ZipEntry(MANIFEST_NAME);
+-                e.setTime(System.currentTimeMillis());
++                if (System.getenv("SOURCE_DATE_EPOCH") != null)
++                    e.setTime(1000 * Long.parseLong(System.getenv("SOURCE_DATE_EPOCH")));
++                else
++                    e.setTime(System.currentTimeMillis());
+                 if (flag0) {
+                     crc32Manifest(e, manifest);
+                 }
+@@ -1022,7 +1028,10 @@
+         throws IOException
+     {
+         ZipEntry e = new ZipEntry(INDEX_NAME);
+-        e.setTime(System.currentTimeMillis());
++        if (System.getenv("SOURCE_DATE_EPOCH") != null)
++            e.setTime(1000 * Long.parseLong(System.getenv("SOURCE_DATE_EPOCH")));
++        else
++            e.setTime(System.currentTimeMillis());
+         if (flag0) {
+             CRC32OutputStream os = new CRC32OutputStream();
+             index.write(os);
+@@ -1041,7 +1050,10 @@
+             String name = mi.getKey();
+             byte[] bytes = mi.getValue();
+             ZipEntry e = new ZipEntry(name);
+-            e.setTime(System.currentTimeMillis());
++            if (System.getenv("SOURCE_DATE_EPOCH") != null)
++                e.setTime(1000 * Long.parseLong(System.getenv("SOURCE_DATE_EPOCH")));
++            else
++                e.setTime(System.currentTimeMillis());
+             if (flag0) {
+                 crc32ModuleInfo(e, bytes);
+             }
+@@ -1066,7 +1078,10 @@
+             addMultiRelease(m);
+         }
+         ZipEntry e = new ZipEntry(MANIFEST_NAME);
+-        e.setTime(System.currentTimeMillis());
++        if (System.getenv("SOURCE_DATE_EPOCH") != null)
++            e.setTime(1000 * Long.parseLong(System.getenv("SOURCE_DATE_EPOCH")));
++        else
++            e.setTime(System.currentTimeMillis());
+         if (flag0) {
+             crc32Manifest(e, m);
+         }
diff --git a/gnu/packages/patches/openjdk-9-module-reproducibility.patch b/gnu/packages/patches/openjdk-9-module-reproducibility.patch
new file mode 100644
index 0000000000..80b6808395
--- /dev/null
+++ b/gnu/packages/patches/openjdk-9-module-reproducibility.patch
@@ -0,0 +1,296 @@
+From a52c4ef44c0553a399a8a47e528db92e3bf51c6c Mon Sep 17 00:00:00 2001
+From: Alan Bateman <alanb <at> openjdk.org>
+Date: Wed, 29 Apr 2020 08:38:28 +0100
+Subject: [PATCH] 8243666: ModuleHashes attribute generated for JMOD and JAR
+ files depends on timestamps
+
+Reviewed-by: mchung
+---
+
+diff -ru orig/jdk-3cc80be736f2/jdk/src/java.base/share/classes/jdk/internal/module/ModuleHashesBuilder.java jdk-3cc80be736f2/jdk/src/java.base/share/classes/jdk/internal/module/ModuleHashesBuilder.java
+--- orig/jdk-3cc80be736f2/jdk/src/java.base/share/classes/jdk/internal/module/ModuleHashesBuilder.java	1970-01-01 01:00:01.000000000 +0100
++++ jdk-3cc80be736f2/jdk/src/java.base/share/classes/jdk/internal/module/ModuleHashesBuilder.java	2022-04-12 16:47:15.690423653 +0200
+@@ -27,9 +27,8 @@
+ 
+ import java.io.PrintStream;
+ import java.lang.module.Configuration;
++import java.lang.module.ModuleReference;
+ import java.lang.module.ResolvedModule;
+-import java.net.URI;
+-import java.nio.file.Path;
+ import java.nio.file.Paths;
+ import java.util.ArrayDeque;
+ import java.util.Collections;
+@@ -40,7 +39,6 @@
+ import java.util.Map;
+ import java.util.Set;
+ import java.util.function.Consumer;
+-import java.util.function.Function;
+ import java.util.stream.Stream;
+ import static java.util.stream.Collectors.*;
+ 
+@@ -116,27 +114,17 @@
+                    mods.addAll(ns);
+ 
+                    if (!ns.isEmpty()) {
+-                       Map<String, Path> moduleToPath = ns.stream()
+-                           .collect(toMap(Function.identity(), this::moduleToPath));
+-                       hashes.put(mn, ModuleHashes.generate(moduleToPath, "SHA-256"));
++                       Set<ModuleReference> mrefs = ns.stream()
++                               .map(name -> configuration.findModule(name)
++                                                         .orElseThrow(InternalError::new))
++                               .map(ResolvedModule::reference)
++                               .collect(toSet());
++                       hashes.put(mn, ModuleHashes.generate(mrefs, "SHA-256"));
+                    }
+                });
+         return hashes;
+     }
+ 
+-    private Path moduleToPath(String name) {
+-        ResolvedModule rm = configuration.findModule(name).orElseThrow(
+-            () -> new InternalError("Selected module " + name + " not on module path"));
+-
+-        URI uri = rm.reference().location().get();
+-        Path path = Paths.get(uri);
+-        String fn = path.getFileName().toString();
+-        if (!fn.endsWith(".jar") && !fn.endsWith(".jmod")) {
+-            throw new UnsupportedOperationException(path + " is not a modular JAR or jmod file");
+-        }
+-        return path;
+-    }
+-
+     /*
+      * Utility class
+      */
+diff -ru orig/jdk-3cc80be736f2/jdk/src/java.base/share/classes/jdk/internal/module/ModuleHashes.java jdk-3cc80be736f2/jdk/src/java.base/share/classes/jdk/internal/module/ModuleHashes.java
+--- orig/jdk-3cc80be736f2/jdk/src/java.base/share/classes/jdk/internal/module/ModuleHashes.java	1970-01-01 01:00:01.000000000 +0100
++++ jdk-3cc80be736f2/jdk/src/java.base/share/classes/jdk/internal/module/ModuleHashes.java	2022-04-12 16:58:05.639985936 +0200
+@@ -26,17 +26,21 @@
+ package jdk.internal.module;
+ 
+ import java.io.IOException;
++import java.io.InputStream;
+ import java.io.UncheckedIOException;
+-import java.nio.ByteBuffer;
+-import java.nio.channels.FileChannel;
+-import java.nio.file.Path;
++import java.lang.module.ModuleReader;
++import java.lang.module.ModuleReference;
++import java.nio.charset.StandardCharsets;
+ import java.security.MessageDigest;
+ import java.security.NoSuchAlgorithmException;
++import java.util.Arrays;
+ import java.util.Collections;
+ import java.util.HashMap;
+ import java.util.Map;
+ import java.util.Objects;
+ import java.util.Set;
++import java.util.TreeMap;
++import java.util.function.Supplier;
+ 
+ /**
+  * The result of hashing the contents of a number of module artifacts.
+@@ -60,8 +64,8 @@
+      * @param algorithm   the algorithm used to create the hashes
+      * @param nameToHash  the map of module name to hash value
+      */
+-    public ModuleHashes(String algorithm, Map<String, byte[]> nameToHash) {
+-        this.algorithm = algorithm;
++    ModuleHashes(String algorithm, Map<String, byte[]> nameToHash) {
++        this.algorithm = Objects.requireNonNull(algorithm);
+         this.nameToHash = Collections.unmodifiableMap(nameToHash);
+     }
+ 
+@@ -95,54 +99,125 @@
+     }
+ 
+     /**
+-     * Computes the hash for the given file with the given message digest
+-     * algorithm.
++     * Computes a hash from the names and content of a module.
+      *
++     * @param reader the module reader to access the module content
++     * @param algorithm the name of the message digest algorithm to use
++     * @return the hash
++     * @throws IllegalArgumentException if digest algorithm is not supported
+      * @throws UncheckedIOException if an I/O error occurs
+      * @throws RuntimeException if the algorithm is not available
+      */
+-    public static byte[] computeHash(Path file, String algorithm) {
++    private static byte[] computeHash(ModuleReader reader, String algorithm) {
++        MessageDigest md;
+         try {
+-            MessageDigest md = MessageDigest.getInstance(algorithm);
+-
+-            // Ideally we would just mmap the file but this consumes too much
+-            // memory when jlink is running concurrently on very large jmods
+-            try (FileChannel fc = FileChannel.open(file)) {
+-                ByteBuffer bb = ByteBuffer.allocate(32*1024);
+-                while (fc.read(bb) > 0) {
+-                    bb.flip();
+-                    md.update(bb);
+-                    assert bb.remaining() == 0;
+-                    bb.clear();
+-                }
+-            }
+-
+-            return md.digest();
++            md = MessageDigest.getInstance(algorithm);
+         } catch (NoSuchAlgorithmException e) {
+-            throw new RuntimeException(e);
++            throw new IllegalArgumentException(e);
++        }
++        try {
++            byte[] buf = new byte[32*1024];
++            reader.list().sorted().forEach(rn -> {
++                md.update(rn.getBytes(StandardCharsets.UTF_8));
++                try (InputStream in = reader.open(rn).orElseThrow(java.util.NoSuchElementException::new)) {
++                    int n;
++                    while ((n = in.read(buf)) > 0) {
++                        md.update(buf, 0, n);
++                    }
++                } catch (IOException ioe) {
++                    throw new UncheckedIOException(ioe);
++                }
++            });
+         } catch (IOException ioe) {
+             throw new UncheckedIOException(ioe);
+         }
++        return md.digest();
+     }
+ 
+     /**
+-     * Computes the hash for every entry in the given map, returning a
+-     * {@code ModuleHashes} to encapsulate the result. The map key is
+-     * the entry name, typically the module name. The map value is the file
+-     * path to the entry (module artifact).
++     * Computes a hash from the names and content of a module.
+      *
++     * @param supplier supplies the module reader to access the module content
++     * @param algorithm the name of the message digest algorithm to use
++     * @return the hash
++     * @throws IllegalArgumentException if digest algorithm is not supported
++     * @throws UncheckedIOException if an I/O error occurs
++     */
++    static byte[] computeHash(Supplier<ModuleReader> supplier, String algorithm) {
++        try (ModuleReader reader = supplier.get()) {
++            return computeHash(reader, algorithm);
++        } catch (IOException ioe) {
++            throw new UncheckedIOException(ioe);
++        }
++    }
++
++    /**
++     * Computes the hash from the names and content of a set of modules. Returns
++     * a {@code ModuleHashes} to encapsulate the result.
++     * @param mrefs the set of modules
++     * @param algorithm the name of the message digest algorithm to use
+      * @return ModuleHashes that encapsulates the hashes
++     * @throws IllegalArgumentException if digest algorithm is not supported
++     * @throws UncheckedIOException if an I/O error occurs
+      */
+-    public static ModuleHashes generate(Map<String, Path> map, String algorithm) {
++    static ModuleHashes generate(Set<ModuleReference> mrefs, String algorithm) {
+         Map<String, byte[]> nameToHash = new HashMap<>();
+-        for (Map.Entry<String, Path> entry: map.entrySet()) {
+-            String name = entry.getKey();
+-            Path path = entry.getValue();
+-            nameToHash.put(name, computeHash(path, algorithm));
++        for (ModuleReference mref : mrefs) {
++            try (ModuleReader reader = mref.open()) {
++                byte[] hash = computeHash(reader, algorithm);
++                nameToHash.put(mref.descriptor().name(), hash);
++            } catch (IOException ioe) {
++                throw new UncheckedIOException(ioe);
++            }
+         }
+         return new ModuleHashes(algorithm, nameToHash);
+     }
+ 
++    @Override
++    public int hashCode() {
++        int h = algorithm.hashCode();
++        for (Map.Entry<String, byte[]> e : nameToHash.entrySet()) {
++            h = h * 31 + e.getKey().hashCode();
++            h = h * 31 + Arrays.hashCode(e.getValue());
++        }
++        return h;
++    }
++
++    @Override
++    public boolean equals(Object obj) {
++        if (!(obj instanceof ModuleHashes))
++            return false;
++        ModuleHashes other = (ModuleHashes) obj;
++        if (!algorithm.equals(other.algorithm)
++                || nameToHash.size() != other.nameToHash.size())
++            return false;
++        for (Map.Entry<String, byte[]> e : nameToHash.entrySet()) {
++            String name = e.getKey();
++            byte[] hash = e.getValue();
++            if (!Arrays.equals(hash, other.nameToHash.get(name)))
++                return false;
++        }
++        return true;
++    }
++
++    @Override
++    public String toString() {
++        StringBuilder sb = new StringBuilder(algorithm);
++        sb.append(" ");
++        nameToHash.entrySet()
++                .stream()
++                .sorted(Map.Entry.comparingByKey())
++                .forEach(e -> {
++                    sb.append(e.getKey());
++                    sb.append("=");
++                    byte[] ba = e.getValue();
++                    for (byte b : ba) {
++                        sb.append(String.format("%02x", b & 0xff));
++                    }
++                });
++        return sb.toString();
++    }
++
+     /**
+      * This is used by jdk.internal.module.SystemModules class
+      * generated at link time.
+diff -ru orig/jdk-3cc80be736f2/jdk/src/java.base/share/classes/jdk/internal/module/ModuleInfoExtender.java jdk-3cc80be736f2/jdk/src/java.base/share/classes/jdk/internal/module/ModuleInfoExtender.java
+--- orig/jdk-3cc80be736f2/jdk/src/java.base/share/classes/jdk/internal/module/ModuleInfoExtender.java	1970-01-01 01:00:01.000000000 +0100
++++ jdk-3cc80be736f2/jdk/src/java.base/share/classes/jdk/internal/module/ModuleInfoExtender.java	2022-04-12 16:43:12.967868689 +0200
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
++ * Copyright (c) 2014, 2020, Oracle and/or its affiliates. All rights reserved.
+  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+  *
+  * This code is free software; you can redistribute it and/or modify it
+diff -ru orig/jdk-3cc80be736f2/jdk/src/java.base/share/classes/jdk/internal/module/ModuleReferences.java jdk-3cc80be736f2/jdk/src/java.base/share/classes/jdk/internal/module/ModuleReferences.java
+--- orig/jdk-3cc80be736f2/jdk/src/java.base/share/classes/jdk/internal/module/ModuleReferences.java	1970-01-01 01:00:01.000000000 +0100
++++ jdk-3cc80be736f2/jdk/src/java.base/share/classes/jdk/internal/module/ModuleReferences.java	2022-04-12 16:43:12.971868797 +0200
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
++ * Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved.
+  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+  *
+  * This code is free software; you can redistribute it and/or modify it
+@@ -95,7 +95,7 @@
+                                         Path file) {
+         URI uri = file.toUri();
+         Supplier<ModuleReader> supplier = () -> new JarModuleReader(file, uri);
+-        HashSupplier hasher = (a) -> ModuleHashes.computeHash(file, a);
++        HashSupplier hasher = (a) -> ModuleHashes.computeHash(supplier, a);
+         return newModule(attrs, uri, supplier, patcher, hasher);
+     }
+ 
+@@ -105,7 +105,7 @@
+     static ModuleReference newJModModule(ModuleInfo.Attributes attrs, Path file) {
+         URI uri = file.toUri();
+         Supplier<ModuleReader> supplier = () -> new JModModuleReader(file, uri);
+-        HashSupplier hasher = (a) -> ModuleHashes.computeHash(file, a);
++        HashSupplier hasher = (a) -> ModuleHashes.computeHash(supplier, a);
+         return newModule(attrs, uri, supplier, null, hasher);
+     }
+ 
diff --git a/gnu/packages/patches/openjdk-9-module2-reproducibility.patch b/gnu/packages/patches/openjdk-9-module2-reproducibility.patch
new file mode 100644
index 0000000000..f167d94dc8
--- /dev/null
+++ b/gnu/packages/patches/openjdk-9-module2-reproducibility.patch
@@ -0,0 +1,125 @@
+Backport from openjdk 10
+
+--- orig/jdk-3cc80be736f2/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ModuleSorter.java	1970-01-01 01:00:01.000000000 +0100
++++ jdk-3cc80be736f2/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ModuleSorter.java	2022-04-12 20:48:04.474353305 +0200
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
++ * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
+  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+  *
+  * This code is free software; you can redistribute it and/or modify it
+@@ -30,13 +30,16 @@
+ import jdk.tools.jlink.plugin.ResourcePoolModuleView;
+ 
+ import java.lang.module.ModuleDescriptor;
++import java.lang.module.ModuleDescriptor.Requires;
+ import java.lang.module.ModuleDescriptor.Requires.Modifier;
+ 
+ import java.nio.ByteBuffer;
+-import java.util.Deque;
++import java.util.ArrayList;
++import java.util.Comparator;
+ import java.util.HashMap;
+ import java.util.HashSet;
+-import java.util.LinkedList;
++import java.util.LinkedHashSet;
++import java.util.List;
+ import java.util.Map;
+ import java.util.Set;
+ import java.util.stream.Stream;
+@@ -45,9 +48,8 @@
+  * Helper class to sort modules in topological order
+  */
+ public final class ModuleSorter {
+-    private final Deque<ResourcePoolModule> nodes = new LinkedList<>();
+-    private final Map<String, Set<ResourcePoolModule>> edges = new HashMap<>();
+-    private final Deque<ResourcePoolModule> result = new LinkedList<>();
++    private final Map<ResourcePoolModule, Set<ResourcePoolModule>> graph = new HashMap<>();
++    private final List<ResourcePoolModule> result = new ArrayList<>();
+ 
+     private final ResourcePoolModuleView moduleView;
+ 
+@@ -69,11 +71,17 @@
+ 
+     private ModuleSorter addModule(ResourcePoolModule module) {
+         addNode(module);
+-        readModuleDescriptor(module).requires().forEach(req -> {
++        // the module graph will be traversed in a stable order for
++        // the topological sort. So add the dependences in the module name order
++        readModuleDescriptor(module).requires()
++                                    .stream()
++                                    .sorted(Comparator.comparing(Requires::name))
++                                    .forEach(req ->
++        {
+             ResourcePoolModule dep = moduleView.findModule(req.name()).orElse(null);
+             if (dep != null) {
+                 addNode(dep);
+-                edges.get(module.name()).add(dep);
++                graph.get(module).add(dep);
+             } else if (!req.modifiers().contains(Modifier.STATIC)) {
+                 throw new PluginException(req.name() + " not found");
+             }
+@@ -82,22 +90,23 @@
+     }
+ 
+     private void addNode(ResourcePoolModule module) {
+-        nodes.add(module);
+-        edges.computeIfAbsent(module.name(), _n -> new HashSet<>());
++        graph.computeIfAbsent(module, _n -> new LinkedHashSet<>());
+     }
+ 
++    /*
++     * The module graph will be traversed in a stable order
++     * (traversing the modules and their dependences in alphabetical order)
++     * so that it will produce the same result of a given module graph.
++     */
+     private synchronized void build() {
+-        if (!result.isEmpty() || nodes.isEmpty())
++        if (!result.isEmpty() || graph.isEmpty())
+             return;
+ 
+-        Deque<ResourcePoolModule> visited = new LinkedList<>();
+-        Deque<ResourcePoolModule> done = new LinkedList<>();
+-        ResourcePoolModule node;
+-        while ((node = nodes.poll()) != null) {
+-            if (!visited.contains(node)) {
+-                visit(node, visited, done);
+-            }
+-        }
++        Set<ResourcePoolModule> visited = new HashSet<>();
++        Set<ResourcePoolModule> done = new HashSet<>();
++        graph.keySet().stream()
++             .sorted(Comparator.comparing(ResourcePoolModule::name))
++             .forEach(node -> visit(node, visited, done));
+     }
+ 
+     public Stream<ResourcePoolModule> sorted() {
+@@ -106,19 +115,21 @@
+     }
+ 
+     private void visit(ResourcePoolModule node,
+-                       Deque<ResourcePoolModule> visited,
+-                       Deque<ResourcePoolModule> done) {
++                       Set<ResourcePoolModule> visited,
++                       Set<ResourcePoolModule> done) {
+         if (visited.contains(node)) {
+             if (!done.contains(node)) {
+                 throw new IllegalArgumentException("Cyclic detected: " +
+-                    node + " " + edges.get(node.name()));
++                    node + " " + graph.get(node));
+             }
+             return;
+         }
++
++        // traverse the dependences of the given module which are
++        // also sorted in alphabetical order
+         visited.add(node);
+-        edges.get(node.name())
+-             .forEach(x -> visit(x, visited, done));
++        graph.get(node).forEach(x -> visit(x, visited, done));
+         done.add(node);
+-        result.addLast(node);
++        result.add(node);
+     }
+ }
diff --git a/gnu/packages/patches/openjdk-9-module3-reproducibility.patch b/gnu/packages/patches/openjdk-9-module3-reproducibility.patch
new file mode 100644
index 0000000000..9db54f5531
--- /dev/null
+++ b/gnu/packages/patches/openjdk-9-module3-reproducibility.patch
@@ -0,0 +1,36 @@
+From: Danny Milosavljevic <dannym <at> scratchpost.org>
+Date: Wed, 18 Apr 2022 21:50:00 +0100
+Subject: Make module descriptor reproducible
+
+--- orig/jdk-3cc80be736f2/jdk/src/java.base/share/classes/java/lang/module/ModuleDescriptor.java	1970-01-01 01:00:01.000000000 +0100
++++ jdk-3cc80be736f2/jdk/src/java.base/share/classes/java/lang/module/ModuleDescriptor.java	2022-04-13 17:30:37.242775977 +0200
+@@ -43,6 +43,7 @@
+ import java.util.Objects;
+ import java.util.Optional;
+ import java.util.Set;
++import java.util.TreeSet;
+ import java.util.function.Supplier;
+ import java.util.stream.Collectors;
+ import java.util.stream.Stream;
+@@ -2155,9 +2156,9 @@
+          * @return The module descriptor
+          */
+         public ModuleDescriptor build() {
+-            Set<Requires> requires = new HashSet<>(this.requires.values());
+-            Set<Exports> exports = new HashSet<>(this.exports.values());
+-            Set<Opens> opens = new HashSet<>(this.opens.values());
++            Set<Requires> requires = new TreeSet<>(this.requires.values());
++            Set<Exports> exports = new TreeSet<>(this.exports.values());
++            Set<Opens> opens = new TreeSet<>(this.opens.values());
+ 
+             // add dependency on java.base
+             if (strict
+@@ -2169,7 +2170,7 @@
+                                           null));
+             }
+ 
+-            Set<Provides> provides = new HashSet<>(this.provides.values());
++            Set<Provides> provides = new TreeSet<>(this.provides.values());
+ 
+             return new ModuleDescriptor(name,
+                                         version,
-- 
2.36.1





Information forwarded to guix-patches <at> gnu.org:
bug#55751; Package guix-patches. (Wed, 01 Jun 2022 13:01:03 GMT) Full text and rfc822 format available.

Message #11 received at 55751 <at> debbugs.gnu.org (full text, mbox):

From: dannym <at> scratchpost.org
To: 55751 <at> debbugs.gnu.org
Cc: Danny Milosavljevic <dannym <at> scratchpost.org>
Subject: [PATCH 3/8] gnu: openjdk11: Make more reproducible.
Date: Wed,  1 Jun 2022 15:00:06 +0200
From: Danny Milosavljevic <dannym <at> scratchpost.org>

* gnu/packages/java.scm (openjdk11)[source]: Add patches.
[arguments]<#:phases>[remove-timestamping]: Add phase.
* gnu/packages/patches/openjdk-11-classlist-reproducibility.patch: New file.
* gnu/local.mk (dist_patch_DATA): Add patches.
---
 gnu/local.mk                                  |  1 +
 gnu/packages/java.scm                         | 21 ++++++++++++++++++-
 ...openjdk-11-classlist-reproducibility.patch | 11 ++++++++++
 3 files changed, 32 insertions(+), 1 deletion(-)
 create mode 100644 gnu/packages/patches/openjdk-11-classlist-reproducibility.patch

diff --git a/gnu/local.mk b/gnu/local.mk
index 0a81e0fe75..eaf0e306fb 100644
--- a/gnu/local.mk
+++ b/gnu/local.mk
@@ -1582,6 +1582,7 @@ dist_patch_DATA =						\
   %D%/packages/patches/openjdk-10-module-reproducibility.patch	\
   %D%/packages/patches/openjdk-10-module3-reproducibility.patch	\
   %D%/packages/patches/openjdk-10-module4-reproducibility.patch	\
+  %D%/packages/patches/openjdk-11-classlist-reproducibility.patch	\
   %D%/packages/patches/openjdk-15-xcursor-no-dynamic.patch	\
   %D%/packages/patches/openmpi-mtl-priorities.patch		\
   %D%/packages/patches/openssh-hurd.patch			\
diff --git a/gnu/packages/java.scm b/gnu/packages/java.scm
index 37b310141e..5a1e45ca68 100644
--- a/gnu/packages/java.scm
+++ b/gnu/packages/java.scm
@@ -1842,7 +1842,17 @@ (define-public openjdk11
               (snippet
                `(begin
                   (for-each delete-file (find-files "." ".*.(bin|exe|jar)$"))
-                  #t))))
+                  #t))
+              (patches
+               (search-patches ;"openjdk-10-module-reproducibility.patch"
+                        "openjdk-10-module3-reproducibility.patch"
+                        "openjdk-10-module4-reproducibility.patch"
+                        "openjdk-10-char-reproducibility.patch"
+                        "openjdk-11-classlist-reproducibility.patch"
+                        ;"openjdk-10-corba-reproducibility.patch"
+                        ;"openjdk-10-idlj-reproducibility.patch"
+                        "openjdk-10-jar-reproducibility.patch"
+                        "openjdk-10-jtask-reproducibility.patch"))))
     (build-system gnu-build-system)
     (outputs '("out" "jdk" "doc"))
     (arguments
@@ -1869,6 +1879,10 @@ (define-public openjdk11
          "--with-libjpeg=system"
          "--with-libpng=system"
          "--with-version-pre="
+         ;; should be set by SOURCE_DATE_EPOCH handler, but
+         ;; isn't being set. So manually do it.
+         "--with-hotspot-build-time=1970-01-01T00:00:01"
+         "--enable-reproducible-build" ; to be sure
          ;; allow the build system to locate the system freetype
          ,(string-append "--with-freetype-include="
                          (assoc-ref %build-inputs "freetype") "/include")
@@ -1883,6 +1897,11 @@ (define-public openjdk11
              (substitute* "make/data/blockedcertsconverter/blocked.certs.pem"
                (("^#!.*") "#! java BlockedCertsConverter SHA-256\n"))
              #t))
+         (add-after 'unpack 'remove-timestamping
+           (lambda _
+             (substitute* "src/hotspot/share/runtime/abstract_vm_version.cpp"
+              (("__DATE__") "")
+              (("__TIME__") ""))))
          (add-after 'unpack 'patch-jni-libs
            ;; Hardcode dynamically loaded libraries.
            (lambda _
diff --git a/gnu/packages/patches/openjdk-11-classlist-reproducibility.patch b/gnu/packages/patches/openjdk-11-classlist-reproducibility.patch
new file mode 100644
index 0000000000..2ac7c2b664
--- /dev/null
+++ b/gnu/packages/patches/openjdk-11-classlist-reproducibility.patch
@@ -0,0 +1,11 @@
+--- jdk-11.0.13-ga/make/GenerateLinkOptData.gmk.orig	2022-04-04 17:18:56.801929954 +0200
++++ jdk-11.0.13-ga/make/GenerateLinkOptData.gmk	2022-04-04 17:19:14.962422622 +0200
+@@ -66,7 +66,7 @@
+ 	    -cp $(SUPPORT_OUTPUTDIR)/classlist.jar \
+ 	    build.tools.classlist.HelloClasslist \
+ 	    $(LOG_DEBUG) 2>&1 > $(JLI_TRACE_FILE)
+-	$(GREP) -v HelloClasslist $@.raw > $@
++	$(GREP) -v HelloClasslist $@.raw |sort > $@
+ 
+ # The jli trace is created by the same recipe as classlist. By declaring these
+ # dependencies, make will correctly rebuild both jli trace and classlist
-- 
2.36.1





Information forwarded to guix-patches <at> gnu.org:
bug#55751; Package guix-patches. (Wed, 01 Jun 2022 13:01:03 GMT) Full text and rfc822 format available.

Message #14 received at 55751 <at> debbugs.gnu.org (full text, mbox):

From: dannym <at> scratchpost.org
To: 55751 <at> debbugs.gnu.org
Cc: Danny Milosavljevic <dannym <at> scratchpost.org>
Subject: [PATCH 4/8] gnu: openjdk12: Make reproducible.
Date: Wed,  1 Jun 2022 15:00:07 +0200
From: Danny Milosavljevic <dannym <at> scratchpost.org>

* gnu/packages/java.scm (openjdk12)[arguments]<#:phases>[remove-timestamping]:
Modify phase.
---
 gnu/packages/java.scm | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/gnu/packages/java.scm b/gnu/packages/java.scm
index 5a1e45ca68..1a872ce786 100644
--- a/gnu/packages/java.scm
+++ b/gnu/packages/java.scm
@@ -2138,6 +2138,11 @@ (define-public openjdk12
      (substitute-keyword-arguments (package-arguments openjdk11)
        ((#:phases phases)
         `(modify-phases ,phases
+           (replace 'remove-timestamping
+             (lambda _
+               (substitute* "src/hotspot/share/runtime/vm_version.cpp"
+                (("__DATE__") "")
+                (("__TIME__") ""))))
            (replace 'fix-java-shebangs
              (lambda _
                ;; This file was "fixed" by patch-source-shebangs, but it requires
-- 
2.36.1





Information forwarded to guix-patches <at> gnu.org:
bug#55751; Package guix-patches. (Wed, 01 Jun 2022 13:01:03 GMT) Full text and rfc822 format available.

Message #17 received at 55751 <at> debbugs.gnu.org (full text, mbox):

From: dannym <at> scratchpost.org
To: 55751 <at> debbugs.gnu.org
Cc: Danny Milosavljevic <dannym <at> scratchpost.org>
Subject: [PATCH 6/8] gnu: openjdk14: Make reproducible.
Date: Wed,  1 Jun 2022 15:00:09 +0200
From: Danny Milosavljevic <dannym <at> scratchpost.org>

* gnu/packages/java.scm (openjdk14)[source]: Add patches.
---
 gnu/packages/java.scm | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/gnu/packages/java.scm b/gnu/packages/java.scm
index 7bf8527d67..2599170d84 100644
--- a/gnu/packages/java.scm
+++ b/gnu/packages/java.scm
@@ -2245,6 +2245,9 @@ (define-public openjdk14
               (sha256
                (base32
                 "07k9bsbxwyf2z2n50z96nvhsdai916mxdxcr5lm44jz7f6xrwfq6"))
+              (patches
+                (search-patches "openjdk-13-classlist-reproducibility.patch"
+                                "openjdk-10-jtask-reproducibility.patch"))
               (modules '((guix build utils)))
               (snippet
                `(begin
-- 
2.36.1





Information forwarded to guix-patches <at> gnu.org:
bug#55751; Package guix-patches. (Wed, 01 Jun 2022 13:01:04 GMT) Full text and rfc822 format available.

Message #20 received at 55751 <at> debbugs.gnu.org (full text, mbox):

From: dannym <at> scratchpost.org
To: 55751 <at> debbugs.gnu.org
Cc: Danny Milosavljevic <dannym <at> scratchpost.org>
Subject: [PATCH 5/8] gnu: openjdk13: Make reproducible.
Date: Wed,  1 Jun 2022 15:00:08 +0200
From: Danny Milosavljevic <dannym <at> scratchpost.org>

* gnu/packages/patches/openjdk-13-classlist-reproducibility.patch: New file.
* gnu/local.mk (dist_patch_DATA): Add patch.
* gnu/packages/java.scm (openjdk13)[source]: Add patch.
[arguments]<#:phases>[remove-timestamping]: Modify phase.
---
 gnu/local.mk                                         |  1 +
 gnu/packages/java.scm                                | 12 ++++++++++++
 .../openjdk-13-classlist-reproducibility.patch       | 11 +++++++++++
 3 files changed, 24 insertions(+)
 create mode 100644 gnu/packages/patches/openjdk-13-classlist-reproducibility.patch

diff --git a/gnu/local.mk b/gnu/local.mk
index eaf0e306fb..aab850b4f7 100644
--- a/gnu/local.mk
+++ b/gnu/local.mk
@@ -1583,6 +1583,7 @@ dist_patch_DATA =						\
   %D%/packages/patches/openjdk-10-module3-reproducibility.patch	\
   %D%/packages/patches/openjdk-10-module4-reproducibility.patch	\
   %D%/packages/patches/openjdk-11-classlist-reproducibility.patch	\
+  %D%/packages/patches/openjdk-13-classlist-reproducibility.patch	\
   %D%/packages/patches/openjdk-15-xcursor-no-dynamic.patch	\
   %D%/packages/patches/openmpi-mtl-priorities.patch		\
   %D%/packages/patches/openssh-hurd.patch			\
diff --git a/gnu/packages/java.scm b/gnu/packages/java.scm
index 1a872ce786..7bf8527d67 100644
--- a/gnu/packages/java.scm
+++ b/gnu/packages/java.scm
@@ -2189,11 +2189,23 @@ (define-public openjdk13
               (sha256
                (base32
                 "0wrrr0d7lz1v8qqm752mn4gz5l2vpl2kmx4ac3ysvk4mljc924hp"))
+              (patches
+                (search-patches "openjdk-13-classlist-reproducibility.patch"
+                                "openjdk-10-jtask-reproducibility.patch"))
               (modules '((guix build utils)))
               (snippet
                `(begin
                   (for-each delete-file (find-files "." ".*.(bin|exe|jar)$"))
                   #t))))
+    (arguments
+     (substitute-keyword-arguments (package-arguments openjdk12)
+       ((#:phases phases)
+        `(modify-phases ,phases
+           (replace 'remove-timestamping
+             (lambda _
+               (substitute* "src/hotspot/share/runtime/abstract_vm_version.cpp"
+                (("__DATE__") "")
+                (("__TIME__") ""))))))))
     (inputs
      `(("alsa-lib" ,alsa-lib)
        ("cups" ,cups)
diff --git a/gnu/packages/patches/openjdk-13-classlist-reproducibility.patch b/gnu/packages/patches/openjdk-13-classlist-reproducibility.patch
new file mode 100644
index 0000000000..326f6875ec
--- /dev/null
+++ b/gnu/packages/patches/openjdk-13-classlist-reproducibility.patch
@@ -0,0 +1,11 @@
+--- 6cllxkf0narh0b4wgx8npwjkznd7ifq0-openjdk-13.0.7-checkout/make/GenerateLinkOptData.gmk.orig	2022-04-04 17:20:33.012539984 +0200
++++ 6cllxkf0narh0b4wgx8npwjkznd7ifq0-openjdk-13.0.7-checkout/make/GenerateLinkOptData.gmk	2022-04-04 17:20:51.181032859 +0200
+@@ -78,7 +78,7 @@
+ 	        $(CAT) $(LINK_OPT_DIR)/stderr $(JLI_TRACE_FILE) ; \
+ 	        exit $$exitcode \
+ 	    )
+-	$(GREP) -v HelloClasslist $@.raw > $@
++	$(GREP) -v HelloClasslist $@.raw | sort > $@
+ 
+ # The jli trace is created by the same recipe as classlist. By declaring these
+ # dependencies, make will correctly rebuild both jli trace and classlist
-- 
2.36.1





Information forwarded to guix-patches <at> gnu.org:
bug#55751; Package guix-patches. (Wed, 01 Jun 2022 13:01:04 GMT) Full text and rfc822 format available.

Message #23 received at 55751 <at> debbugs.gnu.org (full text, mbox):

From: dannym <at> scratchpost.org
To: 55751 <at> debbugs.gnu.org
Cc: Danny Milosavljevic <dannym <at> scratchpost.org>
Subject: [PATCH 7/8] gnu: openjdk15: Make reproducible.
Date: Wed,  1 Jun 2022 15:00:10 +0200
From: Danny Milosavljevic <dannym <at> scratchpost.org>

* gnu/packages/java.scm (openjdk15)[source]: Add patch.
---
 gnu/packages/java.scm | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/gnu/packages/java.scm b/gnu/packages/java.scm
index 2599170d84..368abf8ba6 100644
--- a/gnu/packages/java.scm
+++ b/gnu/packages/java.scm
@@ -2297,7 +2297,8 @@ (define-public openjdk15
                (base32
                 "168cr08nywp0q3vyj8njkhsmmnyd8rz9r58hk4xhzdzc6bdfkl1i"))
               (patches
-                (search-patches "openjdk-15-xcursor-no-dynamic.patch"))))
+                (search-patches "openjdk-15-jtask-reproducibility.patch"
+                                "openjdk-15-xcursor-no-dynamic.patch"))))
     (inputs
      (cons `("libxcursor" ,libxcursor) ; for our patch to work
            (package-inputs openjdk14)))
-- 
2.36.1





Information forwarded to guix-patches <at> gnu.org:
bug#55751; Package guix-patches. (Wed, 01 Jun 2022 13:01:05 GMT) Full text and rfc822 format available.

Message #26 received at 55751 <at> debbugs.gnu.org (full text, mbox):

From: dannym <at> scratchpost.org
To: 55751 <at> debbugs.gnu.org
Cc: Danny Milosavljevic <dannym <at> scratchpost.org>
Subject: [PATCH 8/8] gnu: openjdk16: Make reproducible.
Date: Wed,  1 Jun 2022 15:00:11 +0200
From: Danny Milosavljevic <dannym <at> scratchpost.org>

* gnu/packages/java.scm (openjdk16)[source]: Add patch.
---
 gnu/packages/java.scm | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/gnu/packages/java.scm b/gnu/packages/java.scm
index 368abf8ba6..d1538d0afa 100644
--- a/gnu/packages/java.scm
+++ b/gnu/packages/java.scm
@@ -2326,7 +2326,8 @@ (define-public openjdk16
                (base32
                 "1ggddsbsar4dj2fycfqqqagqil7prhb30afvq6933rz7pa9apm2f"))
               (patches
-                (search-patches "openjdk-15-xcursor-no-dynamic.patch"))))
+                (search-patches "openjdk-15-jtask-reproducibility.patch"
+                                "openjdk-15-xcursor-no-dynamic.patch"))))
     (native-inputs
      `(("autoconf" ,autoconf)
        ("openjdk15:jdk" ,openjdk15 "jdk")
-- 
2.36.1





Information forwarded to guix-patches <at> gnu.org:
bug#55751; Package guix-patches. (Wed, 01 Jun 2022 13:01:05 GMT) Full text and rfc822 format available.

Message #29 received at 55751 <at> debbugs.gnu.org (full text, mbox):

From: dannym <at> scratchpost.org
To: 55751 <at> debbugs.gnu.org
Cc: Danny Milosavljevic <dannym <at> scratchpost.org>
Subject: [PATCH 2/8] gnu: openjdk10: Make more reproducible.
Date: Wed,  1 Jun 2022 15:00:05 +0200
From: Danny Milosavljevic <dannym <at> scratchpost.org>

* gnu/packages/patches/openjdk-10-char-reproducibility.patch: New file.
* gnu/packages/patches/openjdk-10-classlist-reproducibility.patch: New file.
* gnu/packages/patches/openjdk-10-corba-reproducibility.patch: New file.
* gnu/packages/patches/openjdk-10-jar-reproducibility.patch: New file.
* gnu/packages/patches/openjdk-10-jtask-reproducibility.patch: New file.
* gnu/packages/patches/openjdk-10-module-reproducibility.patch: New file.
* gnu/packages/patches/openjdk-10-module3-reproducibility.patch: New file.
* gnu/packages/patches/openjdk-10-module4-reproducibility.patch: New file.
* gnu/packages/java.scm (openjdk10)[source]: Add patches.
[arguments]<#:phases>[remove-timestamping]: New phase.
* gnu/local.mk (dist_patch_DATA): Add patches.
---
 gnu/local.mk                                  |   8 +
 gnu/packages/java.scm                         |  15 +-
 .../openjdk-10-char-reproducibility.patch     |  12 +
 ...openjdk-10-classlist-reproducibility.patch |  27 ++
 .../openjdk-10-corba-reproducibility.patch    |  12 +
 .../openjdk-10-jar-reproducibility.patch      | 103 ++++++
 .../openjdk-10-jtask-reproducibility.patch    |  53 +++
 .../openjdk-10-module-reproducibility.patch   | 305 ++++++++++++++++++
 .../openjdk-10-module3-reproducibility.patch  |  34 ++
 .../openjdk-10-module4-reproducibility.patch  |  14 +
 10 files changed, 582 insertions(+), 1 deletion(-)
 create mode 100644 gnu/packages/patches/openjdk-10-char-reproducibility.patch
 create mode 100644 gnu/packages/patches/openjdk-10-classlist-reproducibility.patch
 create mode 100644 gnu/packages/patches/openjdk-10-corba-reproducibility.patch
 create mode 100644 gnu/packages/patches/openjdk-10-jar-reproducibility.patch
 create mode 100644 gnu/packages/patches/openjdk-10-jtask-reproducibility.patch
 create mode 100644 gnu/packages/patches/openjdk-10-module-reproducibility.patch
 create mode 100644 gnu/packages/patches/openjdk-10-module3-reproducibility.patch
 create mode 100644 gnu/packages/patches/openjdk-10-module4-reproducibility.patch

diff --git a/gnu/local.mk b/gnu/local.mk
index 5ba5af94a6..0a81e0fe75 100644
--- a/gnu/local.mk
+++ b/gnu/local.mk
@@ -1573,7 +1573,15 @@ dist_patch_DATA =						\
   %D%/packages/patches/openjdk-9-module-reproducibility.patch	\
   %D%/packages/patches/openjdk-9-module2-reproducibility.patch	\
   %D%/packages/patches/openjdk-9-module3-reproducibility.patch	\
+  %D%/packages/patches/openjdk-10-char-reproducibility.patch	\
+  %D%/packages/patches/openjdk-10-classlist-reproducibility.patch	\
+  %D%/packages/patches/openjdk-10-corba-reproducibility.patch	\
   %D%/packages/patches/openjdk-10-idlj-reproducibility.patch	\
+  %D%/packages/patches/openjdk-10-jar-reproducibility.patch	\
+  %D%/packages/patches/openjdk-10-jtask-reproducibility.patch	\
+  %D%/packages/patches/openjdk-10-module-reproducibility.patch	\
+  %D%/packages/patches/openjdk-10-module3-reproducibility.patch	\
+  %D%/packages/patches/openjdk-10-module4-reproducibility.patch	\
   %D%/packages/patches/openjdk-15-xcursor-no-dynamic.patch	\
   %D%/packages/patches/openmpi-mtl-priorities.patch		\
   %D%/packages/patches/openssh-hurd.patch			\
diff --git a/gnu/packages/java.scm b/gnu/packages/java.scm
index 3d36849f7d..37b310141e 100644
--- a/gnu/packages/java.scm
+++ b/gnu/packages/java.scm
@@ -1763,7 +1763,15 @@ (define-public openjdk10
                (base32
                 "0zywq2203b4hx4jms9vbwvjcj1d3k2v3qpx4s33729fkpmid97r4"))
               (patches (search-patches
-                        "openjdk-10-idlj-reproducibility.patch"))
+                        "openjdk-10-module-reproducibility.patch"
+                        "openjdk-10-module3-reproducibility.patch"
+                        "openjdk-10-module4-reproducibility.patch"
+                        "openjdk-10-char-reproducibility.patch"
+                        "openjdk-10-classlist-reproducibility.patch"
+                        "openjdk-10-corba-reproducibility.patch"
+                        "openjdk-10-idlj-reproducibility.patch"
+                        "openjdk-10-jar-reproducibility.patch"
+                        "openjdk-10-jtask-reproducibility.patch"))
               (modules '((guix build utils)))
               (snippet
                `(begin
@@ -1780,6 +1788,11 @@ (define-public openjdk10
                (substitute* "make/data/blacklistedcertsconverter/blacklisted.certs.pem"
                  (("^#!.*") "#! java BlacklistedCertsConverter SHA-256\n"))
                #t))
+           (add-after 'unpack 'remove-timestamping
+             (lambda _
+               (substitute* "./src/hotspot/share/runtime/vm_version.cpp"
+                 (("__DATE__") "")
+                 (("__TIME__") ""))))
            (replace 'configure
              (lambda* (#:key inputs outputs #:allow-other-keys)
                (invoke "bash" "./configure"
diff --git a/gnu/packages/patches/openjdk-10-char-reproducibility.patch b/gnu/packages/patches/openjdk-10-char-reproducibility.patch
new file mode 100644
index 0000000000..a7932678af
--- /dev/null
+++ b/gnu/packages/patches/openjdk-10-char-reproducibility.patch
@@ -0,0 +1,12 @@
+Danny
+--- orig/jdk-6fa770f9f8ab/make/jdk/src/classes/build/tools/generatecharacter/GenerateCharacter.java	2022-04-13 19:24:10.211683257 +0200
++++ jdk-6fa770f9f8ab/make/jdk/src/classes/build/tools/generatecharacter/GenerateCharacter.java	2022-04-13 22:51:50.680487330 +0200
+@@ -693,7 +693,7 @@
+         PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(theOutputFileName)));
+         out.println(commentStart +
+             " This file was generated AUTOMATICALLY from a template file " +
+-            new java.util.Date() + commentEnd);
++            (System.getenv("SOURCE_DATE_EPOCH") == null ? new java.util.Date() : new java.util.Date(1000 * Long.parseLong(System.getenv("SOURCE_DATE_EPOCH")))) + commentEnd);
+         int marklen = commandMarker.length();
+         LOOP: while(true) {
+             try {
diff --git a/gnu/packages/patches/openjdk-10-classlist-reproducibility.patch b/gnu/packages/patches/openjdk-10-classlist-reproducibility.patch
new file mode 100644
index 0000000000..e1292ba82d
--- /dev/null
+++ b/gnu/packages/patches/openjdk-10-classlist-reproducibility.patch
@@ -0,0 +1,27 @@
+--- orig/jdk-6fa770f9f8ab/make/GenerateLinkOptData.gmk	2022-04-04 17:16:29.365930149 +0200
++++ jdk-6fa770f9f8ab/make/GenerateLinkOptData.gmk	2022-04-04 17:16:54.954624358 +0200
+@@ -61,11 +61,12 @@
+ 	$(call MakeDir, $(LINK_OPT_DIR))
+ 	$(call LogInfo, Generating $(patsubst $(OUTPUTDIR)/%, %, $@))
+ 	$(call LogInfo, Generating $(patsubst $(OUTPUTDIR)/%, %, $(JLI_TRACE_FILE)))
+-	$(FIXPATH) $(INTERIM_IMAGE_DIR)/bin/java -XX:DumpLoadedClassList=$@ \
++	$(FIXPATH) $(INTERIM_IMAGE_DIR)/bin/java -XX:DumpLoadedClassList=$@.tmp \
+ 	    -Djava.lang.invoke.MethodHandle.TRACE_RESOLVE=true \
+ 	    -cp $(SUPPORT_OUTPUTDIR)/classlist.jar \
+ 	    build.tools.classlist.HelloClasslist \
+ 	    $(LOG_DEBUG) 2>&1 > $(JLI_TRACE_FILE)
++	sort $@.tmp > $@
+ 
+ # The jli trace is created by the same recipe as classlist. By declaring these
+ # dependencies, make will correctly rebuild both jli trace and classlist
+--- orig/jdk-6fa770f9f8ab/make/gendata/Gendata-jdk.compiler.gmk	2022-04-13 19:24:10.191682716 +0200
++++ jdk-6fa770f9f8ab/make/gendata/Gendata-jdk.compiler.gmk	2022-04-13 20:58:57.891368216 +0200
+@@ -83,6 +83,8 @@
+ 	    $(CT_MODULESOURCEPATH) \
+ 	    $(CT_MODULES) \
+ 	    >$(@D)/A/system-modules
++	# Make files reproducible
++	find $(@D) -exec $(TOUCH) -h -c -t 197001010000.01 {} \;
+ 	$(TOUCH) $@
+ 
+ # Can't generate ct.sym directly into modules libs as the SetupJarArchive macro
diff --git a/gnu/packages/patches/openjdk-10-corba-reproducibility.patch b/gnu/packages/patches/openjdk-10-corba-reproducibility.patch
new file mode 100644
index 0000000000..bd5ce1fd2b
--- /dev/null
+++ b/gnu/packages/patches/openjdk-10-corba-reproducibility.patch
@@ -0,0 +1,12 @@
+Danny
+--- orig/jdk-6fa770f9f8ab/make/corba/src/classes/build/tools/logutil/MC.java	2022-04-13 19:24:10.111680549 +0200
++++ jdk-6fa770f9f8ab/make/corba/src/classes/build/tools/logutil/MC.java	2022-04-13 22:51:13.399462259 +0200
+@@ -154,7 +154,7 @@
+                   groupName);
+     pw.println("//");
+     pw.printMsg("// Generated by MC.java version @, DO NOT EDIT BY HAND!", VERSION);
+-    pw.printMsg("// Generated from input file @ on @", inFile, new Date());
++    pw.printMsg("// Generated from input file @ on @", inFile, System.getenv("SOURCE_DATE_EPOCH") == null ? new Date() : new Date(1000 * Long.parseLong(System.getenv("SOURCE_DATE_EPOCH"))));
+     pw.println();
+   }
+ 
diff --git a/gnu/packages/patches/openjdk-10-jar-reproducibility.patch b/gnu/packages/patches/openjdk-10-jar-reproducibility.patch
new file mode 100644
index 0000000000..176eedfce6
--- /dev/null
+++ b/gnu/packages/patches/openjdk-10-jar-reproducibility.patch
@@ -0,0 +1,103 @@
+diff -ru orig/jdk-6fa770f9f8ab/make/common/JarArchive.gmk jdk-6fa770f9f8ab/make/common/JarArchive.gmk
+--- orig/jdk-6fa770f9f8ab/make/common/JarArchive.gmk	2022-04-13 19:24:10.107680441 +0200
++++ jdk-6fa770f9f8ab/make/common/JarArchive.gmk	2022-04-13 19:31:18.031271019 +0200
+@@ -251,12 +251,14 @@
+ 	    $(ECHO) "Main-Class: $$(strip $$($1_JARMAIN))" >> $$($1_MANIFEST_FILE) $$(NEWLINE)) \
+ 	  $$(if $$($1_EXTRA_MANIFEST_ATTR), \
+ 	    $(PRINTF) "$$($1_EXTRA_MANIFEST_ATTR)\n" >> $$($1_MANIFEST_FILE) $$(NEWLINE)) \
++	  $(TOUCH) -h -c -t 197001010000.00 $$($1_MANIFEST_FILE) $$(NEWLINE) \
+ 	  $(ECHO) Creating $$($1_NAME) $$(NEWLINE) \
+ 	  $$($1_JAR_CMD) $$($1_JAR_CREATE_OPTIONS) $$@ $$($1_MANIFEST_FILE) $$(NEWLINE) \
+ 	  $$($1_SCAPTURE_CONTENTS) \
+ 	  $$($1_SCAPTURE_METAINF) \
+ 	  $$($1_SUPDATE_CONTENTS) \
+-	  $$($1_JARINDEX) && true \
++	  $$($1_JARINDEX) && true $$(NEWLINE) \
++	  d="`mktemp -d`" && $(CP) -f $$@ "$$$$d/a.jar" && (cd "$$$$d" && unzip a.jar META-INF/MANIFEST.MF && $(TOUCH) -h -c -t 197001010000.00 META-INF &&  $(TOUCH) -h -c -t 197001010000.00 META-INF/MANIFEST.MF && (zip --symlinks -0 -X a.jar META-INF META-INF/MANIFEST.MF; zip --symlinks -0 -X a.jar META-INF META-INF/MANIFEST.MF)) && $(CP) -f "$$$$d/a.jar" $$@ \
+ 	, \
+ 	  $(ECHO) Modifying $$($1_NAME) $$(NEWLINE) \
+ 	  $$($1_CAPTURE_CONTENTS) \
+diff -ru orig/jdk-6fa770f9f8ab/make/JrtfsJar.gmk jdk-6fa770f9f8ab/make/JrtfsJar.gmk
+--- orig/jdk-6fa770f9f8ab/make/JrtfsJar.gmk	2022-04-13 19:24:10.091680007 +0200
++++ jdk-6fa770f9f8ab/make/JrtfsJar.gmk	2022-04-13 19:29:30.044346222 +0200
+@@ -57,13 +57,18 @@
+ # file will not be copied unless META-INF/services would also be added to the INCLUDES.
+ # Adding META-INF/services would include all files in that directory when only the one
+ # is needed, which is why this explicit copy is defined instead.
+-$(eval $(call SetupCopyFiles, COPY_JIMAGE_SERVICE_PROVIDER, \
++$(eval $(call SetupCopyFiles, COPY_JIMAGE_SERVICE_PROVIDER, \
+     SRC := $(TOPDIR)/src/java.base/share/classes, \
+     DEST := $(SUPPORT_OUTPUTDIR)/jrtfs_classes, \
+     FILES := META-INF/services/java.nio.file.spi.FileSystemProvider))
+ 
++.PHONY: $(COPY_JIMAGE_SERVICE_PROVIDER)_fix
++$(COPY_JIMAGE_SERVICE_PROVIDER)_fix: $(COPY_JIMAGE_SERVICE_PROVIDER)
++	find $(SUPPORT_OUTPUTDIR)/jrtfs_classes -exec $(TOUCH) -h -c -t 197001010000.00 {} \;
++	$(TOUCH) -h -c -t 197001010000.00 $(SUPPORT_OUTPUTDIR)/java-main-manifest.mf
++
+ $(eval $(call SetupJarArchive,BUILD_JRTFS_JAR, \
+-    DEPENDENCIES := $(BUILD_JRTFS) $(COPY_JIMAGE_SERVICE_PROVIDER), \
++    DEPENDENCIES := $(BUILD_JRTFS) $(COPY_JIMAGE_SERVICE_PROVIDER)_fix, \
+     SRCS := $(SUPPORT_OUTPUTDIR)/jrtfs_classes, \
+     JAR := $(SUPPORT_OUTPUTDIR)/modules_libs/java.base/jrt-fs.jar, \
+     MANIFEST := $(SUPPORT_OUTPUTDIR)/java-main-manifest.mf, \
+diff -ru orig/jdk-6fa770f9f8ab/src/jdk.jartool/share/classes/sun/tools/jar/Main.java jdk-6fa770f9f8ab/src/jdk.jartool/share/classes/sun/tools/jar/Main.java
+--- orig/jdk-6fa770f9f8ab/src/jdk.jartool/share/classes/sun/tools/jar/Main.java	2022-04-13 19:24:12.555746751 +0200
++++ jdk-6fa770f9f8ab/src/jdk.jartool/share/classes/sun/tools/jar/Main.java	2022-04-13 19:25:34.117955999 +0200
+@@ -849,12 +849,18 @@
+                     output(getMsg("out.added.manifest"));
+                 }
+                 ZipEntry e = new ZipEntry(MANIFEST_DIR);
+-                e.setTime(System.currentTimeMillis());
++                if (System.getenv("SOURCE_DATE_EPOCH") != null)
++                    e.setTime(1000 * Long.parseLong(System.getenv("SOURCE_DATE_EPOCH")));
++                else
++                    e.setTime(System.currentTimeMillis());
+                 e.setSize(0);
+                 e.setCrc(0);
+                 zos.putNextEntry(e);
+                 e = new ZipEntry(MANIFEST_NAME);
+-                e.setTime(System.currentTimeMillis());
++                if (System.getenv("SOURCE_DATE_EPOCH") != null)
++                    e.setTime(1000 * Long.parseLong(System.getenv("SOURCE_DATE_EPOCH")));
++                else
++                    e.setTime(System.currentTimeMillis());
+                 if (flag0) {
+                     crc32Manifest(e, manifest);
+                 }
+@@ -1021,7 +1027,10 @@
+         throws IOException
+     {
+         ZipEntry e = new ZipEntry(INDEX_NAME);
+-        e.setTime(System.currentTimeMillis());
++        if (System.getenv("SOURCE_DATE_EPOCH") != null)
++            e.setTime(1000 * Long.parseLong(System.getenv("SOURCE_DATE_EPOCH")));
++        else
++            e.setTime(System.currentTimeMillis());
+         if (flag0) {
+             CRC32OutputStream os = new CRC32OutputStream();
+             index.write(os);
+@@ -1040,7 +1049,10 @@
+             String name = mi.getKey();
+             byte[] bytes = mi.getValue();
+             ZipEntry e = new ZipEntry(name);
+-            e.setTime(System.currentTimeMillis());
++            if (System.getenv("SOURCE_DATE_EPOCH") != null)
++                e.setTime(1000 * Long.parseLong(System.getenv("SOURCE_DATE_EPOCH")));
++            else
++                e.setTime(System.currentTimeMillis());
+             if (flag0) {
+                 crc32ModuleInfo(e, bytes);
+             }
+@@ -1065,7 +1077,10 @@
+             addMultiRelease(m);
+         }
+         ZipEntry e = new ZipEntry(MANIFEST_NAME);
+-        e.setTime(System.currentTimeMillis());
++        if (System.getenv("SOURCE_DATE_EPOCH") != null)
++            e.setTime(1000 * Long.parseLong(System.getenv("SOURCE_DATE_EPOCH")));
++        else
++            e.setTime(System.currentTimeMillis());
+         if (flag0) {
+             crc32Manifest(e, m);
+         }
diff --git a/gnu/packages/patches/openjdk-10-jtask-reproducibility.patch b/gnu/packages/patches/openjdk-10-jtask-reproducibility.patch
new file mode 100644
index 0000000000..3411ca12ae
--- /dev/null
+++ b/gnu/packages/patches/openjdk-10-jtask-reproducibility.patch
@@ -0,0 +1,53 @@
+--- jdk-10/src/jdk.jlink/share/classes/jdk/tools/jmod/JmodTask.java.orig	2022-04-04 11:18:52.760626467 +0200
++++ jdk-10/src/jdk.jlink/share/classes/jdk/tools/jmod/JmodTask.java	2022-04-04 12:03:40.645325687 +0200
+@@ -105,6 +105,7 @@
+ import jdk.internal.module.ModuleTarget;
+ import jdk.internal.module.Resources;
+ import jdk.tools.jlink.internal.Utils;
++import java.util.TreeSet;
+ 
+ import static java.util.stream.Collectors.joining;
+ 
+@@ -768,6 +769,7 @@
+         void processSection(JmodOutputStream out, Section section, Path path)
+             throws IOException
+         {
++            TreeSet<Path> paths = new TreeSet<>();
+             Files.walkFileTree(path, Set.of(FileVisitOption.FOLLOW_LINKS),
+                 Integer.MAX_VALUE, new SimpleFileVisitor<Path>() {
+                     @Override
+@@ -781,20 +783,24 @@
+ 
+                         if (!relPath.toString().equals(MODULE_INFO)
+                                 && !matches(relPath, excludes)) {
+-                            try (InputStream in = Files.newInputStream(file)) {
+-                                out.writeEntry(in, section, relPath.toString());
+-                            } catch (IOException x) {
+-                                if (x.getMessage().contains("duplicate entry")) {
+-                                    warning("warn.ignore.duplicate.entry",
+-                                            relPath.toString(), section);
+-                                    return FileVisitResult.CONTINUE;
+-                                }
+-                                throw x;
+-                            }
++                            paths.add(file);
+                         }
+                         return FileVisitResult.CONTINUE;
+                     }
+                 });
++            for (Path file : paths) {
++                Path relPath = path.relativize(file);
++                try (InputStream in = Files.newInputStream(file)) {
++                    out.writeEntry(in, section, relPath.toString());
++                } catch (IOException x) {
++                    if (x.getMessage().contains("duplicate entry")) {
++                        warning("warn.ignore.duplicate.entry",
++                                  relPath.toString(), section);
++                        continue;
++                    }
++                    throw x;
++                }
++            }
+         }
+ 
+         boolean matches(Path path, List<PathMatcher> matchers) {
diff --git a/gnu/packages/patches/openjdk-10-module-reproducibility.patch b/gnu/packages/patches/openjdk-10-module-reproducibility.patch
new file mode 100644
index 0000000000..165edd3b4a
--- /dev/null
+++ b/gnu/packages/patches/openjdk-10-module-reproducibility.patch
@@ -0,0 +1,305 @@
+From a52c4ef44c0553a399a8a47e528db92e3bf51c6c Mon Sep 17 00:00:00 2001
+From: Alan Bateman <alanb <at> openjdk.org>
+Date: Wed, 29 Apr 2020 08:38:28 +0100
+Subject: [PATCH] 8243666: ModuleHashes attribute generated for JMOD and JAR
+ files depends on timestamps
+
+Reviewed-by: mchung
+---
+
+--- orig/jdk-3cc80be736f2/src/java.base/share/classes/jdk/internal/module/ModuleHashesBuilder.java	2022-04-13 19:24:10.655695284 +0200
++++ jdk-3cc80be736f2/src/java.base/share/classes/jdk/internal/module/ModuleHashesBuilder.java	2022-04-14 02:43:48.610326492 +0200
+@@ -27,9 +27,8 @@
+ 
+ import java.io.PrintStream;
+ import java.lang.module.Configuration;
++import java.lang.module.ModuleReference;
+ import java.lang.module.ResolvedModule;
+-import java.net.URI;
+-import java.nio.file.Path;
+ import java.nio.file.Paths;
+ import java.util.ArrayDeque;
+ import java.util.Collections;
+@@ -39,8 +38,8 @@
+ import java.util.LinkedList;
+ import java.util.Map;
+ import java.util.Set;
++import java.util.TreeMap;
+ import java.util.function.Consumer;
+-import java.util.function.Function;
+ import java.util.stream.Stream;
+ import static java.util.stream.Collectors.*;
+ 
+@@ -101,7 +100,7 @@
+         // the modules to record the hashes - it is the first matching
+         // module and has not been hashed during the traversal.
+         Set<String> mods = new HashSet<>();
+-        Map<String, ModuleHashes> hashes = new HashMap<>();
++        Map<String, ModuleHashes> hashes = new TreeMap<>();
+         builder.build()
+                .orderedNodes()
+                .filter(mn -> roots.contains(mn) && !mods.contains(mn))
+@@ -116,27 +115,17 @@
+                    mods.addAll(ns);
+ 
+                    if (!ns.isEmpty()) {
+-                       Map<String, Path> moduleToPath = ns.stream()
+-                           .collect(toMap(Function.identity(), this::moduleToPath));
+-                       hashes.put(mn, ModuleHashes.generate(moduleToPath, "SHA-256"));
++                       Set<ModuleReference> mrefs = ns.stream()
++                               .map(name -> configuration.findModule(name)
++                                                         .orElseThrow(InternalError::new))
++                               .map(ResolvedModule::reference)
++                               .collect(toSet());
++                       hashes.put(mn, ModuleHashes.generate(mrefs, "SHA-256"));
+                    }
+                });
+         return hashes;
+     }
+ 
+-    private Path moduleToPath(String name) {
+-        ResolvedModule rm = configuration.findModule(name).orElseThrow(
+-            () -> new InternalError("Selected module " + name + " not on module path"));
+-
+-        URI uri = rm.reference().location().get();
+-        Path path = Paths.get(uri);
+-        String fn = path.getFileName().toString();
+-        if (!fn.endsWith(".jar") && !fn.endsWith(".jmod")) {
+-            throw new UnsupportedOperationException(path + " is not a modular JAR or jmod file");
+-        }
+-        return path;
+-    }
+-
+     /*
+      * Utility class
+      */diff -ru orig/jdk-3cc80be736f2/src/java.base/share/classes/jdk/internal/module/ModuleHashes.java jdk-3cc80be736f2/src/java.base/share/classes/jdk/internal/module/ModuleHashes.java
+--- orig/jdk-3cc80be736f2/src/java.base/share/classes/jdk/internal/module/ModuleHashes.java	1970-01-01 01:00:01.000000000 +0100
++++ jdk-3cc80be736f2/src/java.base/share/classes/jdk/internal/module/ModuleHashes.java	2022-04-12 16:58:05.639985936 +0200
+@@ -26,17 +26,21 @@
+ package jdk.internal.module;
+ 
+ import java.io.IOException;
++import java.io.InputStream;
+ import java.io.UncheckedIOException;
+-import java.nio.ByteBuffer;
+-import java.nio.channels.FileChannel;
+-import java.nio.file.Path;
++import java.lang.module.ModuleReader;
++import java.lang.module.ModuleReference;
++import java.nio.charset.StandardCharsets;
+ import java.security.MessageDigest;
+ import java.security.NoSuchAlgorithmException;
++import java.util.Arrays;
+ import java.util.Collections;
+ import java.util.HashMap;
+ import java.util.Map;
+ import java.util.Objects;
+ import java.util.Set;
++import java.util.TreeMap;
++import java.util.function.Supplier;
+ 
+ /**
+  * The result of hashing the contents of a number of module artifacts.
+@@ -60,8 +64,8 @@
+      * @param algorithm   the algorithm used to create the hashes
+      * @param nameToHash  the map of module name to hash value
+      */
+-    public ModuleHashes(String algorithm, Map<String, byte[]> nameToHash) {
+-        this.algorithm = algorithm;
++    ModuleHashes(String algorithm, Map<String, byte[]> nameToHash) {
++        this.algorithm = Objects.requireNonNull(algorithm);
+         this.nameToHash = Collections.unmodifiableMap(nameToHash);
+     }
+ 
+@@ -95,54 +99,125 @@
+     }
+ 
+     /**
+-     * Computes the hash for the given file with the given message digest
+-     * algorithm.
++     * Computes a hash from the names and content of a module.
+      *
++     * @param reader the module reader to access the module content
++     * @param algorithm the name of the message digest algorithm to use
++     * @return the hash
++     * @throws IllegalArgumentException if digest algorithm is not supported
+      * @throws UncheckedIOException if an I/O error occurs
+      * @throws RuntimeException if the algorithm is not available
+      */
+-    public static byte[] computeHash(Path file, String algorithm) {
++    private static byte[] computeHash(ModuleReader reader, String algorithm) {
++        MessageDigest md;
+         try {
+-            MessageDigest md = MessageDigest.getInstance(algorithm);
+-
+-            // Ideally we would just mmap the file but this consumes too much
+-            // memory when jlink is running concurrently on very large jmods
+-            try (FileChannel fc = FileChannel.open(file)) {
+-                ByteBuffer bb = ByteBuffer.allocate(32*1024);
+-                while (fc.read(bb) > 0) {
+-                    bb.flip();
+-                    md.update(bb);
+-                    assert bb.remaining() == 0;
+-                    bb.clear();
+-                }
+-            }
+-
+-            return md.digest();
++            md = MessageDigest.getInstance(algorithm);
+         } catch (NoSuchAlgorithmException e) {
+-            throw new RuntimeException(e);
++            throw new IllegalArgumentException(e);
++        }
++        try {
++            byte[] buf = new byte[32*1024];
++            reader.list().sorted().forEach(rn -> {
++                md.update(rn.getBytes(StandardCharsets.UTF_8));
++                try (InputStream in = reader.open(rn).orElseThrow(java.util.NoSuchElementException::new)) {
++                    int n;
++                    while ((n = in.read(buf)) > 0) {
++                        md.update(buf, 0, n);
++                    }
++                } catch (IOException ioe) {
++                    throw new UncheckedIOException(ioe);
++                }
++            });
+         } catch (IOException ioe) {
+             throw new UncheckedIOException(ioe);
+         }
++        return md.digest();
+     }
+ 
+     /**
+-     * Computes the hash for every entry in the given map, returning a
+-     * {@code ModuleHashes} to encapsulate the result. The map key is
+-     * the entry name, typically the module name. The map value is the file
+-     * path to the entry (module artifact).
++     * Computes a hash from the names and content of a module.
+      *
++     * @param supplier supplies the module reader to access the module content
++     * @param algorithm the name of the message digest algorithm to use
++     * @return the hash
++     * @throws IllegalArgumentException if digest algorithm is not supported
++     * @throws UncheckedIOException if an I/O error occurs
++     */
++    static byte[] computeHash(Supplier<ModuleReader> supplier, String algorithm) {
++        try (ModuleReader reader = supplier.get()) {
++            return computeHash(reader, algorithm);
++        } catch (IOException ioe) {
++            throw new UncheckedIOException(ioe);
++        }
++    }
++
++    /**
++     * Computes the hash from the names and content of a set of modules. Returns
++     * a {@code ModuleHashes} to encapsulate the result.
++     * @param mrefs the set of modules
++     * @param algorithm the name of the message digest algorithm to use
+      * @return ModuleHashes that encapsulates the hashes
++     * @throws IllegalArgumentException if digest algorithm is not supported
++     * @throws UncheckedIOException if an I/O error occurs
+      */
+-    public static ModuleHashes generate(Map<String, Path> map, String algorithm) {
++    static ModuleHashes generate(Set<ModuleReference> mrefs, String algorithm) {
+         Map<String, byte[]> nameToHash = new HashMap<>();
+-        for (Map.Entry<String, Path> entry: map.entrySet()) {
+-            String name = entry.getKey();
+-            Path path = entry.getValue();
+-            nameToHash.put(name, computeHash(path, algorithm));
++        for (ModuleReference mref : mrefs) {
++            try (ModuleReader reader = mref.open()) {
++                byte[] hash = computeHash(reader, algorithm);
++                nameToHash.put(mref.descriptor().name(), hash);
++            } catch (IOException ioe) {
++                throw new UncheckedIOException(ioe);
++            }
+         }
+         return new ModuleHashes(algorithm, nameToHash);
+     }
+ 
++    @Override
++    public int hashCode() {
++        int h = algorithm.hashCode();
++        for (Map.Entry<String, byte[]> e : nameToHash.entrySet()) {
++            h = h * 31 + e.getKey().hashCode();
++            h = h * 31 + Arrays.hashCode(e.getValue());
++        }
++        return h;
++    }
++
++    @Override
++    public boolean equals(Object obj) {
++        if (!(obj instanceof ModuleHashes))
++            return false;
++        ModuleHashes other = (ModuleHashes) obj;
++        if (!algorithm.equals(other.algorithm)
++                || nameToHash.size() != other.nameToHash.size())
++            return false;
++        for (Map.Entry<String, byte[]> e : nameToHash.entrySet()) {
++            String name = e.getKey();
++            byte[] hash = e.getValue();
++            if (!Arrays.equals(hash, other.nameToHash.get(name)))
++                return false;
++        }
++        return true;
++    }
++
++    @Override
++    public String toString() {
++        StringBuilder sb = new StringBuilder(algorithm);
++        sb.append(" ");
++        nameToHash.entrySet()
++                .stream()
++                .sorted(Map.Entry.comparingByKey())
++                .forEach(e -> {
++                    sb.append(e.getKey());
++                    sb.append("=");
++                    byte[] ba = e.getValue();
++                    for (byte b : ba) {
++                        sb.append(String.format("%02x", b & 0xff));
++                    }
++                });
++        return sb.toString();
++    }
++
+     /**
+      * This is used by jdk.internal.module.SystemModules class
+      * generated at link time.
+diff -ru orig/jdk-3cc80be736f2/src/java.base/share/classes/jdk/internal/module/ModuleInfoExtender.java jdk-3cc80be736f2/src/java.base/share/classes/jdk/internal/module/ModuleInfoExtender.java
+--- orig/jdk-3cc80be736f2/src/java.base/share/classes/jdk/internal/module/ModuleInfoExtender.java	1970-01-01 01:00:01.000000000 +0100
++++ jdk-3cc80be736f2/src/java.base/share/classes/jdk/internal/module/ModuleInfoExtender.java	2022-04-12 16:43:12.967868689 +0200
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
++ * Copyright (c) 2014, 2020, Oracle and/or its affiliates. All rights reserved.
+  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+  *
+  * This code is free software; you can redistribute it and/or modify it
+diff -ru orig/jdk-3cc80be736f2/src/java.base/share/classes/jdk/internal/module/ModuleReferences.java jdk-3cc80be736f2/src/java.base/share/classes/jdk/internal/module/ModuleReferences.java
+--- orig/jdk-3cc80be736f2/src/java.base/share/classes/jdk/internal/module/ModuleReferences.java	1970-01-01 01:00:01.000000000 +0100
++++ jdk-3cc80be736f2/src/java.base/share/classes/jdk/internal/module/ModuleReferences.java	2022-04-12 16:43:12.971868797 +0200
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
++ * Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved.
+  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+  *
+  * This code is free software; you can redistribute it and/or modify it
+@@ -95,7 +95,7 @@
+                                         Path file) {
+         URI uri = file.toUri();
+         Supplier<ModuleReader> supplier = () -> new JarModuleReader(file, uri);
+-        HashSupplier hasher = (a) -> ModuleHashes.computeHash(file, a);
++        HashSupplier hasher = (a) -> ModuleHashes.computeHash(supplier, a);
+         return newModule(attrs, uri, supplier, patcher, hasher);
+     }
+ 
+@@ -105,7 +105,7 @@
+     static ModuleReference newJModModule(ModuleInfo.Attributes attrs, Path file) {
+         URI uri = file.toUri();
+         Supplier<ModuleReader> supplier = () -> new JModModuleReader(file, uri);
+-        HashSupplier hasher = (a) -> ModuleHashes.computeHash(file, a);
++        HashSupplier hasher = (a) -> ModuleHashes.computeHash(supplier, a);
+         return newModule(attrs, uri, supplier, null, hasher);
+     }
+ 
diff --git a/gnu/packages/patches/openjdk-10-module3-reproducibility.patch b/gnu/packages/patches/openjdk-10-module3-reproducibility.patch
new file mode 100644
index 0000000000..bc54803bea
--- /dev/null
+++ b/gnu/packages/patches/openjdk-10-module3-reproducibility.patch
@@ -0,0 +1,34 @@
+Danny wrote.
+
+--- orig/jdk-3cc80be736f2/src/java.base/share/classes/java/lang/module/ModuleDescriptor.java	1970-01-01 01:00:01.000000000 +0100
++++ jdk-3cc80be736f2/src/java.base/share/classes/java/lang/module/ModuleDescriptor.java	2022-04-13 17:30:37.242775977 +0200
+@@ -43,6 +43,7 @@
+ import java.util.Objects;
+ import java.util.Optional;
+ import java.util.Set;
++import java.util.TreeSet;
+ import java.util.function.Supplier;
+ import java.util.stream.Collectors;
+ import java.util.stream.Stream;
+@@ -2155,9 +2156,9 @@
+          * @return The module descriptor
+          */
+         public ModuleDescriptor build() {
+-            Set<Requires> requires = new HashSet<>(this.requires.values());
+-            Set<Exports> exports = new HashSet<>(this.exports.values());
+-            Set<Opens> opens = new HashSet<>(this.opens.values());
++            Set<Requires> requires = new TreeSet<>(this.requires.values());
++            Set<Exports> exports = new TreeSet<>(this.exports.values());
++            Set<Opens> opens = new TreeSet<>(this.opens.values());
+ 
+             // add dependency on java.base
+             if (strict
+@@ -2169,7 +2170,7 @@
+                                           null));
+             }
+ 
+-            Set<Provides> provides = new HashSet<>(this.provides.values());
++            Set<Provides> provides = new TreeSet<>(this.provides.values());
+ 
+             return new ModuleDescriptor(name,
+                                         version,
diff --git a/gnu/packages/patches/openjdk-10-module4-reproducibility.patch b/gnu/packages/patches/openjdk-10-module4-reproducibility.patch
new file mode 100644
index 0000000000..051c9344eb
--- /dev/null
+++ b/gnu/packages/patches/openjdk-10-module4-reproducibility.patch
@@ -0,0 +1,14 @@
+Danny wrote it
+
+--- orig/jdk-6fa770f9f8ab/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/SystemModulesPlugin.java	2022-04-13 19:24:12.655749459 +0200
++++ jdk-6fa770f9f8ab/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/SystemModulesPlugin.java	2022-04-14 01:53:23.555465018 +0200
+@@ -861,7 +861,8 @@
+          */
+         private void genModuleReads(ClassWriter cw, Configuration cf) {
+             // module name -> names of modules that it reads
+-            Map<String, Set<String>> map = cf.modules().stream()
++            Map<String, Set<String>> map = cf.modules().stream()
++                    .sorted(java.util.Comparator.comparing(ResolvedModule::name))
+                     .collect(Collectors.toMap(
+                             ResolvedModule::name,
+                             m -> m.reads().stream()
-- 
2.36.1





Information forwarded to guix-patches <at> gnu.org:
bug#55751; Package guix-patches. (Wed, 01 Jun 2022 13:13:02 GMT) Full text and rfc822 format available.

Message #32 received at 55751 <at> debbugs.gnu.org (full text, mbox):

From: Maxime Devos <maximedevos <at> telenet.be>
To: dannym <at> scratchpost.org, 55751 <at> debbugs.gnu.org
Subject: Re: [bug#55751] [PATCH 1/8] gnu: openjdk9: Make build reproducible.
Date: Wed, 01 Jun 2022 15:12:41 +0200
[Message part 1 (text/plain, inline)]
dannym <at> scratchpost.org schreef op wo 01-06-2022 om 15:00 [+0200]:
>         #:imported-modules
>         ((guix build syscalls)
> +        (srfi srfi-35)
>          ,@%gnu-build-system-modules)


#:imported-modules is not for importing modules as in use-modules, but
for copying modules.  By adding (srfi srfi-35), you copy (srfi srfi-35)
from the Guile against which Guix is compiled.  Use #:modules instead.

Greetings,
Maxime;


[signature.asc (application/pgp-signature, inline)]

Information forwarded to guix-patches <at> gnu.org:
bug#55751; Package guix-patches. (Wed, 01 Jun 2022 13:15:01 GMT) Full text and rfc822 format available.

Message #35 received at 55751 <at> debbugs.gnu.org (full text, mbox):

From: Maxime Devos <maximedevos <at> telenet.be>
To: dannym <at> scratchpost.org, 55751 <at> debbugs.gnu.org
Subject: Re: [bug#55751] [PATCH 1/8] gnu: openjdk9: Make build reproducible.
Date: Wed, 01 Jun 2022 15:14:28 +0200
[Message part 1 (text/plain, inline)]
dannym <at> scratchpost.org schreef op wo 01-06-2022 om 15:00 [+0200]:
> +++ b/gnu/packages/patches/openjdk-9-module-reproducibility.patch
> @@ -0,0 +1,296 @@
> +From a52c4ef44c0553a399a8a47e528db92e3bf51c6c Mon Sep 17 00:00:00 2001
> +From: Alan Bateman <alanb <at> openjdk.org>
> +Date: Wed, 29 Apr 2020 08:38:28 +0100
> +Subject: [PATCH] 8243666: ModuleHashes attribute generated for JMOD and JAR
> + files depends on timestamps
> +
> +Reviewed-by: mchung

IIUC, "guix lint" will want you tu put a link to upstream.

Greetings,
Maxime.
[signature.asc (application/pgp-signature, inline)]

Information forwarded to guix-patches <at> gnu.org:
bug#55751; Package guix-patches. (Wed, 01 Jun 2022 13:19:01 GMT) Full text and rfc822 format available.

Message #38 received at 55751 <at> debbugs.gnu.org (full text, mbox):

From: Maxime Devos <maximedevos <at> telenet.be>
To: dannym <at> scratchpost.org, 55751 <at> debbugs.gnu.org
Subject: Re: [bug#55751] [PATCH 1/8] gnu: openjdk9: Make build reproducible.
Date: Wed, 01 Jun 2022 15:18:24 +0200
[Message part 1 (text/plain, inline)]
dannym <at> scratchpost.org schreef op wo 01-06-2022 om 15:00 [+0200]:
> +                             (let ((code (system* "unzip" "--" zip)))
> +                               (write code)
> +                               (newline)
> +                               (when (> (status:exit-val code) 1) ; 1 is just a warning

What's the warning?  Maybe the warning can be addressed or we could ask
unzip to not do warnings and then this could simplified to (invoke
"unzip" ...).

> +                                 (raise (condition (&invoke-error
> +                                                    (program "unzip")
> +                                                    (arguments (list "--" zip))
> +                                                    (exit-status (status:exit-val code))
> +                                                    (term-signal (status:term-sig code))
> +                                                    (stop-signal (status:stop-sig code))))))))

This block could use a block explaining what it's for.
Likewise for the other undocumented block of code.
[signature.asc (application/pgp-signature, inline)]

Information forwarded to guix-patches <at> gnu.org:
bug#55751; Package guix-patches. (Wed, 01 Jun 2022 13:21:02 GMT) Full text and rfc822 format available.

Message #41 received at 55751 <at> debbugs.gnu.org (full text, mbox):

From: Maxime Devos <maximedevos <at> telenet.be>
To: dannym <at> scratchpost.org, 55751 <at> debbugs.gnu.org
Subject: Re: [bug#55751] [PATCH 0/8] Towards reproducible openjdk
Date: Wed, 01 Jun 2022 15:20:31 +0200
dannym <at> scratchpost.org schreef op wo 01-06-2022 om 14:57 [+0200]:
> From: Danny Milosavljevic <dannym <at> scratchpost.org>
> 
> This patchseries improves the reproducibility of openjdk.
> 
> After it:
> * openjdk9 is reproducible.
> * openjdk10 has only a few non-reproducible parts.
> * openjdk11 has a number of non-reproducible parts.
> * openjdk12's "doc" output is still not reproducible ("Generated by javadoc" comment with timestamp in it)
> * openjdk13 still has non-reproducible parts (jmod, modules, classes.jsa, src.zip)
> * openjdk14 still has very few non-reproducible parts (jmod, modules, classes.jsa)
> * openjdk15 still has a number of non-reproducible parts (diz files only).
> * openjdk16 still has one non-reproducible part (classes*.jsa)

Now we are rebuilding everything Java anyway, could this be followed by
a patch removing the input labels and removing trailing #t?

Greetings,
Maxime.





Information forwarded to guix-patches <at> gnu.org:
bug#55751; Package guix-patches. (Wed, 21 Sep 2022 20:19:01 GMT) Full text and rfc822 format available.

Message #44 received at 55751 <at> debbugs.gnu.org (full text, mbox):

From: Danny Milosavljevic <dannym <at> scratchpost.org>
To: Maxime Devos <maximedevos <at> telenet.be>
Cc: 55751 <at> debbugs.gnu.org
Subject: Re: [bug#55751] [PATCH 1/8] gnu: openjdk9: Make build reproducible.
Date: Wed, 21 Sep 2022 22:18:10 +0200
[Message part 1 (text/plain, inline)]
Hi,

On Wed, 01 Jun 2022 15:18:24 +0200
Maxime Devos <maximedevos <at> telenet.be> wrote:

> dannym <at> scratchpost.org schreef op wo 01-06-2022 om 15:00 [+0200]:
> > +                             (let ((code (system* "unzip" "--" zip)))
> > +                               (write code)
> > +                               (newline)
> > +                               (when (> (status:exit-val code) 1) ; 1 is just a warning  
> 
> What's the warning?  Maybe the warning can be addressed or we could ask
> unzip to not do warnings and then this could simplified to (invoke
> "unzip" ...).

In jmod files, there's a weird header in front and the warning is that it's
skipping that header.

> 
> > +                                 (raise (condition (&invoke-error
> > +                                                    (program "unzip")
> > +                                                    (arguments (list "--" zip))
> > +                                                    (exit-status (status:exit-val code))
> > +                                                    (term-signal (status:term-sig code))
> > +                                                    (stop-signal (status:stop-sig code))))))))  
> 
> This block could use a block explaining what it's for.
> Likewise for the other undocumented block of code.

Sure. I'll add a comment.

It's basically just like "invoke" with a change in the exit-val check
(1 instead of 0).
[Message part 2 (application/pgp-signature, inline)]

Information forwarded to guix-patches <at> gnu.org:
bug#55751; Package guix-patches. (Mon, 31 Jul 2023 18:10:02 GMT) Full text and rfc822 format available.

Message #47 received at 55751 <at> debbugs.gnu.org (full text, mbox):

From: Danny Milosavljevic <dannym <at> scratchpost.org>
To: 55751 <at> debbugs.gnu.org
Cc: Danny Milosavljevic <dannym <at> scratchpost.org>
Subject: [PATCH v2 0/7] Towards reproducible openjdk
Date: Mon, 31 Jul 2023 20:09:12 +0200
This patchseries improves the reproducibility of openjdk.

After it:
* openjdk9 is reproducible.
* openjdk10 has only a few non-reproducible parts.
* openjdk11 has a number of non-reproducible parts.
* openjdk12's "doc" output is still not reproducible ("Generated by javadoc" comment with timestamp in it)
* openjdk13 still has non-reproducible parts (jmod, modules, classes.jsa, src.zip)
* openjdk14 still has very few non-reproducible parts (jmod, modules, classes.jsa)
* openjdk15 still has a number of non-reproducible parts (diz files only).
* openjdk16 still has one non-reproducible part (classes*.jsa)

Danny Milosavljevic (7):
  gnu: openjdk9: Make build reproducible.
  gnu: openjdk10: Make more reproducible.
  gnu: openjdk11: Make more reproducible.
  gnu: openjdk12: Make reproducible.
  gnu: openjdk13: Make reproducible.
  gnu: openjdk14: Make reproducible.
  gnu: openjdk15: Make reproducible.

 gnu/local.mk                                  |  16 +
 gnu/packages/java.scm                         | 151 +++++++--
 .../openjdk-10-char-reproducibility.patch     |  12 +
 ...openjdk-10-classlist-reproducibility.patch |  27 ++
 .../openjdk-10-corba-reproducibility.patch    |  12 +
 .../openjdk-10-jar-reproducibility.patch      | 103 ++++++
 .../openjdk-10-jtask-reproducibility.patch    |  53 +++
 .../openjdk-10-module-reproducibility.patch   | 305 ++++++++++++++++++
 .../openjdk-10-module3-reproducibility.patch  |  34 ++
 .../openjdk-10-module4-reproducibility.patch  |  14 +
 ...openjdk-11-classlist-reproducibility.patch |  11 +
 ...openjdk-13-classlist-reproducibility.patch |  11 +
 .../openjdk-15-jtask-reproducibility.patch    |  40 +++
 .../openjdk-9-classlist-reproducibility.patch |  31 ++
 .../openjdk-9-idlj-reproducibility.patch      |  37 +++
 .../openjdk-9-jar-reproducibility.patch       | 107 ++++++
 .../openjdk-9-module-reproducibility.patch    | 297 +++++++++++++++++
 .../openjdk-9-module2-reproducibility.patch   | 125 +++++++
 .../openjdk-9-module3-reproducibility.patch   |  36 +++
 19 files changed, 1392 insertions(+), 30 deletions(-)
 create mode 100644 gnu/packages/patches/openjdk-10-char-reproducibility.patch
 create mode 100644 gnu/packages/patches/openjdk-10-classlist-reproducibility.patch
 create mode 100644 gnu/packages/patches/openjdk-10-corba-reproducibility.patch
 create mode 100644 gnu/packages/patches/openjdk-10-jar-reproducibility.patch
 create mode 100644 gnu/packages/patches/openjdk-10-jtask-reproducibility.patch
 create mode 100644 gnu/packages/patches/openjdk-10-module-reproducibility.patch
 create mode 100644 gnu/packages/patches/openjdk-10-module3-reproducibility.patch
 create mode 100644 gnu/packages/patches/openjdk-10-module4-reproducibility.patch
 create mode 100644 gnu/packages/patches/openjdk-11-classlist-reproducibility.patch
 create mode 100644 gnu/packages/patches/openjdk-13-classlist-reproducibility.patch
 create mode 100644 gnu/packages/patches/openjdk-15-jtask-reproducibility.patch
 create mode 100644 gnu/packages/patches/openjdk-9-classlist-reproducibility.patch
 create mode 100644 gnu/packages/patches/openjdk-9-idlj-reproducibility.patch
 create mode 100644 gnu/packages/patches/openjdk-9-jar-reproducibility.patch
 create mode 100644 gnu/packages/patches/openjdk-9-module-reproducibility.patch
 create mode 100644 gnu/packages/patches/openjdk-9-module2-reproducibility.patch
 create mode 100644 gnu/packages/patches/openjdk-9-module3-reproducibility.patch

-- 
2.39.2





Information forwarded to guix-patches <at> gnu.org:
bug#55751; Package guix-patches. (Mon, 31 Jul 2023 18:10:03 GMT) Full text and rfc822 format available.

Message #50 received at 55751 <at> debbugs.gnu.org (full text, mbox):

From: Danny Milosavljevic <dannym <at> scratchpost.org>
To: 55751 <at> debbugs.gnu.org
Cc: Danny Milosavljevic <dannym <at> scratchpost.org>
Subject: [PATCH v2 1/7] gnu: openjdk9: Make build reproducible.
Date: Mon, 31 Jul 2023 20:09:13 +0200
* gnu/packages/patches/openjdk-9-classlist-reproducibility.patch: New file.
* gnu/packages/patches/openjdk-9-jar-reproducibility.patch: New file.
* gnu/packages/patches/openjdk-9-module-reproducibility.patch: New file.
* gnu/packages/patches/openjdk-9-module2-reproducibility.patch: New file.
* gnu/packages/patches/openjdk-9-module3-reproducibility.patch: New file.
* gnu/packages/patches/openjdk-9-idlj-reproducibility.patch: New file.
* gnu/packages/java.scm (openjdk9)[source]: Add patches.
[arguments]<#:phases>[strip-zip-timestamps]: Modify.
[inputs]: Use new-style syntax.
* gnu/local/mk (dist_patch_DATA): Add patches.
---
 gnu/local.mk                                  |   6 +
 gnu/packages/java.scm                         |  88 ++++--
 .../openjdk-9-classlist-reproducibility.patch |  31 ++
 .../openjdk-9-idlj-reproducibility.patch      |  37 +++
 .../openjdk-9-jar-reproducibility.patch       | 107 +++++++
 .../openjdk-9-module-reproducibility.patch    | 297 ++++++++++++++++++
 .../openjdk-9-module2-reproducibility.patch   | 125 ++++++++
 .../openjdk-9-module3-reproducibility.patch   |  36 +++
 8 files changed, 703 insertions(+), 24 deletions(-)
 create mode 100644 gnu/packages/patches/openjdk-9-classlist-reproducibility.patch
 create mode 100644 gnu/packages/patches/openjdk-9-idlj-reproducibility.patch
 create mode 100644 gnu/packages/patches/openjdk-9-jar-reproducibility.patch
 create mode 100644 gnu/packages/patches/openjdk-9-module-reproducibility.patch
 create mode 100644 gnu/packages/patches/openjdk-9-module2-reproducibility.patch
 create mode 100644 gnu/packages/patches/openjdk-9-module3-reproducibility.patch

diff --git a/gnu/local.mk b/gnu/local.mk
index 00fe7a036c..155b9e7740 100644
--- a/gnu/local.mk
+++ b/gnu/local.mk
@@ -1658,6 +1658,12 @@ dist_patch_DATA =						\
   %D%/packages/patches/openfoam-4.1-cleanup.patch			\
   %D%/packages/patches/openjdk-9-pointer-comparison.patch       \
   %D%/packages/patches/openjdk-9-setsignalhandler.patch         \
+  %D%/packages/patches/openjdk-9-classlist-reproducibility.patch	\
+  %D%/packages/patches/openjdk-9-idlj-reproducibility.patch	\
+  %D%/packages/patches/openjdk-9-jar-reproducibility.patch	\
+  %D%/packages/patches/openjdk-9-module-reproducibility.patch	\
+  %D%/packages/patches/openjdk-9-module2-reproducibility.patch	\
+  %D%/packages/patches/openjdk-9-module3-reproducibility.patch	\
   %D%/packages/patches/openjdk-10-idlj-reproducibility.patch	\
   %D%/packages/patches/openjdk-10-pointer-comparison.patch      \
   %D%/packages/patches/openjdk-10-setsignalhandler.patch        \
diff --git a/gnu/packages/java.scm b/gnu/packages/java.scm
index 5a6288581e..ad2af44229 100644
--- a/gnu/packages/java.scm
+++ b/gnu/packages/java.scm
@@ -865,7 +865,9 @@ (define-public openjdk9
               (uri (hg-reference (url "https://hg.openjdk.org/jdk/jdk")
                                  (changeset "jdk-9+181")))
               (file-name (hg-file-name name version))
-              (modules '((guix build utils)))
+              (modules '((guix build utils)
+                         (srfi srfi-35)
+                         (ice-9 binary-ports)))
               (snippet `(begin
                           (for-each delete-file
                                     (find-files "." ".*.(bin|exe|jar)$"))))
@@ -873,6 +875,12 @@ (define-public openjdk9
                (base32
                 "1v92nzdqx07c35x945awzir4yk0fk22vky6fpp8mq9js930sxsz0"))
               (patches (search-patches "openjdk-9-pointer-comparison.patch"
+                                       "openjdk-9-classlist-reproducibility.patch"
+                                       "openjdk-9-jar-reproducibility.patch"
+                                       "openjdk-9-module-reproducibility.patch"
+                                       "openjdk-9-module2-reproducibility.patch"
+                                       "openjdk-9-module3-reproducibility.patch"
+                                       "openjdk-9-idlj-reproducibility.patch"
                                        "openjdk-9-setsignalhandler.patch"))))
     (build-system gnu-build-system)
     (outputs '("out" "jdk" "doc"))
@@ -995,37 +1003,69 @@ (define (icedtea-or-openjdk? path)
              (for-each (lambda (zip)
                          (let ((dir (mkdtemp "zip-contents.XXXXXX")))
                            (with-directory-excursion dir
-                             (invoke "unzip" zip))
+                             ;; This is an exact copy of the implementation
+                             ;; of invoke, but this accepts exit code 1
+                             ;; as OK.
+                             (let ((code (system* "unzip" "--" zip)))
+                               ;; jmod files are zip files with an extra header in front.
+                               ;; unzip will warn about that--but otherwise work.
+                               (when (> (status:exit-val code) 1) ; 1 is just a warning
+                                 (raise
+                                  (condition
+                                   (&invoke-error
+                                    (program "unzip")
+                                    (arguments (list "--" zip))
+                                    (exit-status (status:exit-val code))
+                                    (term-signal (status:term-sig code))
+                                    (stop-signal (status:stop-sig code))))))))
                            (delete-file zip)
                            (for-each (lambda (file)
                                        (let ((s (lstat file)))
-                                         (unless (eq? (stat:type s) 'symlink)
                                            (format #t "reset ~a~%" file)
-                                           (utime file 0 0 0 0))))
+                                           (utime file 1 1 0 0
+                                                       AT_SYMLINK_NOFOLLOW)))
                                      (find-files dir #:directories? #t))
                            (with-directory-excursion dir
-                             (let ((files (find-files "." ".*" #:directories? #t)))
-                               (apply invoke "zip" "-0" "-X" zip files)))))
-                       (find-files (assoc-ref outputs "doc") ".*.zip$"))
+                             (let ((files (cons "./META-INF/MANIFEST.MF"
+                                                (append
+                                                 (find-files "./META-INF" ".*")
+                                                 ;; for jmod:
+                                                 (list "./classes/module-info.class")
+                                                 (find-files "." ".*")))))
+                               (apply invoke "zip" "--symlinks" "-0" "-X" zip files)
+                               (when (string-suffix? ".jmod" zip)
+                                 (let ((new-zip (string-append zip "n"))
+                                       (contents (call-with-input-file zip
+                                                   (@ (ice-9 binary-ports)
+                                                      get-bytevector-all))))
+                                   (call-with-output-file new-zip
+                                     (lambda (output-port)
+                                       ((@ (ice-9 binary-ports) put-bytevector)
+                                        output-port
+                                        #vu8(#x4a #x4d #x01 #x00)) ; JM
+                                       ((@ (ice-9 binary-ports) put-bytevector)
+                                        output-port
+                                        contents)))
+                                   (rename-file new-zip zip)))))))
+                       (append (find-files (string-append
+                                            (assoc-ref outputs "doc")
+                                            "/api")
+                                           "\\.zip$")
+                               (find-files (assoc-ref outputs "doc") "src\\.zip$")
+                               (find-files (assoc-ref outputs "jdk") "src\\.zip$")
+                               (find-files (assoc-ref outputs "jdk") "\\.jmod$")
+                               (find-files (assoc-ref outputs "jdk") "\\.diz$")
+                               (find-files (assoc-ref outputs "out") "\\.diz$")
+
+                               (list (string-append (assoc-ref outputs "jdk") "/lib/jrt-fs.jar"))
+                               (find-files (string-append (assoc-ref outputs "jdk")
+                                                          "/demo")
+                                           "\\.jar$")))
              #t)))))
     (inputs
-     `(("alsa-lib" ,alsa-lib)
-       ("cups" ,cups)
-       ("fontconfig" ,fontconfig)
-       ("freetype" ,freetype)
-       ("giflib" ,giflib)
-       ("lcms" ,lcms)
-       ("libelf" ,libelf)
-       ("libjpeg" ,libjpeg-turbo)
-       ("libice" ,libice)
-       ("libpng" ,libpng)
-       ("libx11" ,libx11)
-       ("libxcomposite" ,libxcomposite)
-       ("libxi" ,libxi)
-       ("libxinerama" ,libxinerama)
-       ("libxrender" ,libxrender)
-       ("libxt" ,libxt)
-       ("libxtst" ,libxtst)))
+     (list alsa-lib cups fontconfig freetype giflib lcms libelf libjpeg-turbo
+           libice libpng libx11 libxcomposite libxi libxinerama libxrender
+           libxt libxtst))
     (native-inputs
      `(("icedtea-8" ,icedtea-8)
        ("icedtea-8:jdk" ,icedtea-8 "jdk")
diff --git a/gnu/packages/patches/openjdk-9-classlist-reproducibility.patch b/gnu/packages/patches/openjdk-9-classlist-reproducibility.patch
new file mode 100644
index 0000000000..d0ce7bc4d6
--- /dev/null
+++ b/gnu/packages/patches/openjdk-9-classlist-reproducibility.patch
@@ -0,0 +1,31 @@
+From: Danny Milosavljevic <dannym <at> scratchpost.org>
+Date: Wed, 18 Apr 2022 18:38:28 +0100
+Subject: Make classlist reproducible
+
+--- jdk-09/make/GenerateLinkOptData.gmk.orig	2022-04-05 10:05:35.892134188 +0200
++++ jdk-09/make/GenerateLinkOptData.gmk	2022-04-05 10:06:07.885003056 +0200
+@@ -61,11 +61,12 @@
+ 	$(call MakeDir, $(LINK_OPT_DIR))
+ 	$(call LogInfo, Generating $(patsubst $(OUTPUT_ROOT)/%, %, $@))
+ 	$(call LogInfo, Generating $(patsubst $(OUTPUT_ROOT)/%, %, $(JLI_TRACE_FILE)))
+-	$(FIXPATH) $(INTERIM_IMAGE_DIR)/bin/java -XX:DumpLoadedClassList=$@ \
++	$(FIXPATH) $(INTERIM_IMAGE_DIR)/bin/java -XX:DumpLoadedClassList=$@.tmp \
+ 	    -Djava.lang.invoke.MethodHandle.TRACE_RESOLVE=true \
+ 	    -cp $(SUPPORT_OUTPUTDIR)/classlist.jar \
+ 	    build.tools.classlist.HelloClasslist \
+ 	    $(LOG_DEBUG) 2>&1 > $(JLI_TRACE_FILE)
++	sort $@.tmp >$@
+ 
+ # The jli trace is created by the same recipe as classlist. By declaring these
+ # dependencies, make will correctly rebuild both jli trace and classlist
+--- jdk-09/langtools/make/gendata/Gendata-jdk.compiler.gmk.orig	2022-04-08 22:04:05.784424812 +0200
++++ jdk-09/langtools/make/gendata/Gendata-jdk.compiler.gmk	2022-04-08 22:09:36.333575143 +0200
+@@ -79,6 +79,8 @@
+ 	    $(CT_MODULESOURCEPATH) \
+ 	    $(CT_MODULES) \
+ 	    >$(@D)/9/system-modules
++	# Make files reproducible
++	find $(@D) -exec $(TOUCH) -h -c -t 197001010000.01 {} \;
+ 	$(TOUCH) $@
+ 
+ # Can't generate ct.sym directly into modules libs as the SetupJarArchive macro
diff --git a/gnu/packages/patches/openjdk-9-idlj-reproducibility.patch b/gnu/packages/patches/openjdk-9-idlj-reproducibility.patch
new file mode 100644
index 0000000000..30dcdf2496
--- /dev/null
+++ b/gnu/packages/patches/openjdk-9-idlj-reproducibility.patch
@@ -0,0 +1,37 @@
+From: Danny Milosavljevic <dannym <at> scratchpost.org>
+Date: Wed, 18 Apr 2022 19:28:00 +0100
+Subject: Make IDL reproducible
+
+--- jdk-09/corba/src/java.corba/share/classes/com/sun/tools/corba/se/idl/toJavaPortable/Util.java.orig	2022-04-05 02:46:26.805340292 +0200
++++ jdk-09/corba/src/java.corba/share/classes/com/sun/tools/corba/se/idl/toJavaPortable/Util.java	2022-04-05 02:48:23.152494213 +0200
+@@ -1146,7 +1146,7 @@
+     else
+       formatter.setTimeZone (java.util.TimeZone.getDefault ());
+ 
+-    stream.println ("* " + formatter.format (new Date ()));
++    stream.println ("* " + formatter.format (System.getenv("SOURCE_DATE_EPOCH") == null ? new Date () : new Date(1000 * Long.parseLong(System.getenv("SOURCE_DATE_EPOCH")))));
+ 
+     // <daz>
+     ///////////////
+--- jdk-09/corba/make/src/classes/build/tools/logutil/MC.java.orig	2022-04-05 11:09:43.824720493 +0200
++++ jdk-09/corba/make/src/classes/build/tools/logutil/MC.java	2022-04-05 11:10:46.518435511 +0200
+@@ -154,7 +154,7 @@
+                   groupName);
+     pw.println("//");
+     pw.printMsg("// Generated by MC.java version @, DO NOT EDIT BY HAND!", VERSION);
+-    pw.printMsg("// Generated from input file @ on @", inFile, new Date());
++    pw.printMsg("// Generated from input file @ on @", inFile, System.getenv("SOURCE_DATE_EPOCH") == null ? new Date() : new Date(1000 * Long.parseLong(System.getenv("SOURCE_DATE_EPOCH"))));
+     pw.println();
+   }
+ 
+--- jdk-09/jdk/make/src/classes/build/tools/generatecharacter/GenerateCharacter.java.orig	2022-04-05 11:14:29.228526408 +0200
++++ jdk-09/jdk/make/src/classes/build/tools/generatecharacter/GenerateCharacter.java	2022-04-05 11:15:32.658260748 +0200
+@@ -693,7 +693,7 @@
+         PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(theOutputFileName)));
+         out.println(commentStart +
+             " This file was generated AUTOMATICALLY from a template file " +
+-            new java.util.Date() + commentEnd);
++            (System.getenv("SOURCE_DATE_EPOCH") == null ? new java.util.Date() : new java.util.Date(1000 * Long.parseLong(System.getenv("SOURCE_DATE_EPOCH")))) + commentEnd);
+         int marklen = commandMarker.length();
+         LOOP: while(true) {
+             try {
diff --git a/gnu/packages/patches/openjdk-9-jar-reproducibility.patch b/gnu/packages/patches/openjdk-9-jar-reproducibility.patch
new file mode 100644
index 0000000000..130eacd867
--- /dev/null
+++ b/gnu/packages/patches/openjdk-9-jar-reproducibility.patch
@@ -0,0 +1,107 @@
+From: Danny Milosavljevic <dannym <at> scratchpost.org>
+Date: Wed, 18 Apr 2022 20:10:01 +0100
+Subject: Make JARs reproducible
+
+--- jdk-09/make/common/JarArchive.gmk.orig	2022-04-08 21:56:04.075111687 +0200
++++ jdk-09/make/common/JarArchive.gmk	2022-04-11 00:49:16.809140388 +0200
+@@ -249,12 +249,16 @@
+ 	    $(ECHO) "Main-Class: $$(strip $$($1_JARMAIN))" >> $$($1_MANIFEST_FILE) $$(NEWLINE)) \
+ 	  $$(if $$($1_EXTRA_MANIFEST_ATTR), \
+ 	    $(PRINTF) "$$($1_EXTRA_MANIFEST_ATTR)\n" >> $$($1_MANIFEST_FILE) $$(NEWLINE)) \
+-	  $(ECHO) Creating $$($1_NAME) $$(NEWLINE) \
++	  $(TOUCH) -h -c -t 197001010000.00 $$($1_MANIFEST_FILE) $$(NEWLINE) \
++	  $(ECHO) XCreating $$($1_NAME) $(JAR) $$($1_JAR_CREATE_OPTIONS) $$@ $$($1_MANIFEST_FILE) $$(NEWLINE) \
+ 	  $(JAR) $$($1_JAR_CREATE_OPTIONS) $$@ $$($1_MANIFEST_FILE) $$(NEWLINE) \
+ 	  $$($1_SCAPTURE_CONTENTS) \
+ 	  $$($1_SCAPTURE_METAINF) \
+ 	  $$($1_SUPDATE_CONTENTS) \
+-	  $$($1_JARINDEX) && true \
++	  $$($1_JARINDEX) && true $$(NEWLINE) \
++	  $(ECHO) Kreppel2 $$@ $$(NEWLINE) \
++	  unzip -v $$@ $$(NEWLINE) \
++	  d="`mktemp -d`" && $(CP) -f $$@ "$$$$d/a.jar" && (cd "$$$$d" && unzip a.jar META-INF/MANIFEST.MF && $(TOUCH) -h -c -t 197001010000.00 META-INF &&  $(TOUCH) -h -c -t 197001010000.00 META-INF/MANIFEST.MF && (zip --symlinks -0 -X a.jar META-INF META-INF/MANIFEST.MF; zip --symlinks -0 -X a.jar META-INF META-INF/MANIFEST.MF)) && $(CP) -f "$$$$d/a.jar" $$@ \
+ 	, \
+ 	  $(ECHO) Modifying $$($1_NAME) $$(NEWLINE) \
+ 	  $$($1_CAPTURE_CONTENTS) \
+--- jdk-09/make/JrtfsJar.gmk.orig	2022-04-10 13:48:57.385120008 +0200
++++ jdk-09/make/JrtfsJar.gmk	2022-04-10 13:58:04.688158538 +0200
+@@ -57,13 +57,18 @@
+ # file will not be copied unless META-INF/services would also be added to the INCLUDES.
+ # Adding META-INF/services would include all files in that directory when only the one
+ # is needed, which is why this explicit copy is defined instead.
+-$(eval $(call SetupCopyFiles, COPY_JIMAGE_SERVICE_PROVIDER, \
++$(eval $(call SetupCopyFiles, COPY_JIMAGE_SERVICE_PROVIDER1, \
+     SRC := $(JDK_TOPDIR)/src/java.base/share/classes, \
+     DEST := $(SUPPORT_OUTPUTDIR)/jrtfs_classes, \
+     FILES := META-INF/services/java.nio.file.spi.FileSystemProvider))
+ 
++.PHONY: jrtfsfixtimestamps47
++jrtfsfixtimestamps47: $(COPY_JIMAGE_SERVICE_PROVIDER1)
++	find $(SUPPORT_OUTPUTDIR)/jrtfs_classes -exec $(TOUCH) -h -c -t 197001010000.00 {} \;
++	$(TOUCH) -h -c -t 197001010000.00 $(SUPPORT_OUTPUTDIR)/java-main-manifest.mf
++
+ $(eval $(call SetupJarArchive,BUILD_JRTFS_JAR, \
+-    DEPENDENCIES := $(BUILD_JRTFS) $(COPY_JIMAGE_SERVICE_PROVIDER), \
++    DEPENDENCIES := $(BUILD_JRTFS) jrtfsfixtimestamps47, \
+     SRCS := $(SUPPORT_OUTPUTDIR)/jrtfs_classes, \
+     JAR := $(SUPPORT_OUTPUTDIR)/modules_libs/java.base/jrt-fs.jar, \
+     MANIFEST := $(SUPPORT_OUTPUTDIR)/java-main-manifest.mf, \
+--- jdk-09/jdk/src/jdk.jartool/share/classes/sun/tools/jar/Main.java.orig	2022-04-10 02:05:50.983247794 +0200
++++ jdk-09/jdk/src/jdk.jartool/share/classes/sun/tools/jar/Main.java	2022-04-10 02:13:01.638960337 +0200
+@@ -850,12 +850,18 @@
+                     output(getMsg("out.added.manifest"));
+                 }
+                 ZipEntry e = new ZipEntry(MANIFEST_DIR);
+-                e.setTime(System.currentTimeMillis());
++                if (System.getenv("SOURCE_DATE_EPOCH") != null)
++                    e.setTime(1000 * Long.parseLong(System.getenv("SOURCE_DATE_EPOCH")));
++                else
++                    e.setTime(System.currentTimeMillis());
+                 e.setSize(0);
+                 e.setCrc(0);
+                 zos.putNextEntry(e);
+                 e = new ZipEntry(MANIFEST_NAME);
+-                e.setTime(System.currentTimeMillis());
++                if (System.getenv("SOURCE_DATE_EPOCH") != null)
++                    e.setTime(1000 * Long.parseLong(System.getenv("SOURCE_DATE_EPOCH")));
++                else
++                    e.setTime(System.currentTimeMillis());
+                 if (flag0) {
+                     crc32Manifest(e, manifest);
+                 }
+@@ -1022,7 +1028,10 @@
+         throws IOException
+     {
+         ZipEntry e = new ZipEntry(INDEX_NAME);
+-        e.setTime(System.currentTimeMillis());
++        if (System.getenv("SOURCE_DATE_EPOCH") != null)
++            e.setTime(1000 * Long.parseLong(System.getenv("SOURCE_DATE_EPOCH")));
++        else
++            e.setTime(System.currentTimeMillis());
+         if (flag0) {
+             CRC32OutputStream os = new CRC32OutputStream();
+             index.write(os);
+@@ -1041,7 +1050,10 @@
+             String name = mi.getKey();
+             byte[] bytes = mi.getValue();
+             ZipEntry e = new ZipEntry(name);
+-            e.setTime(System.currentTimeMillis());
++            if (System.getenv("SOURCE_DATE_EPOCH") != null)
++                e.setTime(1000 * Long.parseLong(System.getenv("SOURCE_DATE_EPOCH")));
++            else
++                e.setTime(System.currentTimeMillis());
+             if (flag0) {
+                 crc32ModuleInfo(e, bytes);
+             }
+@@ -1066,7 +1078,10 @@
+             addMultiRelease(m);
+         }
+         ZipEntry e = new ZipEntry(MANIFEST_NAME);
+-        e.setTime(System.currentTimeMillis());
++        if (System.getenv("SOURCE_DATE_EPOCH") != null)
++            e.setTime(1000 * Long.parseLong(System.getenv("SOURCE_DATE_EPOCH")));
++        else
++            e.setTime(System.currentTimeMillis());
+         if (flag0) {
+             crc32Manifest(e, m);
+         }
diff --git a/gnu/packages/patches/openjdk-9-module-reproducibility.patch b/gnu/packages/patches/openjdk-9-module-reproducibility.patch
new file mode 100644
index 0000000000..320bb7806a
--- /dev/null
+++ b/gnu/packages/patches/openjdk-9-module-reproducibility.patch
@@ -0,0 +1,297 @@
+From a52c4ef44c0553a399a8a47e528db92e3bf51c6c Mon Sep 17 00:00:00 2001
+From: Alan Bateman <alanb <at> openjdk.org>
+Date: Wed, 29 Apr 2020 08:38:28 +0100
+Subject: [PATCH] 8243666: ModuleHashes attribute generated for JMOD and JAR
+ files depends on timestamps
+See: https://bugs.openjdk.org/browse/JDK-8243666
+
+Reviewed-by: mchung
+---
+
+diff -ru orig/jdk-3cc80be736f2/jdk/src/java.base/share/classes/jdk/internal/module/ModuleHashesBuilder.java jdk-3cc80be736f2/jdk/src/java.base/share/classes/jdk/internal/module/ModuleHashesBuilder.java
+--- orig/jdk-3cc80be736f2/jdk/src/java.base/share/classes/jdk/internal/module/ModuleHashesBuilder.java	1970-01-01 01:00:01.000000000 +0100
++++ jdk-3cc80be736f2/jdk/src/java.base/share/classes/jdk/internal/module/ModuleHashesBuilder.java	2022-04-12 16:47:15.690423653 +0200
+@@ -27,9 +27,8 @@
+ 
+ import java.io.PrintStream;
+ import java.lang.module.Configuration;
++import java.lang.module.ModuleReference;
+ import java.lang.module.ResolvedModule;
+-import java.net.URI;
+-import java.nio.file.Path;
+ import java.nio.file.Paths;
+ import java.util.ArrayDeque;
+ import java.util.Collections;
+@@ -40,7 +39,6 @@
+ import java.util.Map;
+ import java.util.Set;
+ import java.util.function.Consumer;
+-import java.util.function.Function;
+ import java.util.stream.Stream;
+ import static java.util.stream.Collectors.*;
+ 
+@@ -116,27 +114,17 @@
+                    mods.addAll(ns);
+ 
+                    if (!ns.isEmpty()) {
+-                       Map<String, Path> moduleToPath = ns.stream()
+-                           .collect(toMap(Function.identity(), this::moduleToPath));
+-                       hashes.put(mn, ModuleHashes.generate(moduleToPath, "SHA-256"));
++                       Set<ModuleReference> mrefs = ns.stream()
++                               .map(name -> configuration.findModule(name)
++                                                         .orElseThrow(InternalError::new))
++                               .map(ResolvedModule::reference)
++                               .collect(toSet());
++                       hashes.put(mn, ModuleHashes.generate(mrefs, "SHA-256"));
+                    }
+                });
+         return hashes;
+     }
+ 
+-    private Path moduleToPath(String name) {
+-        ResolvedModule rm = configuration.findModule(name).orElseThrow(
+-            () -> new InternalError("Selected module " + name + " not on module path"));
+-
+-        URI uri = rm.reference().location().get();
+-        Path path = Paths.get(uri);
+-        String fn = path.getFileName().toString();
+-        if (!fn.endsWith(".jar") && !fn.endsWith(".jmod")) {
+-            throw new UnsupportedOperationException(path + " is not a modular JAR or jmod file");
+-        }
+-        return path;
+-    }
+-
+     /*
+      * Utility class
+      */
+diff -ru orig/jdk-3cc80be736f2/jdk/src/java.base/share/classes/jdk/internal/module/ModuleHashes.java jdk-3cc80be736f2/jdk/src/java.base/share/classes/jdk/internal/module/ModuleHashes.java
+--- orig/jdk-3cc80be736f2/jdk/src/java.base/share/classes/jdk/internal/module/ModuleHashes.java	1970-01-01 01:00:01.000000000 +0100
++++ jdk-3cc80be736f2/jdk/src/java.base/share/classes/jdk/internal/module/ModuleHashes.java	2022-04-12 16:58:05.639985936 +0200
+@@ -26,17 +26,21 @@
+ package jdk.internal.module;
+ 
+ import java.io.IOException;
++import java.io.InputStream;
+ import java.io.UncheckedIOException;
+-import java.nio.ByteBuffer;
+-import java.nio.channels.FileChannel;
+-import java.nio.file.Path;
++import java.lang.module.ModuleReader;
++import java.lang.module.ModuleReference;
++import java.nio.charset.StandardCharsets;
+ import java.security.MessageDigest;
+ import java.security.NoSuchAlgorithmException;
++import java.util.Arrays;
+ import java.util.Collections;
+ import java.util.HashMap;
+ import java.util.Map;
+ import java.util.Objects;
+ import java.util.Set;
++import java.util.TreeMap;
++import java.util.function.Supplier;
+ 
+ /**
+  * The result of hashing the contents of a number of module artifacts.
+@@ -60,8 +64,8 @@
+      * @param algorithm   the algorithm used to create the hashes
+      * @param nameToHash  the map of module name to hash value
+      */
+-    public ModuleHashes(String algorithm, Map<String, byte[]> nameToHash) {
+-        this.algorithm = algorithm;
++    ModuleHashes(String algorithm, Map<String, byte[]> nameToHash) {
++        this.algorithm = Objects.requireNonNull(algorithm);
+         this.nameToHash = Collections.unmodifiableMap(nameToHash);
+     }
+ 
+@@ -95,54 +99,125 @@
+     }
+ 
+     /**
+-     * Computes the hash for the given file with the given message digest
+-     * algorithm.
++     * Computes a hash from the names and content of a module.
+      *
++     * @param reader the module reader to access the module content
++     * @param algorithm the name of the message digest algorithm to use
++     * @return the hash
++     * @throws IllegalArgumentException if digest algorithm is not supported
+      * @throws UncheckedIOException if an I/O error occurs
+      * @throws RuntimeException if the algorithm is not available
+      */
+-    public static byte[] computeHash(Path file, String algorithm) {
++    private static byte[] computeHash(ModuleReader reader, String algorithm) {
++        MessageDigest md;
+         try {
+-            MessageDigest md = MessageDigest.getInstance(algorithm);
+-
+-            // Ideally we would just mmap the file but this consumes too much
+-            // memory when jlink is running concurrently on very large jmods
+-            try (FileChannel fc = FileChannel.open(file)) {
+-                ByteBuffer bb = ByteBuffer.allocate(32*1024);
+-                while (fc.read(bb) > 0) {
+-                    bb.flip();
+-                    md.update(bb);
+-                    assert bb.remaining() == 0;
+-                    bb.clear();
+-                }
+-            }
+-
+-            return md.digest();
++            md = MessageDigest.getInstance(algorithm);
+         } catch (NoSuchAlgorithmException e) {
+-            throw new RuntimeException(e);
++            throw new IllegalArgumentException(e);
++        }
++        try {
++            byte[] buf = new byte[32*1024];
++            reader.list().sorted().forEach(rn -> {
++                md.update(rn.getBytes(StandardCharsets.UTF_8));
++                try (InputStream in = reader.open(rn).orElseThrow(java.util.NoSuchElementException::new)) {
++                    int n;
++                    while ((n = in.read(buf)) > 0) {
++                        md.update(buf, 0, n);
++                    }
++                } catch (IOException ioe) {
++                    throw new UncheckedIOException(ioe);
++                }
++            });
+         } catch (IOException ioe) {
+             throw new UncheckedIOException(ioe);
+         }
++        return md.digest();
+     }
+ 
+     /**
+-     * Computes the hash for every entry in the given map, returning a
+-     * {@code ModuleHashes} to encapsulate the result. The map key is
+-     * the entry name, typically the module name. The map value is the file
+-     * path to the entry (module artifact).
++     * Computes a hash from the names and content of a module.
+      *
++     * @param supplier supplies the module reader to access the module content
++     * @param algorithm the name of the message digest algorithm to use
++     * @return the hash
++     * @throws IllegalArgumentException if digest algorithm is not supported
++     * @throws UncheckedIOException if an I/O error occurs
++     */
++    static byte[] computeHash(Supplier<ModuleReader> supplier, String algorithm) {
++        try (ModuleReader reader = supplier.get()) {
++            return computeHash(reader, algorithm);
++        } catch (IOException ioe) {
++            throw new UncheckedIOException(ioe);
++        }
++    }
++
++    /**
++     * Computes the hash from the names and content of a set of modules. Returns
++     * a {@code ModuleHashes} to encapsulate the result.
++     * @param mrefs the set of modules
++     * @param algorithm the name of the message digest algorithm to use
+      * @return ModuleHashes that encapsulates the hashes
++     * @throws IllegalArgumentException if digest algorithm is not supported
++     * @throws UncheckedIOException if an I/O error occurs
+      */
+-    public static ModuleHashes generate(Map<String, Path> map, String algorithm) {
++    static ModuleHashes generate(Set<ModuleReference> mrefs, String algorithm) {
+         Map<String, byte[]> nameToHash = new HashMap<>();
+-        for (Map.Entry<String, Path> entry: map.entrySet()) {
+-            String name = entry.getKey();
+-            Path path = entry.getValue();
+-            nameToHash.put(name, computeHash(path, algorithm));
++        for (ModuleReference mref : mrefs) {
++            try (ModuleReader reader = mref.open()) {
++                byte[] hash = computeHash(reader, algorithm);
++                nameToHash.put(mref.descriptor().name(), hash);
++            } catch (IOException ioe) {
++                throw new UncheckedIOException(ioe);
++            }
+         }
+         return new ModuleHashes(algorithm, nameToHash);
+     }
+ 
++    @Override
++    public int hashCode() {
++        int h = algorithm.hashCode();
++        for (Map.Entry<String, byte[]> e : nameToHash.entrySet()) {
++            h = h * 31 + e.getKey().hashCode();
++            h = h * 31 + Arrays.hashCode(e.getValue());
++        }
++        return h;
++    }
++
++    @Override
++    public boolean equals(Object obj) {
++        if (!(obj instanceof ModuleHashes))
++            return false;
++        ModuleHashes other = (ModuleHashes) obj;
++        if (!algorithm.equals(other.algorithm)
++                || nameToHash.size() != other.nameToHash.size())
++            return false;
++        for (Map.Entry<String, byte[]> e : nameToHash.entrySet()) {
++            String name = e.getKey();
++            byte[] hash = e.getValue();
++            if (!Arrays.equals(hash, other.nameToHash.get(name)))
++                return false;
++        }
++        return true;
++    }
++
++    @Override
++    public String toString() {
++        StringBuilder sb = new StringBuilder(algorithm);
++        sb.append(" ");
++        nameToHash.entrySet()
++                .stream()
++                .sorted(Map.Entry.comparingByKey())
++                .forEach(e -> {
++                    sb.append(e.getKey());
++                    sb.append("=");
++                    byte[] ba = e.getValue();
++                    for (byte b : ba) {
++                        sb.append(String.format("%02x", b & 0xff));
++                    }
++                });
++        return sb.toString();
++    }
++
+     /**
+      * This is used by jdk.internal.module.SystemModules class
+      * generated at link time.
+diff -ru orig/jdk-3cc80be736f2/jdk/src/java.base/share/classes/jdk/internal/module/ModuleInfoExtender.java jdk-3cc80be736f2/jdk/src/java.base/share/classes/jdk/internal/module/ModuleInfoExtender.java
+--- orig/jdk-3cc80be736f2/jdk/src/java.base/share/classes/jdk/internal/module/ModuleInfoExtender.java	1970-01-01 01:00:01.000000000 +0100
++++ jdk-3cc80be736f2/jdk/src/java.base/share/classes/jdk/internal/module/ModuleInfoExtender.java	2022-04-12 16:43:12.967868689 +0200
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
++ * Copyright (c) 2014, 2020, Oracle and/or its affiliates. All rights reserved.
+  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+  *
+  * This code is free software; you can redistribute it and/or modify it
+diff -ru orig/jdk-3cc80be736f2/jdk/src/java.base/share/classes/jdk/internal/module/ModuleReferences.java jdk-3cc80be736f2/jdk/src/java.base/share/classes/jdk/internal/module/ModuleReferences.java
+--- orig/jdk-3cc80be736f2/jdk/src/java.base/share/classes/jdk/internal/module/ModuleReferences.java	1970-01-01 01:00:01.000000000 +0100
++++ jdk-3cc80be736f2/jdk/src/java.base/share/classes/jdk/internal/module/ModuleReferences.java	2022-04-12 16:43:12.971868797 +0200
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
++ * Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved.
+  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+  *
+  * This code is free software; you can redistribute it and/or modify it
+@@ -95,7 +95,7 @@
+                                         Path file) {
+         URI uri = file.toUri();
+         Supplier<ModuleReader> supplier = () -> new JarModuleReader(file, uri);
+-        HashSupplier hasher = (a) -> ModuleHashes.computeHash(file, a);
++        HashSupplier hasher = (a) -> ModuleHashes.computeHash(supplier, a);
+         return newModule(attrs, uri, supplier, patcher, hasher);
+     }
+ 
+@@ -105,7 +105,7 @@
+     static ModuleReference newJModModule(ModuleInfo.Attributes attrs, Path file) {
+         URI uri = file.toUri();
+         Supplier<ModuleReader> supplier = () -> new JModModuleReader(file, uri);
+-        HashSupplier hasher = (a) -> ModuleHashes.computeHash(file, a);
++        HashSupplier hasher = (a) -> ModuleHashes.computeHash(supplier, a);
+         return newModule(attrs, uri, supplier, null, hasher);
+     }
+ 
diff --git a/gnu/packages/patches/openjdk-9-module2-reproducibility.patch b/gnu/packages/patches/openjdk-9-module2-reproducibility.patch
new file mode 100644
index 0000000000..f167d94dc8
--- /dev/null
+++ b/gnu/packages/patches/openjdk-9-module2-reproducibility.patch
@@ -0,0 +1,125 @@
+Backport from openjdk 10
+
+--- orig/jdk-3cc80be736f2/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ModuleSorter.java	1970-01-01 01:00:01.000000000 +0100
++++ jdk-3cc80be736f2/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ModuleSorter.java	2022-04-12 20:48:04.474353305 +0200
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
++ * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
+  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+  *
+  * This code is free software; you can redistribute it and/or modify it
+@@ -30,13 +30,16 @@
+ import jdk.tools.jlink.plugin.ResourcePoolModuleView;
+ 
+ import java.lang.module.ModuleDescriptor;
++import java.lang.module.ModuleDescriptor.Requires;
+ import java.lang.module.ModuleDescriptor.Requires.Modifier;
+ 
+ import java.nio.ByteBuffer;
+-import java.util.Deque;
++import java.util.ArrayList;
++import java.util.Comparator;
+ import java.util.HashMap;
+ import java.util.HashSet;
+-import java.util.LinkedList;
++import java.util.LinkedHashSet;
++import java.util.List;
+ import java.util.Map;
+ import java.util.Set;
+ import java.util.stream.Stream;
+@@ -45,9 +48,8 @@
+  * Helper class to sort modules in topological order
+  */
+ public final class ModuleSorter {
+-    private final Deque<ResourcePoolModule> nodes = new LinkedList<>();
+-    private final Map<String, Set<ResourcePoolModule>> edges = new HashMap<>();
+-    private final Deque<ResourcePoolModule> result = new LinkedList<>();
++    private final Map<ResourcePoolModule, Set<ResourcePoolModule>> graph = new HashMap<>();
++    private final List<ResourcePoolModule> result = new ArrayList<>();
+ 
+     private final ResourcePoolModuleView moduleView;
+ 
+@@ -69,11 +71,17 @@
+ 
+     private ModuleSorter addModule(ResourcePoolModule module) {
+         addNode(module);
+-        readModuleDescriptor(module).requires().forEach(req -> {
++        // the module graph will be traversed in a stable order for
++        // the topological sort. So add the dependences in the module name order
++        readModuleDescriptor(module).requires()
++                                    .stream()
++                                    .sorted(Comparator.comparing(Requires::name))
++                                    .forEach(req ->
++        {
+             ResourcePoolModule dep = moduleView.findModule(req.name()).orElse(null);
+             if (dep != null) {
+                 addNode(dep);
+-                edges.get(module.name()).add(dep);
++                graph.get(module).add(dep);
+             } else if (!req.modifiers().contains(Modifier.STATIC)) {
+                 throw new PluginException(req.name() + " not found");
+             }
+@@ -82,22 +90,23 @@
+     }
+ 
+     private void addNode(ResourcePoolModule module) {
+-        nodes.add(module);
+-        edges.computeIfAbsent(module.name(), _n -> new HashSet<>());
++        graph.computeIfAbsent(module, _n -> new LinkedHashSet<>());
+     }
+ 
++    /*
++     * The module graph will be traversed in a stable order
++     * (traversing the modules and their dependences in alphabetical order)
++     * so that it will produce the same result of a given module graph.
++     */
+     private synchronized void build() {
+-        if (!result.isEmpty() || nodes.isEmpty())
++        if (!result.isEmpty() || graph.isEmpty())
+             return;
+ 
+-        Deque<ResourcePoolModule> visited = new LinkedList<>();
+-        Deque<ResourcePoolModule> done = new LinkedList<>();
+-        ResourcePoolModule node;
+-        while ((node = nodes.poll()) != null) {
+-            if (!visited.contains(node)) {
+-                visit(node, visited, done);
+-            }
+-        }
++        Set<ResourcePoolModule> visited = new HashSet<>();
++        Set<ResourcePoolModule> done = new HashSet<>();
++        graph.keySet().stream()
++             .sorted(Comparator.comparing(ResourcePoolModule::name))
++             .forEach(node -> visit(node, visited, done));
+     }
+ 
+     public Stream<ResourcePoolModule> sorted() {
+@@ -106,19 +115,21 @@
+     }
+ 
+     private void visit(ResourcePoolModule node,
+-                       Deque<ResourcePoolModule> visited,
+-                       Deque<ResourcePoolModule> done) {
++                       Set<ResourcePoolModule> visited,
++                       Set<ResourcePoolModule> done) {
+         if (visited.contains(node)) {
+             if (!done.contains(node)) {
+                 throw new IllegalArgumentException("Cyclic detected: " +
+-                    node + " " + edges.get(node.name()));
++                    node + " " + graph.get(node));
+             }
+             return;
+         }
++
++        // traverse the dependences of the given module which are
++        // also sorted in alphabetical order
+         visited.add(node);
+-        edges.get(node.name())
+-             .forEach(x -> visit(x, visited, done));
++        graph.get(node).forEach(x -> visit(x, visited, done));
+         done.add(node);
+-        result.addLast(node);
++        result.add(node);
+     }
+ }
diff --git a/gnu/packages/patches/openjdk-9-module3-reproducibility.patch b/gnu/packages/patches/openjdk-9-module3-reproducibility.patch
new file mode 100644
index 0000000000..9db54f5531
--- /dev/null
+++ b/gnu/packages/patches/openjdk-9-module3-reproducibility.patch
@@ -0,0 +1,36 @@
+From: Danny Milosavljevic <dannym <at> scratchpost.org>
+Date: Wed, 18 Apr 2022 21:50:00 +0100
+Subject: Make module descriptor reproducible
+
+--- orig/jdk-3cc80be736f2/jdk/src/java.base/share/classes/java/lang/module/ModuleDescriptor.java	1970-01-01 01:00:01.000000000 +0100
++++ jdk-3cc80be736f2/jdk/src/java.base/share/classes/java/lang/module/ModuleDescriptor.java	2022-04-13 17:30:37.242775977 +0200
+@@ -43,6 +43,7 @@
+ import java.util.Objects;
+ import java.util.Optional;
+ import java.util.Set;
++import java.util.TreeSet;
+ import java.util.function.Supplier;
+ import java.util.stream.Collectors;
+ import java.util.stream.Stream;
+@@ -2155,9 +2156,9 @@
+          * @return The module descriptor
+          */
+         public ModuleDescriptor build() {
+-            Set<Requires> requires = new HashSet<>(this.requires.values());
+-            Set<Exports> exports = new HashSet<>(this.exports.values());
+-            Set<Opens> opens = new HashSet<>(this.opens.values());
++            Set<Requires> requires = new TreeSet<>(this.requires.values());
++            Set<Exports> exports = new TreeSet<>(this.exports.values());
++            Set<Opens> opens = new TreeSet<>(this.opens.values());
+ 
+             // add dependency on java.base
+             if (strict
+@@ -2169,7 +2170,7 @@
+                                           null));
+             }
+ 
+-            Set<Provides> provides = new HashSet<>(this.provides.values());
++            Set<Provides> provides = new TreeSet<>(this.provides.values());
+ 
+             return new ModuleDescriptor(name,
+                                         version,
-- 
2.39.2





Information forwarded to guix-patches <at> gnu.org:
bug#55751; Package guix-patches. (Mon, 31 Jul 2023 18:11:02 GMT) Full text and rfc822 format available.

Message #53 received at 55751 <at> debbugs.gnu.org (full text, mbox):

From: Danny Milosavljevic <dannym <at> scratchpost.org>
To: 55751 <at> debbugs.gnu.org
Cc: Danny Milosavljevic <dannym <at> scratchpost.org>
Subject: [PATCH v2 2/7] gnu: openjdk10: Make more reproducible.
Date: Mon, 31 Jul 2023 20:09:14 +0200
* gnu/packages/patches/openjdk-10-char-reproducibility.patch: New file.
* gnu/packages/patches/openjdk-10-classlist-reproducibility.patch: New file.
* gnu/packages/patches/openjdk-10-corba-reproducibility.patch: New file.
* gnu/packages/patches/openjdk-10-jar-reproducibility.patch: New file.
* gnu/packages/patches/openjdk-10-jtask-reproducibility.patch: New file.
* gnu/packages/patches/openjdk-10-module-reproducibility.patch: New file.
* gnu/packages/patches/openjdk-10-module3-reproducibility.patch: New file.
* gnu/packages/patches/openjdk-10-module4-reproducibility.patch: New file.
* gnu/packages/java.scm (openjdk10)[source]: Add patches.
[arguments]<#:phases>[remove-timestamping]: New phase.
* gnu/local.mk (dist_patch_DATA): Add patches.
---
 gnu/local.mk                                  |   8 +
 gnu/packages/java.scm                         |  13 +
 .../openjdk-10-char-reproducibility.patch     |  12 +
 ...openjdk-10-classlist-reproducibility.patch |  27 ++
 .../openjdk-10-corba-reproducibility.patch    |  12 +
 .../openjdk-10-jar-reproducibility.patch      | 103 ++++++
 .../openjdk-10-jtask-reproducibility.patch    |  53 +++
 .../openjdk-10-module-reproducibility.patch   | 305 ++++++++++++++++++
 .../openjdk-10-module3-reproducibility.patch  |  34 ++
 .../openjdk-10-module4-reproducibility.patch  |  14 +
 10 files changed, 581 insertions(+)
 create mode 100644 gnu/packages/patches/openjdk-10-char-reproducibility.patch
 create mode 100644 gnu/packages/patches/openjdk-10-classlist-reproducibility.patch
 create mode 100644 gnu/packages/patches/openjdk-10-corba-reproducibility.patch
 create mode 100644 gnu/packages/patches/openjdk-10-jar-reproducibility.patch
 create mode 100644 gnu/packages/patches/openjdk-10-jtask-reproducibility.patch
 create mode 100644 gnu/packages/patches/openjdk-10-module-reproducibility.patch
 create mode 100644 gnu/packages/patches/openjdk-10-module3-reproducibility.patch
 create mode 100644 gnu/packages/patches/openjdk-10-module4-reproducibility.patch

diff --git a/gnu/local.mk b/gnu/local.mk
index 155b9e7740..791e5a85aa 100644
--- a/gnu/local.mk
+++ b/gnu/local.mk
@@ -1664,7 +1664,15 @@ dist_patch_DATA =						\
   %D%/packages/patches/openjdk-9-module-reproducibility.patch	\
   %D%/packages/patches/openjdk-9-module2-reproducibility.patch	\
   %D%/packages/patches/openjdk-9-module3-reproducibility.patch	\
+  %D%/packages/patches/openjdk-10-char-reproducibility.patch	\
+  %D%/packages/patches/openjdk-10-classlist-reproducibility.patch	\
+  %D%/packages/patches/openjdk-10-corba-reproducibility.patch	\
   %D%/packages/patches/openjdk-10-idlj-reproducibility.patch	\
+  %D%/packages/patches/openjdk-10-jar-reproducibility.patch	\
+  %D%/packages/patches/openjdk-10-jtask-reproducibility.patch	\
+  %D%/packages/patches/openjdk-10-module-reproducibility.patch	\
+  %D%/packages/patches/openjdk-10-module3-reproducibility.patch	\
+  %D%/packages/patches/openjdk-10-module4-reproducibility.patch	\
   %D%/packages/patches/openjdk-10-pointer-comparison.patch      \
   %D%/packages/patches/openjdk-10-setsignalhandler.patch        \
   %D%/packages/patches/openjdk-15-xcursor-no-dynamic.patch	\
diff --git a/gnu/packages/java.scm b/gnu/packages/java.scm
index ad2af44229..14e9b1f653 100644
--- a/gnu/packages/java.scm
+++ b/gnu/packages/java.scm
@@ -1098,7 +1098,15 @@ (define-public openjdk10
                (base32
                 "0i47ar8lxzjrkkiwbzybfxs473390h4jq9ahm3xqdvy5zpchxy3y"))
               (patches (search-patches
+                        "openjdk-10-char-reproducibility.patch"
+                        "openjdk-10-classlist-reproducibility.patch"
+                        "openjdk-10-corba-reproducibility.patch"
                         "openjdk-10-idlj-reproducibility.patch"
+                        "openjdk-10-module-reproducibility.patch"
+                        "openjdk-10-module3-reproducibility.patch"
+                        "openjdk-10-module4-reproducibility.patch"
+                        "openjdk-10-jar-reproducibility.patch"
+                        "openjdk-10-jtask-reproducibility.patch"
                         "openjdk-10-pointer-comparison.patch"
                         "openjdk-10-setsignalhandler.patch"))))
     (arguments
@@ -1112,6 +1120,11 @@ (define-public openjdk10
                (substitute* "make/data/blacklistedcertsconverter/blacklisted.certs.pem"
                  (("^#!.*") "#! java BlacklistedCertsConverter SHA-256\n"))
                #t))
+           (add-after 'unpack 'remove-timestamping
+             (lambda _
+               (substitute* "./src/hotspot/share/runtime/vm_version.cpp"
+                 (("__DATE__") "")
+                 (("__TIME__") ""))))
            (replace 'configure
              (lambda* (#:key inputs outputs #:allow-other-keys)
                (invoke "bash" "./configure"
diff --git a/gnu/packages/patches/openjdk-10-char-reproducibility.patch b/gnu/packages/patches/openjdk-10-char-reproducibility.patch
new file mode 100644
index 0000000000..a7932678af
--- /dev/null
+++ b/gnu/packages/patches/openjdk-10-char-reproducibility.patch
@@ -0,0 +1,12 @@
+Danny
+--- orig/jdk-6fa770f9f8ab/make/jdk/src/classes/build/tools/generatecharacter/GenerateCharacter.java	2022-04-13 19:24:10.211683257 +0200
++++ jdk-6fa770f9f8ab/make/jdk/src/classes/build/tools/generatecharacter/GenerateCharacter.java	2022-04-13 22:51:50.680487330 +0200
+@@ -693,7 +693,7 @@
+         PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(theOutputFileName)));
+         out.println(commentStart +
+             " This file was generated AUTOMATICALLY from a template file " +
+-            new java.util.Date() + commentEnd);
++            (System.getenv("SOURCE_DATE_EPOCH") == null ? new java.util.Date() : new java.util.Date(1000 * Long.parseLong(System.getenv("SOURCE_DATE_EPOCH")))) + commentEnd);
+         int marklen = commandMarker.length();
+         LOOP: while(true) {
+             try {
diff --git a/gnu/packages/patches/openjdk-10-classlist-reproducibility.patch b/gnu/packages/patches/openjdk-10-classlist-reproducibility.patch
new file mode 100644
index 0000000000..e1292ba82d
--- /dev/null
+++ b/gnu/packages/patches/openjdk-10-classlist-reproducibility.patch
@@ -0,0 +1,27 @@
+--- orig/jdk-6fa770f9f8ab/make/GenerateLinkOptData.gmk	2022-04-04 17:16:29.365930149 +0200
++++ jdk-6fa770f9f8ab/make/GenerateLinkOptData.gmk	2022-04-04 17:16:54.954624358 +0200
+@@ -61,11 +61,12 @@
+ 	$(call MakeDir, $(LINK_OPT_DIR))
+ 	$(call LogInfo, Generating $(patsubst $(OUTPUTDIR)/%, %, $@))
+ 	$(call LogInfo, Generating $(patsubst $(OUTPUTDIR)/%, %, $(JLI_TRACE_FILE)))
+-	$(FIXPATH) $(INTERIM_IMAGE_DIR)/bin/java -XX:DumpLoadedClassList=$@ \
++	$(FIXPATH) $(INTERIM_IMAGE_DIR)/bin/java -XX:DumpLoadedClassList=$@.tmp \
+ 	    -Djava.lang.invoke.MethodHandle.TRACE_RESOLVE=true \
+ 	    -cp $(SUPPORT_OUTPUTDIR)/classlist.jar \
+ 	    build.tools.classlist.HelloClasslist \
+ 	    $(LOG_DEBUG) 2>&1 > $(JLI_TRACE_FILE)
++	sort $@.tmp > $@
+ 
+ # The jli trace is created by the same recipe as classlist. By declaring these
+ # dependencies, make will correctly rebuild both jli trace and classlist
+--- orig/jdk-6fa770f9f8ab/make/gendata/Gendata-jdk.compiler.gmk	2022-04-13 19:24:10.191682716 +0200
++++ jdk-6fa770f9f8ab/make/gendata/Gendata-jdk.compiler.gmk	2022-04-13 20:58:57.891368216 +0200
+@@ -83,6 +83,8 @@
+ 	    $(CT_MODULESOURCEPATH) \
+ 	    $(CT_MODULES) \
+ 	    >$(@D)/A/system-modules
++	# Make files reproducible
++	find $(@D) -exec $(TOUCH) -h -c -t 197001010000.01 {} \;
+ 	$(TOUCH) $@
+ 
+ # Can't generate ct.sym directly into modules libs as the SetupJarArchive macro
diff --git a/gnu/packages/patches/openjdk-10-corba-reproducibility.patch b/gnu/packages/patches/openjdk-10-corba-reproducibility.patch
new file mode 100644
index 0000000000..bd5ce1fd2b
--- /dev/null
+++ b/gnu/packages/patches/openjdk-10-corba-reproducibility.patch
@@ -0,0 +1,12 @@
+Danny
+--- orig/jdk-6fa770f9f8ab/make/corba/src/classes/build/tools/logutil/MC.java	2022-04-13 19:24:10.111680549 +0200
++++ jdk-6fa770f9f8ab/make/corba/src/classes/build/tools/logutil/MC.java	2022-04-13 22:51:13.399462259 +0200
+@@ -154,7 +154,7 @@
+                   groupName);
+     pw.println("//");
+     pw.printMsg("// Generated by MC.java version @, DO NOT EDIT BY HAND!", VERSION);
+-    pw.printMsg("// Generated from input file @ on @", inFile, new Date());
++    pw.printMsg("// Generated from input file @ on @", inFile, System.getenv("SOURCE_DATE_EPOCH") == null ? new Date() : new Date(1000 * Long.parseLong(System.getenv("SOURCE_DATE_EPOCH"))));
+     pw.println();
+   }
+ 
diff --git a/gnu/packages/patches/openjdk-10-jar-reproducibility.patch b/gnu/packages/patches/openjdk-10-jar-reproducibility.patch
new file mode 100644
index 0000000000..176eedfce6
--- /dev/null
+++ b/gnu/packages/patches/openjdk-10-jar-reproducibility.patch
@@ -0,0 +1,103 @@
+diff -ru orig/jdk-6fa770f9f8ab/make/common/JarArchive.gmk jdk-6fa770f9f8ab/make/common/JarArchive.gmk
+--- orig/jdk-6fa770f9f8ab/make/common/JarArchive.gmk	2022-04-13 19:24:10.107680441 +0200
++++ jdk-6fa770f9f8ab/make/common/JarArchive.gmk	2022-04-13 19:31:18.031271019 +0200
+@@ -251,12 +251,14 @@
+ 	    $(ECHO) "Main-Class: $$(strip $$($1_JARMAIN))" >> $$($1_MANIFEST_FILE) $$(NEWLINE)) \
+ 	  $$(if $$($1_EXTRA_MANIFEST_ATTR), \
+ 	    $(PRINTF) "$$($1_EXTRA_MANIFEST_ATTR)\n" >> $$($1_MANIFEST_FILE) $$(NEWLINE)) \
++	  $(TOUCH) -h -c -t 197001010000.00 $$($1_MANIFEST_FILE) $$(NEWLINE) \
+ 	  $(ECHO) Creating $$($1_NAME) $$(NEWLINE) \
+ 	  $$($1_JAR_CMD) $$($1_JAR_CREATE_OPTIONS) $$@ $$($1_MANIFEST_FILE) $$(NEWLINE) \
+ 	  $$($1_SCAPTURE_CONTENTS) \
+ 	  $$($1_SCAPTURE_METAINF) \
+ 	  $$($1_SUPDATE_CONTENTS) \
+-	  $$($1_JARINDEX) && true \
++	  $$($1_JARINDEX) && true $$(NEWLINE) \
++	  d="`mktemp -d`" && $(CP) -f $$@ "$$$$d/a.jar" && (cd "$$$$d" && unzip a.jar META-INF/MANIFEST.MF && $(TOUCH) -h -c -t 197001010000.00 META-INF &&  $(TOUCH) -h -c -t 197001010000.00 META-INF/MANIFEST.MF && (zip --symlinks -0 -X a.jar META-INF META-INF/MANIFEST.MF; zip --symlinks -0 -X a.jar META-INF META-INF/MANIFEST.MF)) && $(CP) -f "$$$$d/a.jar" $$@ \
+ 	, \
+ 	  $(ECHO) Modifying $$($1_NAME) $$(NEWLINE) \
+ 	  $$($1_CAPTURE_CONTENTS) \
+diff -ru orig/jdk-6fa770f9f8ab/make/JrtfsJar.gmk jdk-6fa770f9f8ab/make/JrtfsJar.gmk
+--- orig/jdk-6fa770f9f8ab/make/JrtfsJar.gmk	2022-04-13 19:24:10.091680007 +0200
++++ jdk-6fa770f9f8ab/make/JrtfsJar.gmk	2022-04-13 19:29:30.044346222 +0200
+@@ -57,13 +57,18 @@
+ # file will not be copied unless META-INF/services would also be added to the INCLUDES.
+ # Adding META-INF/services would include all files in that directory when only the one
+ # is needed, which is why this explicit copy is defined instead.
+-$(eval $(call SetupCopyFiles, COPY_JIMAGE_SERVICE_PROVIDER, \
++$(eval $(call SetupCopyFiles, COPY_JIMAGE_SERVICE_PROVIDER, \
+     SRC := $(TOPDIR)/src/java.base/share/classes, \
+     DEST := $(SUPPORT_OUTPUTDIR)/jrtfs_classes, \
+     FILES := META-INF/services/java.nio.file.spi.FileSystemProvider))
+ 
++.PHONY: $(COPY_JIMAGE_SERVICE_PROVIDER)_fix
++$(COPY_JIMAGE_SERVICE_PROVIDER)_fix: $(COPY_JIMAGE_SERVICE_PROVIDER)
++	find $(SUPPORT_OUTPUTDIR)/jrtfs_classes -exec $(TOUCH) -h -c -t 197001010000.00 {} \;
++	$(TOUCH) -h -c -t 197001010000.00 $(SUPPORT_OUTPUTDIR)/java-main-manifest.mf
++
+ $(eval $(call SetupJarArchive,BUILD_JRTFS_JAR, \
+-    DEPENDENCIES := $(BUILD_JRTFS) $(COPY_JIMAGE_SERVICE_PROVIDER), \
++    DEPENDENCIES := $(BUILD_JRTFS) $(COPY_JIMAGE_SERVICE_PROVIDER)_fix, \
+     SRCS := $(SUPPORT_OUTPUTDIR)/jrtfs_classes, \
+     JAR := $(SUPPORT_OUTPUTDIR)/modules_libs/java.base/jrt-fs.jar, \
+     MANIFEST := $(SUPPORT_OUTPUTDIR)/java-main-manifest.mf, \
+diff -ru orig/jdk-6fa770f9f8ab/src/jdk.jartool/share/classes/sun/tools/jar/Main.java jdk-6fa770f9f8ab/src/jdk.jartool/share/classes/sun/tools/jar/Main.java
+--- orig/jdk-6fa770f9f8ab/src/jdk.jartool/share/classes/sun/tools/jar/Main.java	2022-04-13 19:24:12.555746751 +0200
++++ jdk-6fa770f9f8ab/src/jdk.jartool/share/classes/sun/tools/jar/Main.java	2022-04-13 19:25:34.117955999 +0200
+@@ -849,12 +849,18 @@
+                     output(getMsg("out.added.manifest"));
+                 }
+                 ZipEntry e = new ZipEntry(MANIFEST_DIR);
+-                e.setTime(System.currentTimeMillis());
++                if (System.getenv("SOURCE_DATE_EPOCH") != null)
++                    e.setTime(1000 * Long.parseLong(System.getenv("SOURCE_DATE_EPOCH")));
++                else
++                    e.setTime(System.currentTimeMillis());
+                 e.setSize(0);
+                 e.setCrc(0);
+                 zos.putNextEntry(e);
+                 e = new ZipEntry(MANIFEST_NAME);
+-                e.setTime(System.currentTimeMillis());
++                if (System.getenv("SOURCE_DATE_EPOCH") != null)
++                    e.setTime(1000 * Long.parseLong(System.getenv("SOURCE_DATE_EPOCH")));
++                else
++                    e.setTime(System.currentTimeMillis());
+                 if (flag0) {
+                     crc32Manifest(e, manifest);
+                 }
+@@ -1021,7 +1027,10 @@
+         throws IOException
+     {
+         ZipEntry e = new ZipEntry(INDEX_NAME);
+-        e.setTime(System.currentTimeMillis());
++        if (System.getenv("SOURCE_DATE_EPOCH") != null)
++            e.setTime(1000 * Long.parseLong(System.getenv("SOURCE_DATE_EPOCH")));
++        else
++            e.setTime(System.currentTimeMillis());
+         if (flag0) {
+             CRC32OutputStream os = new CRC32OutputStream();
+             index.write(os);
+@@ -1040,7 +1049,10 @@
+             String name = mi.getKey();
+             byte[] bytes = mi.getValue();
+             ZipEntry e = new ZipEntry(name);
+-            e.setTime(System.currentTimeMillis());
++            if (System.getenv("SOURCE_DATE_EPOCH") != null)
++                e.setTime(1000 * Long.parseLong(System.getenv("SOURCE_DATE_EPOCH")));
++            else
++                e.setTime(System.currentTimeMillis());
+             if (flag0) {
+                 crc32ModuleInfo(e, bytes);
+             }
+@@ -1065,7 +1077,10 @@
+             addMultiRelease(m);
+         }
+         ZipEntry e = new ZipEntry(MANIFEST_NAME);
+-        e.setTime(System.currentTimeMillis());
++        if (System.getenv("SOURCE_DATE_EPOCH") != null)
++            e.setTime(1000 * Long.parseLong(System.getenv("SOURCE_DATE_EPOCH")));
++        else
++            e.setTime(System.currentTimeMillis());
+         if (flag0) {
+             crc32Manifest(e, m);
+         }
diff --git a/gnu/packages/patches/openjdk-10-jtask-reproducibility.patch b/gnu/packages/patches/openjdk-10-jtask-reproducibility.patch
new file mode 100644
index 0000000000..3411ca12ae
--- /dev/null
+++ b/gnu/packages/patches/openjdk-10-jtask-reproducibility.patch
@@ -0,0 +1,53 @@
+--- jdk-10/src/jdk.jlink/share/classes/jdk/tools/jmod/JmodTask.java.orig	2022-04-04 11:18:52.760626467 +0200
++++ jdk-10/src/jdk.jlink/share/classes/jdk/tools/jmod/JmodTask.java	2022-04-04 12:03:40.645325687 +0200
+@@ -105,6 +105,7 @@
+ import jdk.internal.module.ModuleTarget;
+ import jdk.internal.module.Resources;
+ import jdk.tools.jlink.internal.Utils;
++import java.util.TreeSet;
+ 
+ import static java.util.stream.Collectors.joining;
+ 
+@@ -768,6 +769,7 @@
+         void processSection(JmodOutputStream out, Section section, Path path)
+             throws IOException
+         {
++            TreeSet<Path> paths = new TreeSet<>();
+             Files.walkFileTree(path, Set.of(FileVisitOption.FOLLOW_LINKS),
+                 Integer.MAX_VALUE, new SimpleFileVisitor<Path>() {
+                     @Override
+@@ -781,20 +783,24 @@
+ 
+                         if (!relPath.toString().equals(MODULE_INFO)
+                                 && !matches(relPath, excludes)) {
+-                            try (InputStream in = Files.newInputStream(file)) {
+-                                out.writeEntry(in, section, relPath.toString());
+-                            } catch (IOException x) {
+-                                if (x.getMessage().contains("duplicate entry")) {
+-                                    warning("warn.ignore.duplicate.entry",
+-                                            relPath.toString(), section);
+-                                    return FileVisitResult.CONTINUE;
+-                                }
+-                                throw x;
+-                            }
++                            paths.add(file);
+                         }
+                         return FileVisitResult.CONTINUE;
+                     }
+                 });
++            for (Path file : paths) {
++                Path relPath = path.relativize(file);
++                try (InputStream in = Files.newInputStream(file)) {
++                    out.writeEntry(in, section, relPath.toString());
++                } catch (IOException x) {
++                    if (x.getMessage().contains("duplicate entry")) {
++                        warning("warn.ignore.duplicate.entry",
++                                  relPath.toString(), section);
++                        continue;
++                    }
++                    throw x;
++                }
++            }
+         }
+ 
+         boolean matches(Path path, List<PathMatcher> matchers) {
diff --git a/gnu/packages/patches/openjdk-10-module-reproducibility.patch b/gnu/packages/patches/openjdk-10-module-reproducibility.patch
new file mode 100644
index 0000000000..165edd3b4a
--- /dev/null
+++ b/gnu/packages/patches/openjdk-10-module-reproducibility.patch
@@ -0,0 +1,305 @@
+From a52c4ef44c0553a399a8a47e528db92e3bf51c6c Mon Sep 17 00:00:00 2001
+From: Alan Bateman <alanb <at> openjdk.org>
+Date: Wed, 29 Apr 2020 08:38:28 +0100
+Subject: [PATCH] 8243666: ModuleHashes attribute generated for JMOD and JAR
+ files depends on timestamps
+
+Reviewed-by: mchung
+---
+
+--- orig/jdk-3cc80be736f2/src/java.base/share/classes/jdk/internal/module/ModuleHashesBuilder.java	2022-04-13 19:24:10.655695284 +0200
++++ jdk-3cc80be736f2/src/java.base/share/classes/jdk/internal/module/ModuleHashesBuilder.java	2022-04-14 02:43:48.610326492 +0200
+@@ -27,9 +27,8 @@
+ 
+ import java.io.PrintStream;
+ import java.lang.module.Configuration;
++import java.lang.module.ModuleReference;
+ import java.lang.module.ResolvedModule;
+-import java.net.URI;
+-import java.nio.file.Path;
+ import java.nio.file.Paths;
+ import java.util.ArrayDeque;
+ import java.util.Collections;
+@@ -39,8 +38,8 @@
+ import java.util.LinkedList;
+ import java.util.Map;
+ import java.util.Set;
++import java.util.TreeMap;
+ import java.util.function.Consumer;
+-import java.util.function.Function;
+ import java.util.stream.Stream;
+ import static java.util.stream.Collectors.*;
+ 
+@@ -101,7 +100,7 @@
+         // the modules to record the hashes - it is the first matching
+         // module and has not been hashed during the traversal.
+         Set<String> mods = new HashSet<>();
+-        Map<String, ModuleHashes> hashes = new HashMap<>();
++        Map<String, ModuleHashes> hashes = new TreeMap<>();
+         builder.build()
+                .orderedNodes()
+                .filter(mn -> roots.contains(mn) && !mods.contains(mn))
+@@ -116,27 +115,17 @@
+                    mods.addAll(ns);
+ 
+                    if (!ns.isEmpty()) {
+-                       Map<String, Path> moduleToPath = ns.stream()
+-                           .collect(toMap(Function.identity(), this::moduleToPath));
+-                       hashes.put(mn, ModuleHashes.generate(moduleToPath, "SHA-256"));
++                       Set<ModuleReference> mrefs = ns.stream()
++                               .map(name -> configuration.findModule(name)
++                                                         .orElseThrow(InternalError::new))
++                               .map(ResolvedModule::reference)
++                               .collect(toSet());
++                       hashes.put(mn, ModuleHashes.generate(mrefs, "SHA-256"));
+                    }
+                });
+         return hashes;
+     }
+ 
+-    private Path moduleToPath(String name) {
+-        ResolvedModule rm = configuration.findModule(name).orElseThrow(
+-            () -> new InternalError("Selected module " + name + " not on module path"));
+-
+-        URI uri = rm.reference().location().get();
+-        Path path = Paths.get(uri);
+-        String fn = path.getFileName().toString();
+-        if (!fn.endsWith(".jar") && !fn.endsWith(".jmod")) {
+-            throw new UnsupportedOperationException(path + " is not a modular JAR or jmod file");
+-        }
+-        return path;
+-    }
+-
+     /*
+      * Utility class
+      */diff -ru orig/jdk-3cc80be736f2/src/java.base/share/classes/jdk/internal/module/ModuleHashes.java jdk-3cc80be736f2/src/java.base/share/classes/jdk/internal/module/ModuleHashes.java
+--- orig/jdk-3cc80be736f2/src/java.base/share/classes/jdk/internal/module/ModuleHashes.java	1970-01-01 01:00:01.000000000 +0100
++++ jdk-3cc80be736f2/src/java.base/share/classes/jdk/internal/module/ModuleHashes.java	2022-04-12 16:58:05.639985936 +0200
+@@ -26,17 +26,21 @@
+ package jdk.internal.module;
+ 
+ import java.io.IOException;
++import java.io.InputStream;
+ import java.io.UncheckedIOException;
+-import java.nio.ByteBuffer;
+-import java.nio.channels.FileChannel;
+-import java.nio.file.Path;
++import java.lang.module.ModuleReader;
++import java.lang.module.ModuleReference;
++import java.nio.charset.StandardCharsets;
+ import java.security.MessageDigest;
+ import java.security.NoSuchAlgorithmException;
++import java.util.Arrays;
+ import java.util.Collections;
+ import java.util.HashMap;
+ import java.util.Map;
+ import java.util.Objects;
+ import java.util.Set;
++import java.util.TreeMap;
++import java.util.function.Supplier;
+ 
+ /**
+  * The result of hashing the contents of a number of module artifacts.
+@@ -60,8 +64,8 @@
+      * @param algorithm   the algorithm used to create the hashes
+      * @param nameToHash  the map of module name to hash value
+      */
+-    public ModuleHashes(String algorithm, Map<String, byte[]> nameToHash) {
+-        this.algorithm = algorithm;
++    ModuleHashes(String algorithm, Map<String, byte[]> nameToHash) {
++        this.algorithm = Objects.requireNonNull(algorithm);
+         this.nameToHash = Collections.unmodifiableMap(nameToHash);
+     }
+ 
+@@ -95,54 +99,125 @@
+     }
+ 
+     /**
+-     * Computes the hash for the given file with the given message digest
+-     * algorithm.
++     * Computes a hash from the names and content of a module.
+      *
++     * @param reader the module reader to access the module content
++     * @param algorithm the name of the message digest algorithm to use
++     * @return the hash
++     * @throws IllegalArgumentException if digest algorithm is not supported
+      * @throws UncheckedIOException if an I/O error occurs
+      * @throws RuntimeException if the algorithm is not available
+      */
+-    public static byte[] computeHash(Path file, String algorithm) {
++    private static byte[] computeHash(ModuleReader reader, String algorithm) {
++        MessageDigest md;
+         try {
+-            MessageDigest md = MessageDigest.getInstance(algorithm);
+-
+-            // Ideally we would just mmap the file but this consumes too much
+-            // memory when jlink is running concurrently on very large jmods
+-            try (FileChannel fc = FileChannel.open(file)) {
+-                ByteBuffer bb = ByteBuffer.allocate(32*1024);
+-                while (fc.read(bb) > 0) {
+-                    bb.flip();
+-                    md.update(bb);
+-                    assert bb.remaining() == 0;
+-                    bb.clear();
+-                }
+-            }
+-
+-            return md.digest();
++            md = MessageDigest.getInstance(algorithm);
+         } catch (NoSuchAlgorithmException e) {
+-            throw new RuntimeException(e);
++            throw new IllegalArgumentException(e);
++        }
++        try {
++            byte[] buf = new byte[32*1024];
++            reader.list().sorted().forEach(rn -> {
++                md.update(rn.getBytes(StandardCharsets.UTF_8));
++                try (InputStream in = reader.open(rn).orElseThrow(java.util.NoSuchElementException::new)) {
++                    int n;
++                    while ((n = in.read(buf)) > 0) {
++                        md.update(buf, 0, n);
++                    }
++                } catch (IOException ioe) {
++                    throw new UncheckedIOException(ioe);
++                }
++            });
+         } catch (IOException ioe) {
+             throw new UncheckedIOException(ioe);
+         }
++        return md.digest();
+     }
+ 
+     /**
+-     * Computes the hash for every entry in the given map, returning a
+-     * {@code ModuleHashes} to encapsulate the result. The map key is
+-     * the entry name, typically the module name. The map value is the file
+-     * path to the entry (module artifact).
++     * Computes a hash from the names and content of a module.
+      *
++     * @param supplier supplies the module reader to access the module content
++     * @param algorithm the name of the message digest algorithm to use
++     * @return the hash
++     * @throws IllegalArgumentException if digest algorithm is not supported
++     * @throws UncheckedIOException if an I/O error occurs
++     */
++    static byte[] computeHash(Supplier<ModuleReader> supplier, String algorithm) {
++        try (ModuleReader reader = supplier.get()) {
++            return computeHash(reader, algorithm);
++        } catch (IOException ioe) {
++            throw new UncheckedIOException(ioe);
++        }
++    }
++
++    /**
++     * Computes the hash from the names and content of a set of modules. Returns
++     * a {@code ModuleHashes} to encapsulate the result.
++     * @param mrefs the set of modules
++     * @param algorithm the name of the message digest algorithm to use
+      * @return ModuleHashes that encapsulates the hashes
++     * @throws IllegalArgumentException if digest algorithm is not supported
++     * @throws UncheckedIOException if an I/O error occurs
+      */
+-    public static ModuleHashes generate(Map<String, Path> map, String algorithm) {
++    static ModuleHashes generate(Set<ModuleReference> mrefs, String algorithm) {
+         Map<String, byte[]> nameToHash = new HashMap<>();
+-        for (Map.Entry<String, Path> entry: map.entrySet()) {
+-            String name = entry.getKey();
+-            Path path = entry.getValue();
+-            nameToHash.put(name, computeHash(path, algorithm));
++        for (ModuleReference mref : mrefs) {
++            try (ModuleReader reader = mref.open()) {
++                byte[] hash = computeHash(reader, algorithm);
++                nameToHash.put(mref.descriptor().name(), hash);
++            } catch (IOException ioe) {
++                throw new UncheckedIOException(ioe);
++            }
+         }
+         return new ModuleHashes(algorithm, nameToHash);
+     }
+ 
++    @Override
++    public int hashCode() {
++        int h = algorithm.hashCode();
++        for (Map.Entry<String, byte[]> e : nameToHash.entrySet()) {
++            h = h * 31 + e.getKey().hashCode();
++            h = h * 31 + Arrays.hashCode(e.getValue());
++        }
++        return h;
++    }
++
++    @Override
++    public boolean equals(Object obj) {
++        if (!(obj instanceof ModuleHashes))
++            return false;
++        ModuleHashes other = (ModuleHashes) obj;
++        if (!algorithm.equals(other.algorithm)
++                || nameToHash.size() != other.nameToHash.size())
++            return false;
++        for (Map.Entry<String, byte[]> e : nameToHash.entrySet()) {
++            String name = e.getKey();
++            byte[] hash = e.getValue();
++            if (!Arrays.equals(hash, other.nameToHash.get(name)))
++                return false;
++        }
++        return true;
++    }
++
++    @Override
++    public String toString() {
++        StringBuilder sb = new StringBuilder(algorithm);
++        sb.append(" ");
++        nameToHash.entrySet()
++                .stream()
++                .sorted(Map.Entry.comparingByKey())
++                .forEach(e -> {
++                    sb.append(e.getKey());
++                    sb.append("=");
++                    byte[] ba = e.getValue();
++                    for (byte b : ba) {
++                        sb.append(String.format("%02x", b & 0xff));
++                    }
++                });
++        return sb.toString();
++    }
++
+     /**
+      * This is used by jdk.internal.module.SystemModules class
+      * generated at link time.
+diff -ru orig/jdk-3cc80be736f2/src/java.base/share/classes/jdk/internal/module/ModuleInfoExtender.java jdk-3cc80be736f2/src/java.base/share/classes/jdk/internal/module/ModuleInfoExtender.java
+--- orig/jdk-3cc80be736f2/src/java.base/share/classes/jdk/internal/module/ModuleInfoExtender.java	1970-01-01 01:00:01.000000000 +0100
++++ jdk-3cc80be736f2/src/java.base/share/classes/jdk/internal/module/ModuleInfoExtender.java	2022-04-12 16:43:12.967868689 +0200
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
++ * Copyright (c) 2014, 2020, Oracle and/or its affiliates. All rights reserved.
+  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+  *
+  * This code is free software; you can redistribute it and/or modify it
+diff -ru orig/jdk-3cc80be736f2/src/java.base/share/classes/jdk/internal/module/ModuleReferences.java jdk-3cc80be736f2/src/java.base/share/classes/jdk/internal/module/ModuleReferences.java
+--- orig/jdk-3cc80be736f2/src/java.base/share/classes/jdk/internal/module/ModuleReferences.java	1970-01-01 01:00:01.000000000 +0100
++++ jdk-3cc80be736f2/src/java.base/share/classes/jdk/internal/module/ModuleReferences.java	2022-04-12 16:43:12.971868797 +0200
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
++ * Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved.
+  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+  *
+  * This code is free software; you can redistribute it and/or modify it
+@@ -95,7 +95,7 @@
+                                         Path file) {
+         URI uri = file.toUri();
+         Supplier<ModuleReader> supplier = () -> new JarModuleReader(file, uri);
+-        HashSupplier hasher = (a) -> ModuleHashes.computeHash(file, a);
++        HashSupplier hasher = (a) -> ModuleHashes.computeHash(supplier, a);
+         return newModule(attrs, uri, supplier, patcher, hasher);
+     }
+ 
+@@ -105,7 +105,7 @@
+     static ModuleReference newJModModule(ModuleInfo.Attributes attrs, Path file) {
+         URI uri = file.toUri();
+         Supplier<ModuleReader> supplier = () -> new JModModuleReader(file, uri);
+-        HashSupplier hasher = (a) -> ModuleHashes.computeHash(file, a);
++        HashSupplier hasher = (a) -> ModuleHashes.computeHash(supplier, a);
+         return newModule(attrs, uri, supplier, null, hasher);
+     }
+ 
diff --git a/gnu/packages/patches/openjdk-10-module3-reproducibility.patch b/gnu/packages/patches/openjdk-10-module3-reproducibility.patch
new file mode 100644
index 0000000000..bc54803bea
--- /dev/null
+++ b/gnu/packages/patches/openjdk-10-module3-reproducibility.patch
@@ -0,0 +1,34 @@
+Danny wrote.
+
+--- orig/jdk-3cc80be736f2/src/java.base/share/classes/java/lang/module/ModuleDescriptor.java	1970-01-01 01:00:01.000000000 +0100
++++ jdk-3cc80be736f2/src/java.base/share/classes/java/lang/module/ModuleDescriptor.java	2022-04-13 17:30:37.242775977 +0200
+@@ -43,6 +43,7 @@
+ import java.util.Objects;
+ import java.util.Optional;
+ import java.util.Set;
++import java.util.TreeSet;
+ import java.util.function.Supplier;
+ import java.util.stream.Collectors;
+ import java.util.stream.Stream;
+@@ -2155,9 +2156,9 @@
+          * @return The module descriptor
+          */
+         public ModuleDescriptor build() {
+-            Set<Requires> requires = new HashSet<>(this.requires.values());
+-            Set<Exports> exports = new HashSet<>(this.exports.values());
+-            Set<Opens> opens = new HashSet<>(this.opens.values());
++            Set<Requires> requires = new TreeSet<>(this.requires.values());
++            Set<Exports> exports = new TreeSet<>(this.exports.values());
++            Set<Opens> opens = new TreeSet<>(this.opens.values());
+ 
+             // add dependency on java.base
+             if (strict
+@@ -2169,7 +2170,7 @@
+                                           null));
+             }
+ 
+-            Set<Provides> provides = new HashSet<>(this.provides.values());
++            Set<Provides> provides = new TreeSet<>(this.provides.values());
+ 
+             return new ModuleDescriptor(name,
+                                         version,
diff --git a/gnu/packages/patches/openjdk-10-module4-reproducibility.patch b/gnu/packages/patches/openjdk-10-module4-reproducibility.patch
new file mode 100644
index 0000000000..051c9344eb
--- /dev/null
+++ b/gnu/packages/patches/openjdk-10-module4-reproducibility.patch
@@ -0,0 +1,14 @@
+Danny wrote it
+
+--- orig/jdk-6fa770f9f8ab/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/SystemModulesPlugin.java	2022-04-13 19:24:12.655749459 +0200
++++ jdk-6fa770f9f8ab/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/SystemModulesPlugin.java	2022-04-14 01:53:23.555465018 +0200
+@@ -861,7 +861,8 @@
+          */
+         private void genModuleReads(ClassWriter cw, Configuration cf) {
+             // module name -> names of modules that it reads
+-            Map<String, Set<String>> map = cf.modules().stream()
++            Map<String, Set<String>> map = cf.modules().stream()
++                    .sorted(java.util.Comparator.comparing(ResolvedModule::name))
+                     .collect(Collectors.toMap(
+                             ResolvedModule::name,
+                             m -> m.reads().stream()
-- 
2.39.2





Information forwarded to guix-patches <at> gnu.org:
bug#55751; Package guix-patches. (Mon, 31 Jul 2023 18:11:02 GMT) Full text and rfc822 format available.

Message #56 received at 55751 <at> debbugs.gnu.org (full text, mbox):

From: Danny Milosavljevic <dannym <at> scratchpost.org>
To: 55751 <at> debbugs.gnu.org
Cc: Danny Milosavljevic <dannym <at> scratchpost.org>
Subject: [PATCH v2 3/7] gnu: openjdk11: Make more reproducible.
Date: Mon, 31 Jul 2023 20:09:15 +0200
* gnu/packages/java.scm (openjdk11)[source]: Add patches.
[arguments]<#:phases>[remove-timestamping]: Add phase.
* gnu/packages/patches/openjdk-11-classlist-reproducibility.patch: New file.
* gnu/local.mk (dist_patch_DATA): Add patches.
---
 gnu/local.mk                                  |  1 +
 gnu/packages/java.scm                         | 21 ++++++++++++++++++-
 ...openjdk-11-classlist-reproducibility.patch | 11 ++++++++++
 3 files changed, 32 insertions(+), 1 deletion(-)
 create mode 100644 gnu/packages/patches/openjdk-11-classlist-reproducibility.patch

diff --git a/gnu/local.mk b/gnu/local.mk
index 791e5a85aa..715e958248 100644
--- a/gnu/local.mk
+++ b/gnu/local.mk
@@ -1675,6 +1675,7 @@ dist_patch_DATA =						\
   %D%/packages/patches/openjdk-10-module4-reproducibility.patch	\
   %D%/packages/patches/openjdk-10-pointer-comparison.patch      \
   %D%/packages/patches/openjdk-10-setsignalhandler.patch        \
+  %D%/packages/patches/openjdk-11-classlist-reproducibility.patch	\
   %D%/packages/patches/openjdk-15-xcursor-no-dynamic.patch	\
   %D%/packages/patches/openmpi-mtl-priorities.patch		\
   %D%/packages/patches/openmw-assume-nonconst-SIGSTKSZ.patch    \
diff --git a/gnu/packages/java.scm b/gnu/packages/java.scm
index 14e9b1f653..9ffd0dce7e 100644
--- a/gnu/packages/java.scm
+++ b/gnu/packages/java.scm
@@ -1172,7 +1172,17 @@ (define-public openjdk11
                 "1prvqy0ysz0999wrhsrbz6vrknpqfihl9l74l16ph93g89dqi5ia"))
               (modules '((guix build utils)))
               (snippet
-               '(for-each delete-file (find-files "." "\\.(bin|exe|jar)$")))))
+               '(for-each delete-file (find-files "." "\\.(bin|exe|jar)$")))
+              (patches
+               (search-patches ;"openjdk-10-module-reproducibility.patch"
+                        "openjdk-10-module3-reproducibility.patch"
+                        "openjdk-10-module4-reproducibility.patch"
+                        "openjdk-10-char-reproducibility.patch"
+                        "openjdk-11-classlist-reproducibility.patch"
+                        ;"openjdk-10-corba-reproducibility.patch"
+                        ;"openjdk-10-idlj-reproducibility.patch"
+                        "openjdk-10-jar-reproducibility.patch"
+                        "openjdk-10-jtask-reproducibility.patch"))))
     (build-system gnu-build-system)
     (outputs '("out" "jdk" "doc"))
     (arguments
@@ -1205,6 +1215,10 @@ (define-public openjdk11
          "--with-libjpeg=system"
          "--with-libpng=system"
          "--with-version-pre="
+         ;; should be set by SOURCE_DATE_EPOCH handler, but
+         ;; isn't being set. So manually do it.
+         "--with-hotspot-build-time=1970-01-01T00:00:01"
+         "--enable-reproducible-build" ; to be sure
          ;; Allow the build system to locate the system freetype.
          (string-append "--with-freetype-include="
                         #$(this-package-input "freetype") "/include")
@@ -1218,6 +1232,11 @@ (define-public openjdk11
               ;; this exact first line.
               (substitute* "make/data/blockedcertsconverter/blocked.certs.pem"
                 (("^#!.*") "#! java BlockedCertsConverter SHA-256\n"))))
+          (add-after 'unpack 'remove-timestamping
+            (lambda _
+              (substitute* "src/hotspot/share/runtime/abstract_vm_version.cpp"
+               (("__DATE__") "")
+               (("__TIME__") ""))))
           (add-after 'unpack 'patch-jni-libs
             ;; Hardcode dynamically loaded libraries.
             (lambda _
diff --git a/gnu/packages/patches/openjdk-11-classlist-reproducibility.patch b/gnu/packages/patches/openjdk-11-classlist-reproducibility.patch
new file mode 100644
index 0000000000..2ac7c2b664
--- /dev/null
+++ b/gnu/packages/patches/openjdk-11-classlist-reproducibility.patch
@@ -0,0 +1,11 @@
+--- jdk-11.0.13-ga/make/GenerateLinkOptData.gmk.orig	2022-04-04 17:18:56.801929954 +0200
++++ jdk-11.0.13-ga/make/GenerateLinkOptData.gmk	2022-04-04 17:19:14.962422622 +0200
+@@ -66,7 +66,7 @@
+ 	    -cp $(SUPPORT_OUTPUTDIR)/classlist.jar \
+ 	    build.tools.classlist.HelloClasslist \
+ 	    $(LOG_DEBUG) 2>&1 > $(JLI_TRACE_FILE)
+-	$(GREP) -v HelloClasslist $@.raw > $@
++	$(GREP) -v HelloClasslist $@.raw |sort > $@
+ 
+ # The jli trace is created by the same recipe as classlist. By declaring these
+ # dependencies, make will correctly rebuild both jli trace and classlist
-- 
2.39.2





Information forwarded to guix-patches <at> gnu.org:
bug#55751; Package guix-patches. (Mon, 31 Jul 2023 18:11:03 GMT) Full text and rfc822 format available.

Message #59 received at 55751 <at> debbugs.gnu.org (full text, mbox):

From: Danny Milosavljevic <dannym <at> scratchpost.org>
To: 55751 <at> debbugs.gnu.org
Cc: Danny Milosavljevic <dannym <at> scratchpost.org>
Subject: [PATCH v2 4/7] gnu: openjdk12: Make reproducible.
Date: Mon, 31 Jul 2023 20:09:16 +0200
* gnu/packages/java.scm (openjdk12)[arguments]<#:phases>[remove-timestamping]:
Modify phase.
---
 gnu/packages/java.scm | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/gnu/packages/java.scm b/gnu/packages/java.scm
index 9ffd0dce7e..66dcc5023e 100644
--- a/gnu/packages/java.scm
+++ b/gnu/packages/java.scm
@@ -1510,6 +1510,11 @@ (define-public openjdk12
     (substitute-keyword-arguments (package-arguments openjdk11)
       ((#:phases phases)
        #~(modify-phases #$phases
+           (replace 'remove-timestamping
+             (lambda _
+               (substitute* "src/hotspot/share/runtime/vm_version.cpp"
+                (("__DATE__") "")
+                (("__TIME__") ""))))
            (replace 'fix-java-shebangs
              (lambda _
                ;; 'blocked' was renamed to 'blacklisted' in this version for
-- 
2.39.2





Information forwarded to guix-patches <at> gnu.org:
bug#55751; Package guix-patches. (Mon, 31 Jul 2023 18:11:03 GMT) Full text and rfc822 format available.

Message #62 received at 55751 <at> debbugs.gnu.org (full text, mbox):

From: Danny Milosavljevic <dannym <at> scratchpost.org>
To: 55751 <at> debbugs.gnu.org
Cc: Danny Milosavljevic <dannym <at> scratchpost.org>
Subject: [PATCH v2 5/7] gnu: openjdk13: Make reproducible.
Date: Mon, 31 Jul 2023 20:09:17 +0200
* gnu/packages/patches/openjdk-13-classlist-reproducibility.patch: New file.
* gnu/local.mk (dist_patch_DATA): Add patch.
* gnu/packages/java.scm (openjdk13)[source]: Add patch.
[arguments]<#:phases>[remove-timestamping]: Modify phase.
---
 gnu/local.mk                                    |  1 +
 gnu/packages/java.scm                           | 17 ++++++++++++++---
 .../openjdk-13-classlist-reproducibility.patch  | 11 +++++++++++
 3 files changed, 26 insertions(+), 3 deletions(-)
 create mode 100644 gnu/packages/patches/openjdk-13-classlist-reproducibility.patch

diff --git a/gnu/local.mk b/gnu/local.mk
index 715e958248..7956b57669 100644
--- a/gnu/local.mk
+++ b/gnu/local.mk
@@ -1676,6 +1676,7 @@ dist_patch_DATA =						\
   %D%/packages/patches/openjdk-10-pointer-comparison.patch      \
   %D%/packages/patches/openjdk-10-setsignalhandler.patch        \
   %D%/packages/patches/openjdk-11-classlist-reproducibility.patch	\
+  %D%/packages/patches/openjdk-13-classlist-reproducibility.patch	\
   %D%/packages/patches/openjdk-15-xcursor-no-dynamic.patch	\
   %D%/packages/patches/openmpi-mtl-priorities.patch		\
   %D%/packages/patches/openmw-assume-nonconst-SIGSTKSZ.patch    \
diff --git a/gnu/packages/java.scm b/gnu/packages/java.scm
index 66dcc5023e..d7cad12bf1 100644
--- a/gnu/packages/java.scm
+++ b/gnu/packages/java.scm
@@ -1527,9 +1527,20 @@ (define-public openjdk12
 (define-public openjdk13
   (make-openjdk openjdk12 "13.0.13"
                 "0pxf4dlig61k0pg7amg4mi919hzam7nzwckry01avgq1wj8ambji"
-  (source (origin
-            (inherit (package-source base))
-            (patches '())))))
+   (source (origin
+             (inherit (package-source base))
+             (patches (search-patches "openjdk-13-classlist-reproducibility.patch"
+                                      "openjdk-10-jtask-reproducibility.patch"))))
+   (arguments
+    (substitute-keyword-arguments (package-arguments openjdk12)
+      ((#:phases phases)
+       #~(modify-phases #$phases
+           (replace 'remove-timestamping
+             (lambda _
+               (substitute*
+                "src/hotspot/share/runtime/abstract_vm_version.cpp"
+                (("__DATE__") "")
+                (("__TIME__") ""))))))))))
 
 (define-public openjdk14
   (make-openjdk
diff --git a/gnu/packages/patches/openjdk-13-classlist-reproducibility.patch b/gnu/packages/patches/openjdk-13-classlist-reproducibility.patch
new file mode 100644
index 0000000000..326f6875ec
--- /dev/null
+++ b/gnu/packages/patches/openjdk-13-classlist-reproducibility.patch
@@ -0,0 +1,11 @@
+--- 6cllxkf0narh0b4wgx8npwjkznd7ifq0-openjdk-13.0.7-checkout/make/GenerateLinkOptData.gmk.orig	2022-04-04 17:20:33.012539984 +0200
++++ 6cllxkf0narh0b4wgx8npwjkznd7ifq0-openjdk-13.0.7-checkout/make/GenerateLinkOptData.gmk	2022-04-04 17:20:51.181032859 +0200
+@@ -78,7 +78,7 @@
+ 	        $(CAT) $(LINK_OPT_DIR)/stderr $(JLI_TRACE_FILE) ; \
+ 	        exit $$exitcode \
+ 	    )
+-	$(GREP) -v HelloClasslist $@.raw > $@
++	$(GREP) -v HelloClasslist $@.raw | sort > $@
+ 
+ # The jli trace is created by the same recipe as classlist. By declaring these
+ # dependencies, make will correctly rebuild both jli trace and classlist
-- 
2.39.2





Information forwarded to guix-patches <at> gnu.org:
bug#55751; Package guix-patches. (Mon, 31 Jul 2023 18:11:04 GMT) Full text and rfc822 format available.

Message #65 received at 55751 <at> debbugs.gnu.org (full text, mbox):

From: Danny Milosavljevic <dannym <at> scratchpost.org>
To: 55751 <at> debbugs.gnu.org
Cc: Danny Milosavljevic <dannym <at> scratchpost.org>
Subject: [PATCH v2 6/7] gnu: openjdk14: Make reproducible.
Date: Mon, 31 Jul 2023 20:09:18 +0200
* gnu/packages/java.scm (openjdk14)[source]: Add patches.
---
 gnu/packages/java.scm | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/gnu/packages/java.scm b/gnu/packages/java.scm
index d7cad12bf1..d4176f1375 100644
--- a/gnu/packages/java.scm
+++ b/gnu/packages/java.scm
@@ -1555,7 +1555,9 @@ (define-public openjdk14
                  (substitute* "make/autoconf/basics.m4"
                    (("if help") "if command -v"))
                  (for-each delete-file (find-files "." "\\.(bin|exe|jar)$"))))
-             (patches (search-patches "openjdk-10-setsignalhandler.patch"))))))
+             (patches (search-patches "openjdk-10-setsignalhandler.patch"
+                                      "openjdk-10-jtask-reproducibility.patch"
+                                      "openjdk-13-classlist-reproducibility.patch"))))))
 
 (define-public openjdk15
   (make-openjdk
-- 
2.39.2





Information forwarded to guix-patches <at> gnu.org:
bug#55751; Package guix-patches. (Mon, 31 Jul 2023 18:11:04 GMT) Full text and rfc822 format available.

Message #68 received at 55751 <at> debbugs.gnu.org (full text, mbox):

From: Danny Milosavljevic <dannym <at> scratchpost.org>
To: 55751 <at> debbugs.gnu.org
Cc: Danny Milosavljevic <dannym <at> scratchpost.org>
Subject: [PATCH v2 7/7] gnu: openjdk15: Make reproducible.
Date: Mon, 31 Jul 2023 20:09:19 +0200
* gnu/packages/java.scm (openjdk15)[source]: Add patch.
---
 gnu/packages/java.scm                         |  3 +-
 .../openjdk-15-jtask-reproducibility.patch    | 40 +++++++++++++++++++
 2 files changed, 42 insertions(+), 1 deletion(-)
 create mode 100644 gnu/packages/patches/openjdk-15-jtask-reproducibility.patch

diff --git a/gnu/packages/java.scm b/gnu/packages/java.scm
index d4176f1375..a8aaedb8af 100644
--- a/gnu/packages/java.scm
+++ b/gnu/packages/java.scm
@@ -1568,7 +1568,8 @@ (define-public openjdk15
              (modules '())
              (snippet #f)
              (patches
-              (search-patches "openjdk-15-xcursor-no-dynamic.patch"))))
+              (search-patches "openjdk-15-jtask-reproducibility.patch"
+                              "openjdk-15-xcursor-no-dynamic.patch"))))
    (inputs
     (modify-inputs (package-inputs base)
       (append libxcursor)))             ;for our patch to work
diff --git a/gnu/packages/patches/openjdk-15-jtask-reproducibility.patch b/gnu/packages/patches/openjdk-15-jtask-reproducibility.patch
new file mode 100644
index 0000000000..2052983ade
--- /dev/null
+++ b/gnu/packages/patches/openjdk-15-jtask-reproducibility.patch
@@ -0,0 +1,40 @@
+--- 22kjr9lzrml0h5m55viq7zlfkqr9p7ny-openjdk-15.0.3-checkout/src/jdk.jlink/share/classes/jdk/tools/jmod/JmodTask.java.orig	2022-04-04 10:57:40.346312924 +0200
++++ 22kjr9lzrml0h5m55viq7zlfkqr9p7ny-openjdk-15.0.3-checkout/src/jdk.jlink/share/classes/jdk/tools/jmod/JmodTask.java	2022-04-04 11:01:38.480751902 +0200
+@@ -82,6 +82,7 @@
+ import jdk.internal.module.ModuleTarget;
+ import jdk.internal.module.Resources;
+ import jdk.tools.jlink.internal.Utils;
++import java.util.TreeSet;
+ 
+ import static java.util.stream.Collectors.joining;
+ 
+@@ -750,6 +751,7 @@
+         void processSection(JmodOutputStream out, Section section, Path path)
+             throws IOException
+         {
++            TreeSet<Path> paths = new TreeSet<>();
+             Files.walkFileTree(path, Set.of(FileVisitOption.FOLLOW_LINKS),
+                 Integer.MAX_VALUE, new SimpleFileVisitor<Path>() {
+                     @Override
+@@ -765,14 +767,18 @@
+                             if (out.contains(section, name)) {
+                                 warning("warn.ignore.duplicate.entry", name, section);
+                             } else {
+-                                try (InputStream in = Files.newInputStream(file)) {
+-                                    out.writeEntry(in, section, name);
+-                                }
++                                paths.add(file);
+                             }
+                         }
+                         return FileVisitResult.CONTINUE;
+                     }
+                 });
++
++            for (Path file : paths) {
++                try (InputStream in = Files.newInputStream(file)) {
++                    out.writeEntry(in, section, path.relativize(file).toString());
++                }
++            }
+         }
+ 
+         boolean matches(Path path, List<PathMatcher> matchers) {
-- 
2.39.2





Information forwarded to guix-patches <at> gnu.org:
bug#55751; Package guix-patches. (Sun, 21 Jan 2024 05:23:02 GMT) Full text and rfc822 format available.

Message #71 received at 55751 <at> debbugs.gnu.org (full text, mbox):

From: Maxim Cournoyer <maxim.cournoyer <at> gmail.com>
To: Danny Milosavljevic <dannym <at> scratchpost.org>
Cc: 55751 <at> debbugs.gnu.org
Subject: Re: [bug#55751] [PATCH v2 7/7] gnu: openjdk15: Make reproducible.
Date: Sun, 21 Jan 2024 00:22:44 -0500
Hello!

Danny Milosavljevic <dannym <at> scratchpost.org> writes:

> * gnu/packages/java.scm (openjdk15)[source]: Add patch.
> ---
>  gnu/packages/java.scm                         |  3 +-
>  .../openjdk-15-jtask-reproducibility.patch    | 40 +++++++++++++++++++
>  2 files changed, 42 insertions(+), 1 deletion(-)
>  create mode 100644 gnu/packages/patches/openjdk-15-jtask-reproducibility.patch

I've queued your work for core-updates.  Thank you!

-- 
Thanks,
Maxim




Reply sent to Vagrant Cascadian <vagrant <at> reproducible-builds.org>:
You have taken responsibility. (Thu, 24 Oct 2024 18:40:01 GMT) Full text and rfc822 format available.

Notification sent to dannym <at> scratchpost.org:
bug acknowledged by developer. (Thu, 24 Oct 2024 18:40:02 GMT) Full text and rfc822 format available.

Message #76 received at 55751-done <at> debbugs.gnu.org (full text, mbox):

From: Vagrant Cascadian <vagrant <at> reproducible-builds.org>
To: Maxim Cournoyer <maxim.cournoyer <at> gmail.com>, Danny Milosavljevic
 <dannym <at> scratchpost.org>
Cc: 55751-done <at> debbugs.gnu.org
Subject: Re: [bug#55751] [PATCH v2 7/7] gnu: openjdk15: Make reproducible.
Date: Thu, 24 Oct 2024 11:38:09 -0700
[Message part 1 (text/plain, inline)]
On 2024-01-21, Maxim Cournoyer wrote:
> Danny Milosavljevic <dannym <at> scratchpost.org> writes:
>
>> * gnu/packages/java.scm (openjdk15)[source]: Add patch.
>> ---
>>  gnu/packages/java.scm                         |  3 +-
>>  .../openjdk-15-jtask-reproducibility.patch    | 40 +++++++++++++++++++
>>  2 files changed, 42 insertions(+), 1 deletion(-)
>>  create mode 100644 gnu/packages/patches/openjdk-15-jtask-reproducibility.patch
>
> I've queued your work for core-updates.  Thank you!

This series appears to be present in guix master as:

3c8ca6b26bee110c4bcfbc6aaa7d4805b1915fc8 gnu: openjdk15: Make reproducible.
dbce2fc28728721c0ac81929799d55deae6b0ab5 gnu: openjdk14: Make reproducible.
5996fb5b0c7ce7ca6b1552308199effa66cbcf6a gnu: openjdk13: Make reproducible.
d109a7322c0597b4f265df93061886984fca9037 gnu: openjdk12: Make reproducible.
edf8fc9a485298e9bdb3793221c75d0a4a18177d gnu: openjdk11: Make more reproducible.
48ea1a2b3b8bc4c8b2247972401ab5a6f7f4ecc7 gnu: openjdk10: Make more reproducible.
2f1daa35746c896cd59882383c236ee97a3cbad7 gnu: openjdk9: Make build reproducible.

Marking as done!

live well,
  vagrant
[signature.asc (application/pgp-signature, inline)]

This bug report was last modified 25 days ago.

Previous Next


GNU bug tracking system
Copyright (C) 1999 Darren O. Benham, 1997,2003 nCipher Corporation Ltd, 1994-97 Ian Jackson.