all messages for Guix-related lists mirrored at yhetil.org
 help / color / mirror / code / Atom feed
* [bug#55751] [PATCH 0/8] Towards reproducible openjdk
@ 2022-06-01 12:57 dannym
  2022-06-01 13:00 ` [bug#55751] [PATCH 1/8] gnu: openjdk9: Make build reproducible dannym
                   ` (9 more replies)
  0 siblings, 10 replies; 24+ messages in thread
From: dannym @ 2022-06-01 12:57 UTC (permalink / raw)
  To: 55751; +Cc: Danny Milosavljevic

From: Danny Milosavljevic <dannym@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





^ permalink raw reply	[flat|nested] 24+ messages in thread

* [bug#55751] [PATCH 1/8] gnu: openjdk9: Make build reproducible.
  2022-06-01 12:57 [bug#55751] [PATCH 0/8] Towards reproducible openjdk dannym
@ 2022-06-01 13:00 ` dannym
  2022-06-01 13:12   ` Maxime Devos
                     ` (2 more replies)
  2022-06-01 13:00 ` [bug#55751] [PATCH 2/8] gnu: openjdk10: Make more reproducible dannym
                   ` (8 subsequent siblings)
  9 siblings, 3 replies; 24+ messages in thread
From: dannym @ 2022-06-01 13:00 UTC (permalink / raw)
  To: 55751; +Cc: Danny Milosavljevic

From: Danny Milosavljevic <dannym@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@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@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@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@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@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





^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [bug#55751] [PATCH 2/8] gnu: openjdk10: Make more reproducible.
  2022-06-01 12:57 [bug#55751] [PATCH 0/8] Towards reproducible openjdk dannym
  2022-06-01 13:00 ` [bug#55751] [PATCH 1/8] gnu: openjdk9: Make build reproducible dannym
@ 2022-06-01 13:00 ` dannym
  2022-06-01 13:00 ` [bug#55751] [PATCH 3/8] gnu: openjdk11: " dannym
                   ` (7 subsequent siblings)
  9 siblings, 0 replies; 24+ messages in thread
From: dannym @ 2022-06-01 13:00 UTC (permalink / raw)
  To: 55751; +Cc: Danny Milosavljevic

From: Danny Milosavljevic <dannym@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@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





^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [bug#55751] [PATCH 3/8] gnu: openjdk11: Make more reproducible.
  2022-06-01 12:57 [bug#55751] [PATCH 0/8] Towards reproducible openjdk dannym
  2022-06-01 13:00 ` [bug#55751] [PATCH 1/8] gnu: openjdk9: Make build reproducible dannym
  2022-06-01 13:00 ` [bug#55751] [PATCH 2/8] gnu: openjdk10: Make more reproducible dannym
@ 2022-06-01 13:00 ` dannym
  2022-06-01 13:00 ` [bug#55751] [PATCH 4/8] gnu: openjdk12: Make reproducible dannym
                   ` (6 subsequent siblings)
  9 siblings, 0 replies; 24+ messages in thread
From: dannym @ 2022-06-01 13:00 UTC (permalink / raw)
  To: 55751; +Cc: Danny Milosavljevic

From: Danny Milosavljevic <dannym@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





^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [bug#55751] [PATCH 4/8] gnu: openjdk12: Make reproducible.
  2022-06-01 12:57 [bug#55751] [PATCH 0/8] Towards reproducible openjdk dannym
                   ` (2 preceding siblings ...)
  2022-06-01 13:00 ` [bug#55751] [PATCH 3/8] gnu: openjdk11: " dannym
@ 2022-06-01 13:00 ` dannym
  2022-06-01 13:00 ` [bug#55751] [PATCH 5/8] gnu: openjdk13: " dannym
                   ` (5 subsequent siblings)
  9 siblings, 0 replies; 24+ messages in thread
From: dannym @ 2022-06-01 13:00 UTC (permalink / raw)
  To: 55751; +Cc: Danny Milosavljevic

From: Danny Milosavljevic <dannym@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





^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [bug#55751] [PATCH 5/8] gnu: openjdk13: Make reproducible.
  2022-06-01 12:57 [bug#55751] [PATCH 0/8] Towards reproducible openjdk dannym
                   ` (3 preceding siblings ...)
  2022-06-01 13:00 ` [bug#55751] [PATCH 4/8] gnu: openjdk12: Make reproducible dannym
@ 2022-06-01 13:00 ` dannym
  2022-06-01 13:00 ` [bug#55751] [PATCH 6/8] gnu: openjdk14: " dannym
                   ` (4 subsequent siblings)
  9 siblings, 0 replies; 24+ messages in thread
From: dannym @ 2022-06-01 13:00 UTC (permalink / raw)
  To: 55751; +Cc: Danny Milosavljevic

From: Danny Milosavljevic <dannym@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





^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [bug#55751] [PATCH 6/8] gnu: openjdk14: Make reproducible.
  2022-06-01 12:57 [bug#55751] [PATCH 0/8] Towards reproducible openjdk dannym
                   ` (4 preceding siblings ...)
  2022-06-01 13:00 ` [bug#55751] [PATCH 5/8] gnu: openjdk13: " dannym
@ 2022-06-01 13:00 ` dannym
  2022-06-01 13:00 ` [bug#55751] [PATCH 7/8] gnu: openjdk15: " dannym
                   ` (3 subsequent siblings)
  9 siblings, 0 replies; 24+ messages in thread
From: dannym @ 2022-06-01 13:00 UTC (permalink / raw)
  To: 55751; +Cc: Danny Milosavljevic

From: Danny Milosavljevic <dannym@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





^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [bug#55751] [PATCH 7/8] gnu: openjdk15: Make reproducible.
  2022-06-01 12:57 [bug#55751] [PATCH 0/8] Towards reproducible openjdk dannym
                   ` (5 preceding siblings ...)
  2022-06-01 13:00 ` [bug#55751] [PATCH 6/8] gnu: openjdk14: " dannym
@ 2022-06-01 13:00 ` dannym
  2022-06-01 13:00 ` [bug#55751] [PATCH 8/8] gnu: openjdk16: " dannym
                   ` (2 subsequent siblings)
  9 siblings, 0 replies; 24+ messages in thread
From: dannym @ 2022-06-01 13:00 UTC (permalink / raw)
  To: 55751; +Cc: Danny Milosavljevic

From: Danny Milosavljevic <dannym@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





^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [bug#55751] [PATCH 8/8] gnu: openjdk16: Make reproducible.
  2022-06-01 12:57 [bug#55751] [PATCH 0/8] Towards reproducible openjdk dannym
                   ` (6 preceding siblings ...)
  2022-06-01 13:00 ` [bug#55751] [PATCH 7/8] gnu: openjdk15: " dannym
@ 2022-06-01 13:00 ` dannym
  2022-06-01 13:20 ` [bug#55751] [PATCH 0/8] Towards reproducible openjdk Maxime Devos
  2023-07-31 18:09 ` [bug#55751] [PATCH v2 0/7] " Danny Milosavljevic
  9 siblings, 0 replies; 24+ messages in thread
From: dannym @ 2022-06-01 13:00 UTC (permalink / raw)
  To: 55751; +Cc: Danny Milosavljevic

From: Danny Milosavljevic <dannym@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





^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [bug#55751] [PATCH 1/8] gnu: openjdk9: Make build reproducible.
  2022-06-01 13:00 ` [bug#55751] [PATCH 1/8] gnu: openjdk9: Make build reproducible dannym
@ 2022-06-01 13:12   ` Maxime Devos
  2022-06-01 13:14   ` Maxime Devos
  2022-06-01 13:18   ` Maxime Devos
  2 siblings, 0 replies; 24+ messages in thread
From: Maxime Devos @ 2022-06-01 13:12 UTC (permalink / raw)
  To: dannym, 55751

[-- Attachment #1: Type: text/plain, Size: 476 bytes --]

dannym@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;



[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 260 bytes --]

^ permalink raw reply	[flat|nested] 24+ messages in thread

* [bug#55751] [PATCH 1/8] gnu: openjdk9: Make build reproducible.
  2022-06-01 13:00 ` [bug#55751] [PATCH 1/8] gnu: openjdk9: Make build reproducible dannym
  2022-06-01 13:12   ` Maxime Devos
@ 2022-06-01 13:14   ` Maxime Devos
  2022-06-01 13:18   ` Maxime Devos
  2 siblings, 0 replies; 24+ messages in thread
From: Maxime Devos @ 2022-06-01 13:14 UTC (permalink / raw)
  To: dannym, 55751

[-- Attachment #1: Type: text/plain, Size: 544 bytes --]

dannym@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@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.

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 260 bytes --]

^ permalink raw reply	[flat|nested] 24+ messages in thread

* [bug#55751] [PATCH 1/8] gnu: openjdk9: Make build reproducible.
  2022-06-01 13:00 ` [bug#55751] [PATCH 1/8] gnu: openjdk9: Make build reproducible dannym
  2022-06-01 13:12   ` Maxime Devos
  2022-06-01 13:14   ` Maxime Devos
@ 2022-06-01 13:18   ` Maxime Devos
  2022-09-21 20:18     ` Danny Milosavljevic
  2 siblings, 1 reply; 24+ messages in thread
From: Maxime Devos @ 2022-06-01 13:18 UTC (permalink / raw)
  To: dannym, 55751

[-- Attachment #1: Type: text/plain, Size: 1495 bytes --]

dannym@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.

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 260 bytes --]

^ permalink raw reply	[flat|nested] 24+ messages in thread

* [bug#55751] [PATCH 0/8] Towards reproducible openjdk
  2022-06-01 12:57 [bug#55751] [PATCH 0/8] Towards reproducible openjdk dannym
                   ` (7 preceding siblings ...)
  2022-06-01 13:00 ` [bug#55751] [PATCH 8/8] gnu: openjdk16: " dannym
@ 2022-06-01 13:20 ` Maxime Devos
  2023-07-31 18:09 ` [bug#55751] [PATCH v2 0/7] " Danny Milosavljevic
  9 siblings, 0 replies; 24+ messages in thread
From: Maxime Devos @ 2022-06-01 13:20 UTC (permalink / raw)
  To: dannym, 55751

dannym@scratchpost.org schreef op wo 01-06-2022 om 14:57 [+0200]:
> From: Danny Milosavljevic <dannym@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.





^ permalink raw reply	[flat|nested] 24+ messages in thread

* [bug#55751] [PATCH 1/8] gnu: openjdk9: Make build reproducible.
  2022-06-01 13:18   ` Maxime Devos
@ 2022-09-21 20:18     ` Danny Milosavljevic
  0 siblings, 0 replies; 24+ messages in thread
From: Danny Milosavljevic @ 2022-09-21 20:18 UTC (permalink / raw)
  To: Maxime Devos; +Cc: 55751

[-- Attachment #1: Type: text/plain, Size: 1872 bytes --]

Hi,

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

> dannym@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).

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 24+ messages in thread

* [bug#55751] [PATCH v2 0/7] Towards reproducible openjdk
  2022-06-01 12:57 [bug#55751] [PATCH 0/8] Towards reproducible openjdk dannym
                   ` (8 preceding siblings ...)
  2022-06-01 13:20 ` [bug#55751] [PATCH 0/8] Towards reproducible openjdk Maxime Devos
@ 2023-07-31 18:09 ` Danny Milosavljevic
  2023-07-31 18:09   ` [bug#55751] [PATCH v2 1/7] gnu: openjdk9: Make build reproducible Danny Milosavljevic
                     ` (6 more replies)
  9 siblings, 7 replies; 24+ messages in thread
From: Danny Milosavljevic @ 2023-07-31 18:09 UTC (permalink / raw)
  To: 55751; +Cc: Danny Milosavljevic

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





^ permalink raw reply	[flat|nested] 24+ messages in thread

* [bug#55751] [PATCH v2 1/7] gnu: openjdk9: Make build reproducible.
  2023-07-31 18:09 ` [bug#55751] [PATCH v2 0/7] " Danny Milosavljevic
@ 2023-07-31 18:09   ` Danny Milosavljevic
  2023-07-31 18:09   ` [bug#55751] [PATCH v2 2/7] gnu: openjdk10: Make more reproducible Danny Milosavljevic
                     ` (5 subsequent siblings)
  6 siblings, 0 replies; 24+ messages in thread
From: Danny Milosavljevic @ 2023-07-31 18:09 UTC (permalink / raw)
  To: 55751; +Cc: Danny Milosavljevic

* 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@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@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@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@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@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





^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [bug#55751] [PATCH v2 2/7] gnu: openjdk10: Make more reproducible.
  2023-07-31 18:09 ` [bug#55751] [PATCH v2 0/7] " Danny Milosavljevic
  2023-07-31 18:09   ` [bug#55751] [PATCH v2 1/7] gnu: openjdk9: Make build reproducible Danny Milosavljevic
@ 2023-07-31 18:09   ` Danny Milosavljevic
  2023-07-31 18:09   ` [bug#55751] [PATCH v2 3/7] gnu: openjdk11: " Danny Milosavljevic
                     ` (4 subsequent siblings)
  6 siblings, 0 replies; 24+ messages in thread
From: Danny Milosavljevic @ 2023-07-31 18:09 UTC (permalink / raw)
  To: 55751; +Cc: Danny Milosavljevic

* 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@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





^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [bug#55751] [PATCH v2 3/7] gnu: openjdk11: Make more reproducible.
  2023-07-31 18:09 ` [bug#55751] [PATCH v2 0/7] " Danny Milosavljevic
  2023-07-31 18:09   ` [bug#55751] [PATCH v2 1/7] gnu: openjdk9: Make build reproducible Danny Milosavljevic
  2023-07-31 18:09   ` [bug#55751] [PATCH v2 2/7] gnu: openjdk10: Make more reproducible Danny Milosavljevic
@ 2023-07-31 18:09   ` Danny Milosavljevic
  2023-07-31 18:09   ` [bug#55751] [PATCH v2 4/7] gnu: openjdk12: Make reproducible Danny Milosavljevic
                     ` (3 subsequent siblings)
  6 siblings, 0 replies; 24+ messages in thread
From: Danny Milosavljevic @ 2023-07-31 18:09 UTC (permalink / raw)
  To: 55751; +Cc: Danny Milosavljevic

* 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





^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [bug#55751] [PATCH v2 4/7] gnu: openjdk12: Make reproducible.
  2023-07-31 18:09 ` [bug#55751] [PATCH v2 0/7] " Danny Milosavljevic
                     ` (2 preceding siblings ...)
  2023-07-31 18:09   ` [bug#55751] [PATCH v2 3/7] gnu: openjdk11: " Danny Milosavljevic
@ 2023-07-31 18:09   ` Danny Milosavljevic
  2023-07-31 18:09   ` [bug#55751] [PATCH v2 5/7] gnu: openjdk13: " Danny Milosavljevic
                     ` (2 subsequent siblings)
  6 siblings, 0 replies; 24+ messages in thread
From: Danny Milosavljevic @ 2023-07-31 18:09 UTC (permalink / raw)
  To: 55751; +Cc: Danny Milosavljevic

* 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





^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [bug#55751] [PATCH v2 5/7] gnu: openjdk13: Make reproducible.
  2023-07-31 18:09 ` [bug#55751] [PATCH v2 0/7] " Danny Milosavljevic
                     ` (3 preceding siblings ...)
  2023-07-31 18:09   ` [bug#55751] [PATCH v2 4/7] gnu: openjdk12: Make reproducible Danny Milosavljevic
@ 2023-07-31 18:09   ` Danny Milosavljevic
  2023-07-31 18:09   ` [bug#55751] [PATCH v2 6/7] gnu: openjdk14: " Danny Milosavljevic
  2023-07-31 18:09   ` [bug#55751] [PATCH v2 7/7] gnu: openjdk15: " Danny Milosavljevic
  6 siblings, 0 replies; 24+ messages in thread
From: Danny Milosavljevic @ 2023-07-31 18:09 UTC (permalink / raw)
  To: 55751; +Cc: Danny Milosavljevic

* 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





^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [bug#55751] [PATCH v2 6/7] gnu: openjdk14: Make reproducible.
  2023-07-31 18:09 ` [bug#55751] [PATCH v2 0/7] " Danny Milosavljevic
                     ` (4 preceding siblings ...)
  2023-07-31 18:09   ` [bug#55751] [PATCH v2 5/7] gnu: openjdk13: " Danny Milosavljevic
@ 2023-07-31 18:09   ` Danny Milosavljevic
  2023-07-31 18:09   ` [bug#55751] [PATCH v2 7/7] gnu: openjdk15: " Danny Milosavljevic
  6 siblings, 0 replies; 24+ messages in thread
From: Danny Milosavljevic @ 2023-07-31 18:09 UTC (permalink / raw)
  To: 55751; +Cc: Danny Milosavljevic

* 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





^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [bug#55751] [PATCH v2 7/7] gnu: openjdk15: Make reproducible.
  2023-07-31 18:09 ` [bug#55751] [PATCH v2 0/7] " Danny Milosavljevic
                     ` (5 preceding siblings ...)
  2023-07-31 18:09   ` [bug#55751] [PATCH v2 6/7] gnu: openjdk14: " Danny Milosavljevic
@ 2023-07-31 18:09   ` Danny Milosavljevic
  2024-01-21  5:22     ` Maxim Cournoyer
  6 siblings, 1 reply; 24+ messages in thread
From: Danny Milosavljevic @ 2023-07-31 18:09 UTC (permalink / raw)
  To: 55751; +Cc: Danny Milosavljevic

* 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





^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [bug#55751] [PATCH v2 7/7] gnu: openjdk15: Make reproducible.
  2023-07-31 18:09   ` [bug#55751] [PATCH v2 7/7] gnu: openjdk15: " Danny Milosavljevic
@ 2024-01-21  5:22     ` Maxim Cournoyer
  2024-10-24 18:38       ` bug#55751: " Vagrant Cascadian
  0 siblings, 1 reply; 24+ messages in thread
From: Maxim Cournoyer @ 2024-01-21  5:22 UTC (permalink / raw)
  To: Danny Milosavljevic; +Cc: 55751

Hello!

Danny Milosavljevic <dannym@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




^ permalink raw reply	[flat|nested] 24+ messages in thread

* bug#55751: [PATCH v2 7/7] gnu: openjdk15: Make reproducible.
  2024-01-21  5:22     ` Maxim Cournoyer
@ 2024-10-24 18:38       ` Vagrant Cascadian
  0 siblings, 0 replies; 24+ messages in thread
From: Vagrant Cascadian @ 2024-10-24 18:38 UTC (permalink / raw)
  To: Maxim Cournoyer, Danny Milosavljevic; +Cc: 55751-done

[-- Attachment #1: Type: text/plain, Size: 1128 bytes --]

On 2024-01-21, Maxim Cournoyer wrote:
> Danny Milosavljevic <dannym@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

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 227 bytes --]

^ permalink raw reply	[flat|nested] 24+ messages in thread

end of thread, other threads:[~2024-10-24 18:40 UTC | newest]

Thread overview: 24+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2022-06-01 12:57 [bug#55751] [PATCH 0/8] Towards reproducible openjdk dannym
2022-06-01 13:00 ` [bug#55751] [PATCH 1/8] gnu: openjdk9: Make build reproducible dannym
2022-06-01 13:12   ` Maxime Devos
2022-06-01 13:14   ` Maxime Devos
2022-06-01 13:18   ` Maxime Devos
2022-09-21 20:18     ` Danny Milosavljevic
2022-06-01 13:00 ` [bug#55751] [PATCH 2/8] gnu: openjdk10: Make more reproducible dannym
2022-06-01 13:00 ` [bug#55751] [PATCH 3/8] gnu: openjdk11: " dannym
2022-06-01 13:00 ` [bug#55751] [PATCH 4/8] gnu: openjdk12: Make reproducible dannym
2022-06-01 13:00 ` [bug#55751] [PATCH 5/8] gnu: openjdk13: " dannym
2022-06-01 13:00 ` [bug#55751] [PATCH 6/8] gnu: openjdk14: " dannym
2022-06-01 13:00 ` [bug#55751] [PATCH 7/8] gnu: openjdk15: " dannym
2022-06-01 13:00 ` [bug#55751] [PATCH 8/8] gnu: openjdk16: " dannym
2022-06-01 13:20 ` [bug#55751] [PATCH 0/8] Towards reproducible openjdk Maxime Devos
2023-07-31 18:09 ` [bug#55751] [PATCH v2 0/7] " Danny Milosavljevic
2023-07-31 18:09   ` [bug#55751] [PATCH v2 1/7] gnu: openjdk9: Make build reproducible Danny Milosavljevic
2023-07-31 18:09   ` [bug#55751] [PATCH v2 2/7] gnu: openjdk10: Make more reproducible Danny Milosavljevic
2023-07-31 18:09   ` [bug#55751] [PATCH v2 3/7] gnu: openjdk11: " Danny Milosavljevic
2023-07-31 18:09   ` [bug#55751] [PATCH v2 4/7] gnu: openjdk12: Make reproducible Danny Milosavljevic
2023-07-31 18:09   ` [bug#55751] [PATCH v2 5/7] gnu: openjdk13: " Danny Milosavljevic
2023-07-31 18:09   ` [bug#55751] [PATCH v2 6/7] gnu: openjdk14: " Danny Milosavljevic
2023-07-31 18:09   ` [bug#55751] [PATCH v2 7/7] gnu: openjdk15: " Danny Milosavljevic
2024-01-21  5:22     ` Maxim Cournoyer
2024-10-24 18:38       ` bug#55751: " Vagrant Cascadian

Code repositories for project(s) associated with this external index

	https://git.savannah.gnu.org/cgit/guix.git

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.