diff options
Diffstat (limited to 'guix/build')
26 files changed, 390 insertions, 231 deletions
diff --git a/guix/build/ant-build-system.scm b/guix/build/ant-build-system.scm index 6ce813a001..a6da530dab 100644 --- a/guix/build/ant-build-system.scm +++ b/guix/build/ant-build-system.scm @@ -228,6 +228,7 @@ repack them. This is necessary to ensure that archives are reproducible." (define %standard-phases (modify-phases gnu:%standard-phases (replace 'unpack unpack) + (delete 'bootstrap) (replace 'configure configure) (replace 'build build) (replace 'check check) diff --git a/guix/build/asdf-build-system.scm b/guix/build/asdf-build-system.scm index c5e820a00a..dd6373b33a 100644 --- a/guix/build/asdf-build-system.scm +++ b/guix/build/asdf-build-system.scm @@ -220,6 +220,7 @@ valid." (define %standard-phases/source (modify-phases gnu:%standard-phases + (delete 'bootstrap) (delete 'configure) (delete 'check) (delete 'build) @@ -227,6 +228,7 @@ valid." (define %standard-phases (modify-phases gnu:%standard-phases + (delete 'bootstrap) (delete 'configure) (delete 'install) (replace 'build build) diff --git a/guix/build/cargo-build-system.scm b/guix/build/cargo-build-system.scm index 139b40321f..f52444f61c 100644 --- a/guix/build/cargo-build-system.scm +++ b/guix/build/cargo-build-system.scm @@ -172,6 +172,7 @@ SRC-NAME as if it was part of the directory DIR-NAME with name (define %standard-phases (modify-phases gnu:%standard-phases + (delete 'bootstrap) (replace 'configure configure) (replace 'build build) (replace 'check check) diff --git a/guix/build/cmake-build-system.scm b/guix/build/cmake-build-system.scm index c82d9fef87..9b1112f2d6 100644 --- a/guix/build/cmake-build-system.scm +++ b/guix/build/cmake-build-system.scm @@ -1,5 +1,5 @@ ;;; GNU Guix --- Functional package management for GNU -;;; Copyright © 2013, 2014, 2015 Ludovic Courtès <ludo@gnu.org> +;;; Copyright © 2013, 2014, 2015, 2018 Ludovic Courtès <ludo@gnu.org> ;;; Copyright © 2013 Cyril Roelandt <tipecaml@gmail.com> ;;; Copyright © 2014, 2015 Andreas Enge <andreas@enge.fr> ;;; Copyright © 2017 Efraim Flashner <efraim@flashner.co.il> @@ -73,7 +73,7 @@ '()) ,@configure-flags))) (format #t "running 'cmake' with arguments ~s~%" args) - (zero? (apply system* "cmake" args))))) + (apply invoke "cmake" args)))) (define* (check #:key (tests? #t) (parallel-tests? #t) (test-target "test") #:allow-other-keys) @@ -86,6 +86,7 @@ ;; Everything is as with the GNU Build System except for the `configure' ;; and 'check' phases. (modify-phases gnu:%standard-phases + (delete 'bootstrap) (replace 'check check) (replace 'configure configure))) diff --git a/guix/build/cvs.scm b/guix/build/cvs.scm index 9976e624b3..7111043747 100644 --- a/guix/build/cvs.scm +++ b/guix/build/cvs.scm @@ -55,19 +55,20 @@ Return #t on success, #f otherwise." ;; Use "-z0" because enabling compression leads to hangs during checkout on ;; certain repositories, such as ;; ":pserver:anonymous@cvs.savannah.gnu.org:/sources/gnustandards". - (and (zero? (system* cvs-command "-z0" - "-d" cvs-root-directory - "checkout" - (if (string-match "^[0-9]{4}-[0-9]{2}-[0-9]{2}$" revision) - "-D" "-r") - revision - module)) - ;; Copy rather than rename in case MODULE and DIRECTORY are on - ;; different devices. - (copy-recursively module directory) + (invoke cvs-command "-z0" + "-d" cvs-root-directory + "checkout" + (if (string-match "^[0-9]{4}-[0-9]{2}-[0-9]{2}$" revision) + "-D" "-r") + revision + module) - (with-directory-excursion directory - (for-each delete-file-recursively (find-cvs-directories))) - #t)) + ;; Copy rather than rename in case MODULE and DIRECTORY are on + ;; different devices. + (copy-recursively module directory) + + (with-directory-excursion directory + (for-each delete-file-recursively (find-cvs-directories))) + #t) ;;; cvs.scm ends here diff --git a/guix/build/dub-build-system.scm b/guix/build/dub-build-system.scm index ed86635708..9a72e3d544 100644 --- a/guix/build/dub-build-system.scm +++ b/guix/build/dub-build-system.scm @@ -121,6 +121,7 @@ (define %standard-phases (modify-phases gnu:%standard-phases + (delete 'bootstrap) (replace 'configure configure) (replace 'build build) (replace 'check check) diff --git a/guix/build/emacs-build-system.scm b/guix/build/emacs-build-system.scm index b779847424..7c3b635139 100644 --- a/guix/build/emacs-build-system.scm +++ b/guix/build/emacs-build-system.scm @@ -262,6 +262,7 @@ second hyphen. This corresponds to 'name-version' as used in ELPA packages." (modify-phases gnu:%standard-phases (add-after 'set-paths 'set-emacs-load-path set-emacs-load-path) (replace 'unpack unpack) + (delete 'bootstrap) (delete 'configure) ;; Move the build phase after install: the .el files are byte compiled ;; directly in the store. diff --git a/guix/build/emacs-utils.scm b/guix/build/emacs-utils.scm index 8389ca582f..30aec5b9c6 100644 --- a/guix/build/emacs-utils.scm +++ b/guix/build/emacs-utils.scm @@ -1,5 +1,5 @@ ;;; GNU Guix --- Functional package management for GNU -;;; Copyright © 2014 Mark H Weaver <mhw@netris.org> +;;; Copyright © 2014, 2018 Mark H Weaver <mhw@netris.org> ;;; Copyright © 2014 Alex Kost <alezost@gmail.com> ;;; ;;; This file is part of GNU Guix. @@ -18,6 +18,7 @@ ;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>. (define-module (guix build emacs-utils) + #:use-module (guix build utils) #:export (%emacs emacs-batch-eval emacs-batch-edit-file @@ -39,16 +40,14 @@ (define (emacs-batch-eval expr) "Run Emacs in batch mode, and execute the elisp code EXPR." - (unless (zero? (system* (%emacs) "--quick" "--batch" - (format #f "--eval=~S" expr))) - (error "emacs-batch-eval failed!" expr))) + (invoke (%emacs) "--quick" "--batch" + (format #f "--eval=~S" expr))) (define (emacs-batch-edit-file file expr) "Load FILE in Emacs using batch mode, and execute the elisp code EXPR." - (unless (zero? (system* (%emacs) "--quick" "--batch" - (string-append "--visit=" file) - (format #f "--eval=~S" expr))) - (error "emacs-batch-edit-file failed!" file expr))) + (invoke (%emacs) "--quick" "--batch" + (string-append "--visit=" file) + (format #f "--eval=~S" expr))) (define (emacs-generate-autoloads name directory) "Generate autoloads for Emacs package NAME placed in DIRECTORY." diff --git a/guix/build/font-build-system.scm b/guix/build/font-build-system.scm index f2a646f6f4..6726595fe1 100644 --- a/guix/build/font-build-system.scm +++ b/guix/build/font-build-system.scm @@ -59,6 +59,7 @@ archive, or a font file." (define %standard-phases (modify-phases gnu:%standard-phases (replace 'unpack unpack) + (delete 'bootstrap) (delete 'configure) (delete 'check) (delete 'build) diff --git a/guix/build/glib-or-gtk-build-system.scm b/guix/build/glib-or-gtk-build-system.scm index b6291e735b..ba680fd1a9 100644 --- a/guix/build/glib-or-gtk-build-system.scm +++ b/guix/build/glib-or-gtk-build-system.scm @@ -1,6 +1,7 @@ ;;; GNU Guix --- Functional package management for GNU ;;; Copyright © 2014 Federico Beffa <beffa@fbengineering.ch> ;;; Copyright © 2014, 2015 Ludovic Courtès <ludo@gnu.org> +;;; Copyright © 2018 Mark H Weaver <mhw@netris.org> ;;; ;;; This file is part of GNU Guix. ;;; @@ -202,16 +203,16 @@ add a dependency of that output on GLib and GTK+." (define* (compile-glib-schemas #:key outputs #:allow-other-keys) "Implement phase \"glib-or-gtk-compile-schemas\": compile \"glib\" schemas if needed." - (every (match-lambda - ((output . directory) - (let ((schemasdir (string-append directory - "/share/glib-2.0/schemas"))) - (if (and (directory-exists? schemasdir) - (not (file-exists? - (string-append schemasdir "/gschemas.compiled")))) - (zero? (system* "glib-compile-schemas" schemasdir)) - #t)))) - outputs)) + (for-each (match-lambda + ((output . directory) + (let ((schemasdir (string-append directory + "/share/glib-2.0/schemas"))) + (when (and (directory-exists? schemasdir) + (not (file-exists? + (string-append schemasdir "/gschemas.compiled")))) + (invoke "glib-compile-schemas" schemasdir))))) + outputs) + #t) (define %standard-phases (modify-phases gnu:%standard-phases diff --git a/guix/build/gnu-build-system.scm b/guix/build/gnu-build-system.scm index 7b43361f99..a39a884852 100644 --- a/guix/build/gnu-build-system.scm +++ b/guix/build/gnu-build-system.scm @@ -1,5 +1,6 @@ ;;; GNU Guix --- Functional package management for GNU -;;; Copyright © 2012, 2013, 2014, 2015, 2016, 2017 Ludovic Courtès <ludo@gnu.org> +;;; Copyright © 2012, 2013, 2014, 2015, 2016, 2017, 2018 Ludovic Courtès <ludo@gnu.org> +;;; Copyright © 2018 Mark H Weaver <mhw@netris.org> ;;; ;;; This file is part of GNU Guix. ;;; @@ -26,10 +27,13 @@ #:use-module (ice-9 format) #:use-module (srfi srfi-1) #:use-module (srfi srfi-19) + #:use-module (srfi srfi-34) + #:use-module (srfi srfi-35) #:use-module (srfi srfi-26) #:use-module (rnrs io ports) #:export (%standard-phases %license-file-regexp + dump-file-contents gnu-build)) ;; Commentary: @@ -152,12 +156,50 @@ working directory." ;; Preserve timestamps (set to the Epoch) on the copied tree so that ;; things work deterministically. (copy-recursively source "." - #:keep-mtime? #t) - #t) - (and (if (string-suffix? ".zip" source) - (zero? (system* "unzip" source)) - (zero? (system* "tar" "xvf" source))) - (chdir (first-subdirectory "."))))) + #:keep-mtime? #t)) + (begin + (if (string-suffix? ".zip" source) + (invoke "unzip" source) + (invoke "tar" "xvf" source)) + (chdir (first-subdirectory ".")))) + #t) + +(define %bootstrap-scripts + ;; Typical names of Autotools "bootstrap" scripts. + '("bootstrap" "bootstrap.sh" "autogen.sh")) + +(define* (bootstrap #:key (bootstrap-scripts %bootstrap-scripts) + #:allow-other-keys) + "If the code uses Autotools and \"configure\" is missing, run +\"autoreconf\". Otherwise do nothing." + ;; Note: Run that right after 'unpack' so that the generated files are + ;; visible when the 'patch-source-shebangs' phase runs. + (if (not (file-exists? "configure")) + + ;; First try one of the BOOTSTRAP-SCRIPTS. If none exists, and it's + ;; clearly an Autoconf-based project, run 'autoreconf'. Otherwise, do + ;; nothing (perhaps the user removed or overrode the 'configure' phase.) + (let ((script (find file-exists? bootstrap-scripts))) + ;; GNU packages often invoke the 'git-version-gen' script from + ;; 'configure.ac' so make sure it has a valid shebang. + (false-if-file-not-found + (patch-shebang "build-aux/git-version-gen")) + + (if script + (let ((script (string-append "./" script))) + (format #t "running '~a'~%" script) + (if (executable-file? script) + (begin + (patch-shebang script) + (invoke script)) + (invoke "sh" script))) + (if (or (file-exists? "configure.ac") + (file-exists? "configure.in")) + (invoke "autoreconf" "-vif") + (format #t "no 'configure.ac' or anything like that, \ +doing nothing~%")))) + (format #t "GNU build system bootstrapping not needed~%")) + #t) ;; See <http://bugs.gnu.org/17840>. (define* (patch-usr-bin-file #:key native-inputs inputs @@ -184,7 +226,8 @@ $CONFIG_SHELL, but some don't, such as `mkinstalldirs' or Automake's (lambda (file stat) ;; Filter out symlinks. (eq? 'regular (stat:type stat))) - #:stat lstat))) + #:stat lstat)) + #t) (define (patch-generated-file-shebangs . rest) "Patch shebangs in generated files, including `SHELL' variables in @@ -199,7 +242,9 @@ makefiles." #:stat lstat)) ;; Patch `SHELL' in generated makefiles. - (for-each patch-makefile-SHELL (find-files "." "^(GNU)?[mM]akefile$"))) + (for-each patch-makefile-SHELL (find-files "." "^(GNU)?[mM]akefile$")) + + #t) (define* (configure #:key build target native-inputs inputs outputs (configure-flags '()) out-of-source? @@ -279,33 +324,61 @@ makefiles." ;; Call `configure' with a relative path. Otherwise, GCC's build system ;; (for instance) records absolute source file names, which typically ;; contain the hash part of the `.drv' file, leading to a reference leak. - (zero? (apply system* bash - (string-append srcdir "/configure") - flags)))) + (apply invoke bash + (string-append srcdir "/configure") + flags))) (define* (build #:key (make-flags '()) (parallel-build? #t) #:allow-other-keys) - (zero? (apply system* "make" - `(,@(if parallel-build? - `("-j" ,(number->string (parallel-job-count))) - '()) - ,@make-flags)))) + (apply invoke "make" + `(,@(if parallel-build? + `("-j" ,(number->string (parallel-job-count))) + '()) + ,@make-flags))) + +(define* (dump-file-contents directory file-regexp + #:optional (port (current-error-port))) + "Dump to PORT the contents of files in DIRECTORY that match FILE-REGEXP." + (define (dump file) + (let ((prefix (string-append "\n--- " file " "))) + (display (if (< (string-length prefix) 78) + (string-pad-right prefix 78 #\-) + prefix) + port) + (display "\n\n" port) + (call-with-input-file file + (lambda (log) + (dump-port log port))) + (display "\n" port))) + + (for-each dump (find-files directory file-regexp))) + +(define %test-suite-log-regexp + ;; Name of test suite log files as commonly found in GNU-based build systems + ;; and CMake. + "^(test-?suite\\.log|LastTestFailed\\.log)$") (define* (check #:key target (make-flags '()) (tests? (not target)) (test-target "check") (parallel-tests? #t) + (test-suite-log-regexp %test-suite-log-regexp) #:allow-other-keys) (if tests? - (zero? (apply system* "make" test-target - `(,@(if parallel-tests? - `("-j" ,(number->string (parallel-job-count))) - '()) - ,@make-flags))) - (begin - (format #t "test suite not run~%") - #t))) + (guard (c ((invoke-error? c) + ;; Dump the test suite log to facilitate debugging. + (display "\nTest suite failed, dumping logs.\n" + (current-error-port)) + (dump-file-contents "." test-suite-log-regexp) + (raise c))) + (apply invoke "make" test-target + `(,@(if parallel-tests? + `("-j" ,(number->string (parallel-job-count))) + '()) + ,@make-flags))) + (format #t "test suite not run~%")) + #t) (define* (install #:key (make-flags '()) #:allow-other-keys) - (zero? (apply system* "make" "install" make-flags))) + (apply invoke "make" "install" make-flags)) (define* (patch-shebangs #:key inputs outputs (patch-shebangs? #t) #:allow-other-keys) @@ -371,10 +444,8 @@ makefiles." (let ((debug (debug-file file))) (mkdir-p (dirname debug)) (copy-file file debug) - (and (zero? (system* strip-command "--only-keep-debug" debug)) - (begin - (chmod debug #o400) - #t)))) + (invoke strip-command "--only-keep-debug" debug) + (chmod debug #o400))) (define (add-debug-link file) ;; Add a debug link in FILE (info "(binutils) strip"). @@ -384,10 +455,10 @@ makefiles." ;; `bfd_fill_in_gnu_debuglink_section' function.) No reference to ;; DEBUG-OUTPUT is kept because bfd keeps only the basename of the debug ;; file. - (zero? (system* objcopy-command "--enable-deterministic-archives" - (string-append "--add-gnu-debuglink=" - (debug-file file)) - file))) + (invoke objcopy-command "--enable-deterministic-archives" + (string-append "--add-gnu-debuglink=" + (debug-file file)) + file)) (define (strip-dir dir) (format #t "stripping binaries in ~s with ~s and flags ~s~%" @@ -397,17 +468,29 @@ makefiles." debug-output objcopy-command)) (for-each (lambda (file) - (and (or (elf-file? file) (ar-file? file)) - (or (not debug-output) - (make-debug-file file)) - - ;; Ensure the file is writable. - (begin (make-file-writable file) #t) - - (zero? (apply system* strip-command - (append strip-flags (list file)))) - (or (not debug-output) - (add-debug-link file)))) + (when (or (elf-file? file) (ar-file? file)) + ;; If an error occurs while processing a file, issue a + ;; warning and continue to the next file. + (guard (c ((invoke-error? c) + (format (current-error-port) + "warning: ~a: program ~s exited\ +~@[ with non-zero exit status ~a~]\ +~@[ terminated by signal ~a~]~%" + file + (invoke-error-program c) + (invoke-error-exit-status c) + (invoke-error-term-signal c)))) + (when debug-output + (make-debug-file file)) + + ;; Ensure the file is writable. + (make-file-writable file) + + (apply invoke strip-command + (append strip-flags (list file))) + + (when debug-output + (add-debug-link file))))) (find-files dir (lambda (file stat) ;; Ignore symlinks such as: @@ -415,15 +498,17 @@ makefiles." (eq? 'regular (stat:type stat))) #:stat lstat))) - (or (not strip-binaries?) - (every strip-dir - (append-map (match-lambda - ((_ . dir) - (filter-map (lambda (d) - (let ((sub (string-append dir "/" d))) - (and (directory-exists? sub) sub))) - strip-directories))) - outputs)))) + (when strip-binaries? + (for-each + strip-dir + (append-map (match-lambda + ((_ . dir) + (filter-map (lambda (d) + (let ((sub (string-append dir "/" d))) + (and (directory-exists? sub) sub))) + strip-directories))) + outputs))) + #t) (define* (validate-runpath #:key (validate-runpath? #t) @@ -466,10 +551,11 @@ phase after stripping." (filter-map (sub-directory output) elf-directories))) outputs))) - (every* validate dirs)) - (begin - (format (current-error-port) "skipping RUNPATH validation~%") - #t))) + (unless (every* validate dirs) + (error "RUNPATH validation failed"))) + (format (current-error-port) "skipping RUNPATH validation~%")) + + #t) (define* (validate-documentation-location #:key outputs #:allow-other-keys) @@ -549,47 +635,45 @@ DOCUMENTATION-COMPRESSOR-FLAGS." (apply throw args)))))) (define (maybe-compress-directory directory regexp) - (or (not (directory-exists? directory)) - (match (find-files directory regexp) - (() ;nothing to compress - #t) - ((files ...) ;one or more files - (format #t - "compressing documentation in '~a' with ~s and flags ~s~%" - directory documentation-compressor - documentation-compressor-flags) - (call-with-values - (lambda () - (partition symbolic-link? files)) - (lambda (symlinks regular-files) - ;; Compress the non-symlink files, and adjust symlinks to refer - ;; to the compressed files. Leave files that have hard links - ;; unchanged ('gzip' would refuse to compress them anyway.) - ;; Also, do not retarget symbolic links pointing to other - ;; symbolic links, since these are not compressed. - (and (every retarget-symlink - (filter (lambda (symlink) - (and (not (points-to-symlink? symlink)) - (string-match regexp symlink))) - symlinks)) - (zero? - (apply system* documentation-compressor - (append documentation-compressor-flags - (remove has-links? regular-files))))))))))) + (when (directory-exists? directory) + (match (find-files directory regexp) + (() ;nothing to compress + #t) + ((files ...) ;one or more files + (format #t + "compressing documentation in '~a' with ~s and flags ~s~%" + directory documentation-compressor + documentation-compressor-flags) + (call-with-values + (lambda () + (partition symbolic-link? files)) + (lambda (symlinks regular-files) + ;; Compress the non-symlink files, and adjust symlinks to refer + ;; to the compressed files. Leave files that have hard links + ;; unchanged ('gzip' would refuse to compress them anyway.) + ;; Also, do not retarget symbolic links pointing to other + ;; symbolic links, since these are not compressed. + (for-each retarget-symlink + (filter (lambda (symlink) + (and (not (points-to-symlink? symlink)) + (string-match regexp symlink))) + symlinks)) + (apply invoke documentation-compressor + (append documentation-compressor-flags + (remove has-links? regular-files))))))))) (define (maybe-compress output) - (and (maybe-compress-directory (string-append output "/share/man") - "\\.[0-9]+$") - (maybe-compress-directory (string-append output "/share/info") - "\\.info(-[0-9]+)?$"))) + (maybe-compress-directory (string-append output "/share/man") + "\\.[0-9]+$") + (maybe-compress-directory (string-append output "/share/info") + "\\.info(-[0-9]+)?$")) (if compress-documentation? (match outputs (((names . directories) ...) - (every maybe-compress directories))) - (begin - (format #t "not compressing documentation~%") - #t))) + (for-each maybe-compress directories))) + (format #t "not compressing documentation~%")) + #t) (define* (delete-info-dir-file #:key outputs #:allow-other-keys) "Delete any 'share/info/dir' file from OUTPUTS." @@ -672,6 +756,7 @@ which cannot be found~%" (let-syntax ((phases (syntax-rules () ((_ p ...) `((p . ,p) ...))))) (phases set-SOURCE-DATE-EPOCH set-paths install-locale unpack + bootstrap patch-usr-bin-file patch-source-shebangs configure patch-generated-file-shebangs build check install @@ -704,17 +789,26 @@ in order. Return #t if all the PHASES succeeded, #f otherwise." ;; The trick is to #:allow-other-keys everywhere, so that each procedure in ;; PHASES can pick the keyword arguments it's interested in. - (every (match-lambda - ((name . proc) - (let ((start (current-time time-monotonic))) - (format #t "starting phase `~a'~%" name) - (let ((result (apply proc args)) - (end (current-time time-monotonic))) - (format #t "phase `~a' ~:[failed~;succeeded~] after ~,1f seconds~%" - name result - (elapsed-time end start)) - - ;; Dump the environment variables as a shell script, for handy debugging. - (system "export > $NIX_BUILD_TOP/environment-variables") - result)))) - phases)) + (for-each (match-lambda + ((name . proc) + (let ((start (current-time time-monotonic))) + (format #t "starting phase `~a'~%" name) + (let ((result (apply proc args)) + (end (current-time time-monotonic))) + (format #t "phase `~a' ~:[failed~;succeeded~] after ~,1f seconds~%" + name result + (elapsed-time end start)) + + ;; Issue a warning unless the result is #t. + (unless (eqv? result #t) + (format (current-error-port) "\ +## WARNING: phase `~a' returned `~s'. Return values other than #t +## are deprecated. Please migrate this package so that its phase +## procedures report errors by raising an exception, and otherwise +## always return #t.~%" + name result)) + + ;; Dump the environment variables as a shell script, for handy debugging. + (system "export > $NIX_BUILD_TOP/environment-variables") + result)))) + phases)) diff --git a/guix/build/gnu-dist.scm b/guix/build/gnu-dist.scm index ad69c6cf16..bf1c63cb85 100644 --- a/guix/build/gnu-dist.scm +++ b/guix/build/gnu-dist.scm @@ -1,5 +1,6 @@ ;;; GNU Guix --- Functional package management for GNU ;;; Copyright © 2013, 2015 Ludovic Courtès <ludo@gnu.org> +;;; Copyright © 2018 Mark H Weaver <mhw@netris.org> ;;; ;;; This file is part of GNU Guix. ;;; @@ -41,24 +42,22 @@ (begin (format #t "bootstrapping with `~a'...~%" file) - (zero? - (system* (string-append "./" file)))) + (invoke (string-append "./" file))) (try-files files ... (else fallback ...))))))) (try-files "bootstrap" "bootstrap.sh" "autogen" "autogen.sh" (else (format #t "bootstrapping with `autoreconf'...~%") - (zero? (system* "autoreconf" "-vfi")))))) + (invoke "autoreconf" "-vfi"))))) (define* (build #:key build-before-dist? make-flags (dist-target "distcheck") #:allow-other-keys #:rest args) - (and (or (not build-before-dist?) - (let ((build (assq-ref %standard-phases 'build))) - (apply build args))) - (begin - (format #t "building target `~a'~%" dist-target) - (zero? (apply system* "make" dist-target make-flags))))) + (when build-before-dist? + (let ((build (assq-ref %standard-phases 'build))) + (apply build args))) + (format #t "building target `~a'~%" dist-target) + (apply invoke "make" dist-target make-flags)) (define* (install-dist #:key outputs #:allow-other-keys) (let* ((out (assoc-ref outputs "out")) diff --git a/guix/build/go-build-system.scm b/guix/build/go-build-system.scm index 3114067aa9..7c833a616f 100644 --- a/guix/build/go-build-system.scm +++ b/guix/build/go-build-system.scm @@ -261,6 +261,7 @@ files in OUTPUTS." (define %standard-phases (modify-phases gnu:%standard-phases + (delete 'bootstrap) (delete 'configure) (delete 'patch-generated-file-shebangs) (replace 'unpack unpack) diff --git a/guix/build/haskell-build-system.scm b/guix/build/haskell-build-system.scm index 3afc37e16d..268d59c1be 100644 --- a/guix/build/haskell-build-system.scm +++ b/guix/build/haskell-build-system.scm @@ -266,6 +266,7 @@ given Haskell package." (define %standard-phases (modify-phases gnu:%standard-phases + (delete 'bootstrap) (add-before 'configure 'setup-compiler setup-compiler) (add-before 'install 'haddock haddock) (add-after 'install 'register register) diff --git a/guix/build/hg.scm b/guix/build/hg.scm index ae4574de57..ea51eb670b 100644 --- a/guix/build/hg.scm +++ b/guix/build/hg.scm @@ -1,5 +1,6 @@ ;;; GNU Guix --- Functional package management for GNU ;;; Copyright © 2016 Ricardo Wurmus <rekado@elephly.net> +;;; Copyright © 2018 Mark H Weaver <mhw@netris.org> ;;; ;;; This file is part of GNU Guix. ;;; @@ -33,19 +34,20 @@ "Fetch CHANGESET from URL into DIRECTORY. CHANGESET must be a valid Mercurial changeset identifier. Return #t on success, #f otherwise." - (and (zero? (system* hg-command - "clone" url - "--rev" changeset - ;; Disable TLS certificate verification. The hash of - ;; the checkout is known in advance anyway. - "--insecure" - directory)) - (with-directory-excursion directory - (begin - ;; The contents of '.hg' vary as a function of the current - ;; status of the Mercurial repo. Since we want a fixed - ;; output, this directory needs to be taken out. - (delete-file-recursively ".hg") - #t)))) + (invoke hg-command + "clone" url + "--rev" changeset + ;; Disable TLS certificate verification. The hash of + ;; the checkout is known in advance anyway. + "--insecure" + directory) + + ;; The contents of '.hg' vary as a function of the current + ;; status of the Mercurial repo. Since we want a fixed + ;; output, this directory needs to be taken out. + (with-directory-excursion directory + (delete-file-recursively ".hg")) + + #t) ;;; hg.scm ends here diff --git a/guix/build/minify-build-system.scm b/guix/build/minify-build-system.scm index 3580deda07..563def88e9 100644 --- a/guix/build/minify-build-system.scm +++ b/guix/build/minify-build-system.scm @@ -60,6 +60,7 @@ (define %standard-phases (modify-phases gnu:%standard-phases + (delete 'bootstrap) (delete 'configure) (replace 'build build) (delete 'check) diff --git a/guix/build/ocaml-build-system.scm b/guix/build/ocaml-build-system.scm index f77251ca09..d10431d8ef 100644 --- a/guix/build/ocaml-build-system.scm +++ b/guix/build/ocaml-build-system.scm @@ -103,6 +103,7 @@ ;; Everything is as with the GNU Build System except for the `configure' ;; , `build', `check' and `install' phases. (modify-phases gnu:%standard-phases + (delete 'bootstrap) (add-before 'configure 'ocaml-findlib-environment ocaml-findlib-environment) (add-before 'install 'prepare-install prepare-install) diff --git a/guix/build/perl-build-system.scm b/guix/build/perl-build-system.scm index b2024e4406..c5f5baa3a9 100644 --- a/guix/build/perl-build-system.scm +++ b/guix/build/perl-build-system.scm @@ -1,5 +1,6 @@ ;;; GNU Guix --- Functional package management for GNU -;;; Copyright © 2013, 2015 Ludovic Courtès <ludo@gnu.org> +;;; Copyright © 2013, 2015, 2018 Ludovic Courtès <ludo@gnu.org> +;;; Copyright © 2018 Mark H Weaver <mhw@netris.org> ;;; ;;; This file is part of GNU Guix. ;;; @@ -49,7 +50,7 @@ "INSTALLDIRS=site" "NO_PERLLOCAL=1" ,@make-maker-flags)) (else (error "no Build.PL or Makefile.PL found"))))) (format #t "running `perl' with arguments ~s~%" args) - (zero? (apply system* "perl" args)))) + (apply invoke "perl" args))) (define-syntax-rule (define-w/gnu-fallback* (name args ...) body ...) (define* (name args ... #:rest rest) @@ -58,24 +59,24 @@ (apply (assoc-ref gnu:%standard-phases 'name) rest)))) (define-w/gnu-fallback* (build) - (zero? (system* "./Build"))) + (invoke "./Build")) (define-w/gnu-fallback* (check #:key target (tests? (not target)) (test-flags '()) #:allow-other-keys) (if tests? - (zero? (apply system* "./Build" "test" test-flags)) - (begin - (format #t "test suite not run~%") - #t))) + (apply invoke "./Build" "test" test-flags) + (format #t "test suite not run~%")) + #t) (define-w/gnu-fallback* (install) - (zero? (system* "./Build" "install"))) + (invoke "./Build" "install")) (define %standard-phases ;; Everything is as with the GNU Build System except for the `configure', ;; `build', `check', and `install' phases. (modify-phases gnu:%standard-phases + (delete 'bootstrap) (replace 'install install) (replace 'check check) (replace 'build build) diff --git a/guix/build/python-build-system.scm b/guix/build/python-build-system.scm index dd07986b94..376ea81f1a 100644 --- a/guix/build/python-build-system.scm +++ b/guix/build/python-build-system.scm @@ -1,9 +1,10 @@ ;;; GNU Guix --- Functional package management for GNU -;;; Copyright © 2013, 2015, 2016 Ludovic Courtès <ludo@gnu.org> +;;; Copyright © 2013, 2015, 2016, 2018 Ludovic Courtès <ludo@gnu.org> ;;; Copyright © 2013 Andreas Enge <andreas@enge.fr> ;;; Copyright © 2013 Nikita Karetnikov <nikita@karetnikov.org> -;;; Copyright © 2015 Mark H Weaver <mhw@netris.org> +;;; Copyright © 2015, 2018 Mark H Weaver <mhw@netris.org> ;;; Copyright © 2016 Hartmut Goebel <h.goebel@crazy-compilers.com> +;;; Copyright © 2018 Ricardo Wurmus <rekado@elephly.net> ;;; ;;; This file is part of GNU Guix. ;;; @@ -120,14 +121,15 @@ (format #t "running \"python setup.py\" with command ~s and parameters ~s~%" command params) (if use-setuptools? - (zero? (apply system* "python" "-c" setuptools-shim - command params)) - (zero? (apply system* "python" "./setup.py" command params)))) + (apply invoke "python" "-c" setuptools-shim + command params) + (apply invoke "python" "./setup.py" command params))) (error "no setup.py found"))) (define* (build #:key use-setuptools? #:allow-other-keys) "Build a given Python package." - (call-setuppy "build" '() use-setuptools?)) + (call-setuppy "build" '() use-setuptools?) + #t) (define* (check #:key tests? test-target use-setuptools? #:allow-other-keys) "Run the test suite of a given Python package." @@ -137,15 +139,12 @@ ;; (given with `package_dir`). This will by copied to the output, too, ;; so we need to remove. (let ((before (find-files "build" "\\.egg-info$" #:directories? #t))) - (if (call-setuppy test-target '() use-setuptools?) - (let* ((after (find-files "build" "\\.egg-info$" #:directories? #t)) - (inter (lset-difference eqv? after before))) - (for-each delete-file-recursively inter) - #t) - #f)) - (begin - (format #t "test suite not run~%") - #t))) + (call-setuppy test-target '() use-setuptools?) + (let* ((after (find-files "build" "\\.egg-info$" #:directories? #t)) + (inter (lset-difference string=? after before))) + (for-each delete-file-recursively inter))) + (format #t "test suite not run~%")) + #t) (define (get-python-version python) (let* ((version (last (string-split python #\-))) @@ -182,7 +181,8 @@ when running checks after installing the package." "--root=/") '()) configure-flags))) - (call-setuppy "install" params use-setuptools?))) + (call-setuppy "install" params use-setuptools?) + #t)) (define* (wrap #:key inputs outputs #:allow-other-keys) (define (list-of-files dir) @@ -211,7 +211,8 @@ when running checks after installing the package." (let ((files (list-of-files dir))) (for-each (cut wrap-program <> var) files))) - bindirs))) + bindirs) + #t)) (define* (rename-pth-file #:key name inputs outputs #:allow-other-keys) "Rename easy-install.pth to NAME.pth to avoid conflicts between packages @@ -243,10 +244,21 @@ installed with setuptools." #t)) #t)) +(define* (enable-bytecode-determinism #:rest _) + "Improve determinism of pyc files." + ;; Set DETERMINISTIC_BUILD to override the embedded mtime in pyc files. + (setenv "DETERMINISTIC_BUILD" "1") + ;; Use deterministic hashes for strings, bytes, and datetime objects. + (setenv "PYTHONHASHSEED" "0") + #t) + (define %standard-phases ;; 'configure' phase is not needed. (modify-phases gnu:%standard-phases (add-after 'unpack 'ensure-no-mtimes-pre-1980 ensure-no-mtimes-pre-1980) + (add-after 'ensure-no-mtimes-pre-1980 'enable-bytecode-determinism + enable-bytecode-determinism) + (delete 'bootstrap) (delete 'configure) (replace 'install install) (replace 'check check) diff --git a/guix/build/r-build-system.scm b/guix/build/r-build-system.scm index 24aa73d4f2..5e18939d22 100644 --- a/guix/build/r-build-system.scm +++ b/guix/build/r-build-system.scm @@ -99,6 +99,7 @@ (define %standard-phases (modify-phases gnu:%standard-phases + (delete 'bootstrap) (delete 'configure) (delete 'build) (delete 'check) ; tests must be run after installation diff --git a/guix/build/ruby-build-system.scm b/guix/build/ruby-build-system.scm index 09ae2390a5..abef6937bc 100644 --- a/guix/build/ruby-build-system.scm +++ b/guix/build/ruby-build-system.scm @@ -308,6 +308,7 @@ extended with definitions for VARS." (define %standard-phases (modify-phases gnu:%standard-phases + (delete 'bootstrap) (delete 'configure) (replace 'unpack unpack) (add-before 'build 'extract-gemspec extract-gemspec) diff --git a/guix/build/scons-build-system.scm b/guix/build/scons-build-system.scm index a8760968d8..eb013f03b6 100644 --- a/guix/build/scons-build-system.scm +++ b/guix/build/scons-build-system.scm @@ -1,5 +1,6 @@ ;;; GNU Guix --- Functional package management for GNU ;;; Copyright © 2017 Arun Isaac <arunisaac@systemreboot.net> +;;; Copyright © 2018 Mark H Weaver <mhw@netris.org> ;;; ;;; This file is part of GNU Guix. ;;; @@ -31,27 +32,27 @@ (define* (build #:key outputs (scons-flags '()) (parallel-build? #t) #:allow-other-keys) (let ((out (assoc-ref outputs "out"))) (mkdir-p out) - (zero? (apply system* "scons" - (append (if parallel-build? - (list "-j" (number->string - (parallel-job-count))) - (list)) - scons-flags))))) + (apply invoke "scons" + (append (if parallel-build? + (list "-j" (number->string + (parallel-job-count))) + (list)) + scons-flags)))) (define* (check #:key tests? test-target (scons-flags '()) #:allow-other-keys) "Run the test suite of a given SCons application." - (cond (tests? - (zero? (apply system* "scons" test-target scons-flags))) - (else - (format #t "test suite not run~%") - #t))) + (if tests? + (apply invoke "scons" test-target scons-flags) + (format #t "test suite not run~%")) + #t) (define* (install #:key outputs (scons-flags '()) #:allow-other-keys) "Install a given SCons application." - (zero? (apply system* "scons" "install" scons-flags))) + (apply invoke "scons" "install" scons-flags)) (define %standard-phases (modify-phases gnu:%standard-phases + (delete 'bootstrap) (delete 'configure) (replace 'build build) (replace 'check check) diff --git a/guix/build/svn.scm b/guix/build/svn.scm index 31c30edaf5..252d1d4ee5 100644 --- a/guix/build/svn.scm +++ b/guix/build/svn.scm @@ -1,6 +1,7 @@ ;;; GNU Guix --- Functional package management for GNU ;;; Copyright © 2014 Ludovic Courtès <ludo@gnu.org> ;;; Copyright © 2014 Sree Harsha Totakura <sreeharsha@totakura.in> +;;; Copyright © 2018 Mark H Weaver <mhw@netris.org> ;;; ;;; This file is part of GNU Guix. ;;; @@ -34,23 +35,24 @@ (password #f)) "Fetch REVISION from URL into DIRECTORY. REVISION must be an integer, and a valid Subversion revision. Return #t on success, #f otherwise." - (and (zero? (apply system* svn-command - "checkout" "--non-interactive" - ;; Trust the server certificate. This is OK as we - ;; verify the checksum later. This can be removed when - ;; ca-certificates package is added. - "--trust-server-cert" "-r" (number->string revision) - `(,@(if (and user-name password) - (list (string-append "--username=" user-name) - (string-append "--password=" password)) - '()) - ,url ,directory))) - (with-directory-excursion directory - (begin - ;; The contents of '.svn' vary as a function of the current status - ;; of the repo. Since we want a fixed output, this directory needs - ;; to be taken out. - (delete-file-recursively ".svn") - #t)))) + (apply invoke svn-command + "checkout" "--non-interactive" + ;; Trust the server certificate. This is OK as we + ;; verify the checksum later. This can be removed when + ;; ca-certificates package is added. + "--trust-server-cert" "-r" (number->string revision) + `(,@(if (and user-name password) + (list (string-append "--username=" user-name) + (string-append "--password=" password)) + '()) + ,url ,directory)) + + ;; The contents of '.svn' vary as a function of the current status + ;; of the repo. Since we want a fixed output, this directory needs + ;; to be taken out. + (with-directory-excursion directory + (delete-file-recursively ".svn")) + + #t) ;;; svn.scm ends here diff --git a/guix/build/texlive-build-system.scm b/guix/build/texlive-build-system.scm index f6b9b96b87..1c393ecd9d 100644 --- a/guix/build/texlive-build-system.scm +++ b/guix/build/texlive-build-system.scm @@ -34,11 +34,11 @@ ;; Code: (define (compile-with-latex format file) - (zero? (system* format - "-interaction=batchmode" - "-output-directory=build" - (string-append "&" format) - file))) + (invoke format + "-interaction=batchmode" + "-output-directory=build" + (string-append "&" format) + file)) (define* (configure #:key inputs #:allow-other-keys) (let* ((out (string-append (getcwd) "/.texlive-union")) @@ -81,6 +81,7 @@ (define %standard-phases (modify-phases gnu:%standard-phases + (delete 'bootstrap) (replace 'configure configure) (replace 'build build) (delete 'check) diff --git a/guix/build/utils.scm b/guix/build/utils.scm index d7ed3d5177..c58a1afd1c 100644 --- a/guix/build/utils.scm +++ b/guix/build/utils.scm @@ -1,8 +1,8 @@ ;;; GNU Guix --- Functional package management for GNU -;;; Copyright © 2012, 2013, 2014, 2015, 2016, 2017 Ludovic Courtès <ludo@gnu.org> +;;; Copyright © 2012, 2013, 2014, 2015, 2016, 2017, 2018 Ludovic Courtès <ludo@gnu.org> ;;; Copyright © 2013 Andreas Enge <andreas@enge.fr> ;;; Copyright © 2013 Nikita Karetnikov <nikita@karetnikov.org> -;;; Copyright © 2015 Mark H Weaver <mhw@netris.org> +;;; Copyright © 2015, 2018 Mark H Weaver <mhw@netris.org> ;;; ;;; This file is part of GNU Guix. ;;; @@ -23,6 +23,8 @@ #:use-module (srfi srfi-1) #:use-module (srfi srfi-11) #:use-module (srfi srfi-26) + #:use-module (srfi srfi-34) + #:use-module (srfi srfi-35) #:use-module (srfi srfi-60) #:use-module (ice-9 ftw) #:use-module (ice-9 match) @@ -61,6 +63,7 @@ delete-file-recursively file-name-predicate find-files + false-if-file-not-found search-path-as-list set-path-environment-variable @@ -85,7 +88,14 @@ fold-port-matches remove-store-references wrap-program + invoke + invoke-error? + invoke-error-program + invoke-error-arguments + invoke-error-exit-status + invoke-error-term-signal + invoke-error-stop-signal locale-category->string)) @@ -396,6 +406,15 @@ also be included. If FAIL-ON-ERROR? is true, raise an exception upon error." stat) string<?))) +(define-syntax-rule (false-if-file-not-found exp) + "Evaluate EXP but return #f if it raises to 'system-error with ENOENT." + (catch 'system-error + (lambda () exp) + (lambda args + (if (= ENOENT (system-error-errno args)) + #f + (apply throw args))))) + ;;; ;;; Search paths. @@ -581,13 +600,25 @@ Where every <*-phase-name> is an expression evaluating to a symbol, and ((_ phases (add-after old-phase-name new-phase-name new-phase)) (alist-cons-after old-phase-name new-phase-name new-phase phases)))) +(define-condition-type &invoke-error &error + invoke-error? + (program invoke-error-program) + (arguments invoke-error-arguments) + (exit-status invoke-error-exit-status) + (term-signal invoke-error-term-signal) + (stop-signal invoke-error-stop-signal)) + (define (invoke program . args) - "Invoke PROGRAM with the given ARGS. Raise an error if the exit -code is non-zero; otherwise return #t." - (let ((status (apply system* program args))) - (unless (zero? status) - (error (format #f "program ~s exited with non-zero code" program) - status)) + "Invoke PROGRAM with the given ARGS. Raise an exception +if the exit code is non-zero; otherwise return #t." + (let ((code (apply system* program args))) + (unless (zero? code) + (raise (condition (&invoke-error + (program program) + (arguments args) + (exit-status (status:exit-val code)) + (term-signal (status:term-sig code)) + (stop-signal (status:stop-sig code)))))) #t)) diff --git a/guix/build/waf-build-system.scm b/guix/build/waf-build-system.scm index 85f0abcfd6..f0364e867d 100644 --- a/guix/build/waf-build-system.scm +++ b/guix/build/waf-build-system.scm @@ -70,6 +70,7 @@ (define %standard-phases (modify-phases gnu:%standard-phases + (delete 'bootstrap) (replace 'configure configure) (replace 'build build) (replace 'check check) |