mirror of
https://codeberg.org/guix/guix.git
synced 2025-10-02 02:15:12 +00:00
gnu: openjdk9: Make build reproducible.
* 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. [native-inputs, inputs]: Use new-style syntax. * gnu/local/mk (dist_patch_DATA): Add patches. Signed-off-by: Maxim Cournoyer <maxim.cournoyer@gmail.com> Modified-by: Maxim Cournoyer <maxim.cournoyer@gmail.com> Change-Id: Ifb7a87b0c11f3a7032597013ac904aefc9234db1
This commit is contained in:
parent
10d45f6a0e
commit
2f1daa3574
8 changed files with 808 additions and 114 deletions
|
@ -1823,6 +1823,12 @@ dist_patch_DATA = \
|
||||||
%D%/packages/patches/openjdk-currency-time-bomb2.patch \
|
%D%/packages/patches/openjdk-currency-time-bomb2.patch \
|
||||||
%D%/packages/patches/openjdk-9-pointer-comparison.patch \
|
%D%/packages/patches/openjdk-9-pointer-comparison.patch \
|
||||||
%D%/packages/patches/openjdk-9-setsignalhandler.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-idlj-reproducibility.patch \
|
||||||
%D%/packages/patches/openjdk-10-pointer-comparison.patch \
|
%D%/packages/patches/openjdk-10-pointer-comparison.patch \
|
||||||
%D%/packages/patches/openjdk-10-setsignalhandler.patch \
|
%D%/packages/patches/openjdk-10-setsignalhandler.patch \
|
||||||
|
|
|
@ -886,9 +886,16 @@ new Date();"))
|
||||||
(sha256
|
(sha256
|
||||||
(base32
|
(base32
|
||||||
"1v92nzdqx07c35x945awzir4yk0fk22vky6fpp8mq9js930sxsz0"))
|
"1v92nzdqx07c35x945awzir4yk0fk22vky6fpp8mq9js930sxsz0"))
|
||||||
(patches (search-patches "openjdk-9-pointer-comparison.patch"
|
(patches
|
||||||
"openjdk-9-setsignalhandler.patch"
|
(search-patches "openjdk-9-pointer-comparison.patch"
|
||||||
"openjdk-currency-time-bomb.patch"))))
|
"openjdk-9-classlist-reproducibility.patch"
|
||||||
|
"openjdk-currency-time-bomb.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)
|
(build-system gnu-build-system)
|
||||||
(outputs '("out" "jdk" "doc"))
|
(outputs '("out" "jdk" "doc"))
|
||||||
(arguments
|
(arguments
|
||||||
|
@ -899,7 +906,7 @@ new Date();"))
|
||||||
((guix build utils)
|
((guix build utils)
|
||||||
(guix build gnu-build-system)
|
(guix build gnu-build-system)
|
||||||
(ice-9 popen))
|
(ice-9 popen))
|
||||||
#:tests? #f; require jtreg
|
#:tests? #f ; require jtreg
|
||||||
#:make-flags '("all")
|
#:make-flags '("all")
|
||||||
#:disallowed-references ,(list (gexp-input icedtea-8)
|
#:disallowed-references ,(list (gexp-input icedtea-8)
|
||||||
(gexp-input icedtea-8 "jdk"))
|
(gexp-input icedtea-8 "jdk"))
|
||||||
|
@ -988,80 +995,80 @@ new Date();"))
|
||||||
file))))
|
file))))
|
||||||
(find-files "."
|
(find-files "."
|
||||||
"\\.c$|\\.h$")))))
|
"\\.c$|\\.h$")))))
|
||||||
;; By default OpenJDK only generates an empty keystore. In order to
|
;; By default OpenJDK only generates an empty keystore. In order to
|
||||||
;; be able to use certificates in Java programs we need to generate a
|
;; be able to use certificates in Java programs we need to generate a
|
||||||
;; keystore from a set of certificates. For convenience we use the
|
;; keystore from a set of certificates. For convenience we use the
|
||||||
;; certificates from the nss-certs package.
|
;; certificates from the nss-certs package.
|
||||||
(add-after 'install 'install-keystore
|
(add-after 'install 'install-keystore
|
||||||
(lambda* (#:key inputs outputs #:allow-other-keys)
|
(lambda* (#:key inputs outputs #:allow-other-keys)
|
||||||
(use-modules (ice-9 rdelim))
|
(use-modules (ice-9 rdelim))
|
||||||
(let* ((keystore "cacerts")
|
(let* ((keystore "cacerts")
|
||||||
(certs-dir (search-input-directory inputs
|
(certs-dir (search-input-directory inputs
|
||||||
"etc/ssl/certs"))
|
"etc/ssl/certs"))
|
||||||
(keytool (string-append (assoc-ref outputs "jdk")
|
(keytool (string-append (assoc-ref outputs "jdk")
|
||||||
"/bin/keytool")))
|
"/bin/keytool")))
|
||||||
(define (extract-cert file target)
|
(define (extract-cert file target)
|
||||||
(call-with-input-file file
|
(call-with-input-file file
|
||||||
(lambda (in)
|
(lambda (in)
|
||||||
(call-with-output-file target
|
(call-with-output-file target
|
||||||
(lambda (out)
|
(lambda (out)
|
||||||
(let loop ((line (read-line in 'concat))
|
(let loop ((line (read-line in 'concat))
|
||||||
(copying? #f))
|
(copying? #f))
|
||||||
(cond
|
(cond
|
||||||
((eof-object? line) #t)
|
((eof-object? line) #t)
|
||||||
((string-prefix? "-----BEGIN" line)
|
((string-prefix? "-----BEGIN" line)
|
||||||
(display line out)
|
(display line out)
|
||||||
(loop (read-line in 'concat) #t))
|
(loop (read-line in 'concat) #t))
|
||||||
((string-prefix? "-----END" line)
|
((string-prefix? "-----END" line)
|
||||||
(display line out)
|
(display line out)
|
||||||
#t)
|
#t)
|
||||||
(else
|
(else
|
||||||
(when copying? (display line out))
|
(when copying? (display line out))
|
||||||
(loop (read-line in 'concat) copying?)))))))))
|
(loop (read-line in 'concat) copying?)))))))))
|
||||||
(define (import-cert cert)
|
(define (import-cert cert)
|
||||||
(format #t "Importing certificate ~a\n" (basename cert))
|
(format #t "Importing certificate ~a\n" (basename cert))
|
||||||
(let ((temp "tmpcert"))
|
(let ((temp "tmpcert"))
|
||||||
(extract-cert cert temp)
|
(extract-cert cert temp)
|
||||||
(let ((port (open-pipe* OPEN_WRITE keytool
|
(let ((port (open-pipe* OPEN_WRITE keytool
|
||||||
"-import"
|
"-import"
|
||||||
"-alias" (basename cert)
|
"-alias" (basename cert)
|
||||||
"-keystore" keystore
|
"-keystore" keystore
|
||||||
"-storepass" "changeit"
|
"-storepass" "changeit"
|
||||||
"-file" temp)))
|
"-file" temp)))
|
||||||
(display "yes\n" port)
|
(display "yes\n" port)
|
||||||
(when (not (zero? (status:exit-val (close-pipe port))))
|
(when (not (zero? (status:exit-val (close-pipe port))))
|
||||||
(format #t "failed to import ~a\n" cert)))
|
(format #t "failed to import ~a\n" cert)))
|
||||||
(delete-file temp)))
|
(delete-file temp)))
|
||||||
|
|
||||||
;; This is necessary because the certificate directory contains
|
;; This is necessary because the certificate directory contains
|
||||||
;; files with non-ASCII characters in their names.
|
;; files with non-ASCII characters in their names.
|
||||||
(setlocale LC_ALL "C.UTF-8")
|
(setlocale LC_ALL "C.UTF-8")
|
||||||
(setenv "LC_ALL" "C.UTF-8")
|
(setenv "LC_ALL" "C.UTF-8")
|
||||||
|
|
||||||
(copy-file (string-append (assoc-ref outputs "out")
|
(copy-file (string-append (assoc-ref outputs "out")
|
||||||
"/lib/security/cacerts")
|
"/lib/security/cacerts")
|
||||||
keystore)
|
keystore)
|
||||||
(chmod keystore #o644)
|
(chmod keystore #o644)
|
||||||
(for-each import-cert (find-files certs-dir "\\.pem$"))
|
(for-each import-cert (find-files certs-dir "\\.pem$"))
|
||||||
(mkdir-p (string-append (assoc-ref outputs "out")
|
(mkdir-p (string-append (assoc-ref outputs "out")
|
||||||
"/lib/security"))
|
"/lib/security"))
|
||||||
(mkdir-p (string-append (assoc-ref outputs "jdk")
|
(mkdir-p (string-append (assoc-ref outputs "jdk")
|
||||||
"/lib/security"))
|
"/lib/security"))
|
||||||
|
|
||||||
;; The cacerts files we are going to overwrite are chmod'ed as
|
;; The cacerts files we are going to overwrite are chmod'ed as
|
||||||
;; read-only (444) in icedtea-8 (which derives from this
|
;; read-only (444) in icedtea-8 (which derives from this
|
||||||
;; package). We have to change this so we can overwrite them.
|
;; package). We have to change this so we can overwrite them.
|
||||||
(chmod (string-append (assoc-ref outputs "out")
|
(chmod (string-append (assoc-ref outputs "out")
|
||||||
"/lib/security/" keystore) #o644)
|
"/lib/security/" keystore) #o644)
|
||||||
(chmod (string-append (assoc-ref outputs "jdk")
|
(chmod (string-append (assoc-ref outputs "jdk")
|
||||||
"/lib/security/" keystore) #o644)
|
"/lib/security/" keystore) #o644)
|
||||||
|
|
||||||
(install-file keystore
|
(install-file keystore
|
||||||
(string-append (assoc-ref outputs "out")
|
(string-append (assoc-ref outputs "out")
|
||||||
"/lib/security"))
|
"/lib/security"))
|
||||||
(install-file keystore
|
(install-file keystore
|
||||||
(string-append (assoc-ref outputs "jdk")
|
(string-append (assoc-ref outputs "jdk")
|
||||||
"/lib/security")))))
|
"/lib/security")))))
|
||||||
;; Some of the libraries in the lib/ folder link to libjvm.so.
|
;; Some of the libraries in the lib/ folder link to libjvm.so.
|
||||||
;; But that shared object is located in the server/ folder, so it
|
;; But that shared object is located in the server/ folder, so it
|
||||||
;; cannot be found. This phase creates a symbolic link in the
|
;; cannot be found. This phase creates a symbolic link in the
|
||||||
|
@ -1094,48 +1101,96 @@ new Date();"))
|
||||||
(copy-recursively (string-append images "/images/docs") doc))))
|
(copy-recursively (string-append images "/images/docs") doc))))
|
||||||
(add-after 'install 'strip-zip-timestamps
|
(add-after 'install 'strip-zip-timestamps
|
||||||
(lambda* (#:key outputs #:allow-other-keys)
|
(lambda* (#:key outputs #:allow-other-keys)
|
||||||
(for-each (lambda (zip)
|
(for-each
|
||||||
(let ((dir (mkdtemp "zip-contents.XXXXXX")))
|
(lambda (zip)
|
||||||
(with-directory-excursion dir
|
(let ((dir (mkdtemp "zip-contents.XXXXXX")))
|
||||||
(invoke "unzip" zip))
|
(with-directory-excursion dir
|
||||||
(delete-file zip)
|
;; This is an exact copy of the implementation of invoke,
|
||||||
(for-each (lambda (file)
|
;; but this accepts exit code 1 as OK.
|
||||||
(let ((s (lstat file)))
|
(let ((code (system* "unzip" "--" zip)))
|
||||||
(unless (eq? (stat:type s) 'symlink)
|
;; jmod files are zip files with an extra header in
|
||||||
(format #t "reset ~a~%" file)
|
;; front. unzip will warn about that -- but otherwise
|
||||||
(utime file 0 0 0 0))))
|
;; work.
|
||||||
(find-files dir #:directories? #t))
|
(when (> (status:exit-val code) 1) ; 1 is just a warning
|
||||||
(with-directory-excursion dir
|
(raise
|
||||||
(let ((files (find-files "." ".*" #:directories? #t)))
|
(condition
|
||||||
(apply invoke "zip" "-0" "-X" zip files)))))
|
(&invoke-error
|
||||||
(find-files (assoc-ref outputs "doc") ".*.zip$")))))))
|
(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)))
|
||||||
|
(format #t "reset ~a~%" file)
|
||||||
|
(utime file 1 1 0 0
|
||||||
|
AT_SYMLINK_NOFOLLOW)))
|
||||||
|
(find-files dir #:directories? #t))
|
||||||
|
(with-directory-excursion dir
|
||||||
|
(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$"))))))))
|
||||||
(inputs
|
(inputs
|
||||||
`(("alsa-lib" ,alsa-lib)
|
(list alsa-lib
|
||||||
("cups" ,cups)
|
cups
|
||||||
("fontconfig" ,fontconfig)
|
fontconfig
|
||||||
("freetype" ,freetype)
|
freetype
|
||||||
("giflib" ,giflib)
|
giflib
|
||||||
("lcms" ,lcms)
|
lcms
|
||||||
("libelf" ,libelf)
|
libelf
|
||||||
("libjpeg" ,libjpeg-turbo)
|
libjpeg-turbo
|
||||||
("libice" ,libice)
|
libice
|
||||||
("libpng" ,libpng)
|
libpng
|
||||||
("libx11" ,libx11)
|
libx11
|
||||||
("libxcomposite" ,libxcomposite)
|
libxcomposite
|
||||||
("libxi" ,libxi)
|
libxi
|
||||||
("libxinerama" ,libxinerama)
|
libxinerama
|
||||||
("libxrender" ,libxrender)
|
libxrender
|
||||||
("libxt" ,libxt)
|
libxt
|
||||||
("libxtst" ,libxtst)))
|
libxtst))
|
||||||
(native-inputs
|
(native-inputs
|
||||||
`(("icedtea-8" ,icedtea-8)
|
(list icedtea-8
|
||||||
("icedtea-8:jdk" ,icedtea-8 "jdk")
|
`(,icedtea-8 "jdk")
|
||||||
;; XXX: The build system fails with newer versions of GNU Make.
|
;; XXX: The build system fails with newer versions of GNU Make.
|
||||||
("make@4.2" ,gnu-make-4.2)
|
gnu-make-4.2
|
||||||
("nss-certs" ,nss-certs)
|
nss-certs
|
||||||
("unzip" ,unzip)
|
unzip
|
||||||
("which" ,which)
|
which
|
||||||
("zip" ,zip)))
|
zip))
|
||||||
(home-page "https://openjdk.org/projects/jdk9/")
|
(home-page "https://openjdk.org/projects/jdk9/")
|
||||||
(synopsis "Java development kit")
|
(synopsis "Java development kit")
|
||||||
(description
|
(description
|
||||||
|
|
|
@ -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
|
37
gnu/packages/patches/openjdk-9-idlj-reproducibility.patch
Normal file
37
gnu/packages/patches/openjdk-9-idlj-reproducibility.patch
Normal file
|
@ -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 {
|
107
gnu/packages/patches/openjdk-9-jar-reproducibility.patch
Normal file
107
gnu/packages/patches/openjdk-9-jar-reproducibility.patch
Normal file
|
@ -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);
|
||||||
|
}
|
297
gnu/packages/patches/openjdk-9-module-reproducibility.patch
Normal file
297
gnu/packages/patches/openjdk-9-module-reproducibility.patch
Normal file
|
@ -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);
|
||||||
|
}
|
||||||
|
|
125
gnu/packages/patches/openjdk-9-module2-reproducibility.patch
Normal file
125
gnu/packages/patches/openjdk-9-module2-reproducibility.patch
Normal file
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
36
gnu/packages/patches/openjdk-9-module3-reproducibility.patch
Normal file
36
gnu/packages/patches/openjdk-9-module3-reproducibility.patch
Normal file
|
@ -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,
|
Loading…
Add table
Add a link
Reference in a new issue