From 756bfd3458ded38e1041ebb255c6b6ffe737732d Mon Sep 17 00:00:00 2001 From: Roman Scherer Date: Mon, 15 Aug 2022 15:29:25 +0000 Subject: [PATCH] build-system: Add repack-jar and use it in Ant & Clojure build systems * guix/build/ant-build-system.scm: Add repack-jar and use it in strip-jar-timestamps * guix/build/clojure-build-system.scm: Use repack-jar in reset-class-timestamps --- guix/build/ant-build-system.scm | 26 ++++++++------ guix/build/clojure-build-system.scm | 55 +++++------------------------ 2 files changed, 24 insertions(+), 57 deletions(-) diff --git a/guix/build/ant-build-system.scm b/guix/build/ant-build-system.scm index fae1b47ec5..63bdee4651 100644 --- a/guix/build/ant-build-system.scm +++ b/guix/build/ant-build-system.scm @@ -195,10 +195,9 @@ (define (generate-index jar) outputs) #t) -(define* (strip-jar-timestamps #:key outputs - #:allow-other-keys) - "Unpack all jar archives, reset the timestamp of all contained files, and -repack them. This is necessary to ensure that archives are reproducible." +(define-public (repack-jar outputs repack-fn) + "Unpack all jar archives, invoke repack-fn for each JAR with the directory +it has been unpacked to, and pack them again." (define (repack-archive jar) (format #t "repacking ~a\n" jar) (let* ((dir (mkdtemp! "jar-contents.XXXXXX")) @@ -206,13 +205,7 @@ (define (repack-archive jar) (with-directory-excursion dir (invoke "jar" "xf" jar)) (delete-file jar) - ;; XXX: copied from (gnu build install) - (for-each (lambda (file) - (let ((s (lstat file))) - (unless (eq? (stat:type s) 'symlink) - (utime file 0 0 0 0)))) - (find-files dir #:directories? #t)) - + (repack-fn dir) ;; The jar tool will always set the timestamp on the manifest file ;; and the containing directory to the current time, even when we ;; reuse an existing manifest file. To avoid this we use "zip" @@ -237,6 +230,17 @@ (define (repack-archive jar) outputs) #t) +(define* (strip-jar-timestamps #:key outputs + #:allow-other-keys) + "Unpack all jar archives, reset the timestamp of all contained files, and +repack them. This is necessary to ensure that archives are reproducible." + (repack-jar outputs (lambda (dir) + (for-each (lambda (file) + (let ((s (lstat file))) + (unless (eq? (stat:type s) 'symlink) + (utime file 0 0 0 0)))) + (find-files dir #:directories? #t))))) + (define* (check #:key target (make-flags '()) (tests? (not target)) (test-target "check") #:allow-other-keys) diff --git a/guix/build/clojure-build-system.scm b/guix/build/clojure-build-system.scm index cacbefb386..b82ebc30fe 100644 --- a/guix/build/clojure-build-system.scm +++ b/guix/build/clojure-build-system.scm @@ -19,7 +19,7 @@ (define-module (guix build clojure-build-system) #:use-module ((guix build ant-build-system) #:select ((%standard-phases . %standard-phases@ant) - ant-build)) + ant-build repack-jar)) #:use-module (guix build clojure-utils) #:use-module (guix build java-utils) #:use-module (guix build syscalls) @@ -112,54 +112,17 @@ (define* (check #:key jar-names))) #t) -(define (regular-jar-file? file stat) - "Predicate returning true if FILE is ending on '.jar' -and STAT indicates it is a regular file." - (and (string-suffix? ".jar" file) - (eq? 'regular (stat:type stat)))) - -;; XXX: The only difference compared to 'strip-jar-timestamps' in -;; ant-build-system.scm is the date. TODO: Adjust and factorize. (define* (reset-class-timestamps #:key outputs #:allow-other-keys) "Unpack all jar archives, reset the timestamp of all contained class files, and repack them. This is necessary to ensure that archives are reproducible." - (define (repack-archive jar) - (format #t "resetting class timestamps and repacking ~a\n" jar) - - ;; Note: .class files need to be strictly newer than source files, - ;; otherwise the Clojure compiler will recompile sources. - (let* ((early-1980 315619200) ; 1980-01-02 UTC - (dir (mkdtemp! "jar-contents.XXXXXX")) - (manifest (string-append dir "/META-INF/MANIFEST.MF"))) - (with-directory-excursion dir - (invoke "jar" "xf" jar)) - (delete-file jar) - (for-each (lambda (file) - (let ((s (lstat file))) - (unless (eq? (stat:type s) 'symlink) - (when (string-match "^(.*)\\.class$" file) - (utime file early-1980 early-1980))))) - (find-files dir #:directories? #t)) - ;; The jar tool will always set the timestamp on the manifest file - ;; and the containing directory to the current time, even when we - ;; reuse an existing manifest file. To avoid this we use "zip" - ;; instead of "jar". It is important that the manifest appears - ;; first. - (with-directory-excursion dir - (let* ((files (find-files "." ".*" #:directories? #t)) - ;; To ensure that the reference scanner can detect all - ;; store references in the jars we disable compression - ;; with the "-0" option. - (command (if (file-exists? manifest) - `("zip" "-0" "-X" ,jar ,manifest ,@files) - `("zip" "-0" "-X" ,jar ,@files)))) - (apply invoke command))) - (utime jar 0 0))) - (for-each (match-lambda - ((output . directory) - (for-each repack-archive - (find-files directory regular-jar-file?)))) - outputs)) + (repack-jar outputs (lambda (dir) + (for-each (lambda (file) + (let ((s (lstat file)) + (early-1980 315619200)) ; 1980-01-02 UTC + (unless (eq? (stat:type s) 'symlink) + (when (string-match "^(.*)\\.class$" file) + (utime file early-1980 early-1980))))) + (find-files dir #:directories? #t))))) (define-with-docs install "Standard 'install' phase for clojure-build-system." -- 2.37.1