diff options
Diffstat (limited to 'guix/build')
| -rw-r--r-- | guix/build/gnu-build-system.scm | 34 | ||||
| -rw-r--r-- | guix/build/gremlin.scm | 130 | ||||
| -rw-r--r-- | guix/build/haskell-build-system.scm | 43 | ||||
| -rw-r--r-- | guix/build/meson-build-system.scm | 58 | ||||
| -rw-r--r-- | guix/build/python-build-system.scm | 2 | ||||
| -rw-r--r-- | guix/build/r-build-system.scm | 2 | ||||
| -rw-r--r-- | guix/build/svn.scm | 2 | ||||
| -rw-r--r-- | guix/build/utils.scm | 8 | 
8 files changed, 149 insertions, 130 deletions
| diff --git a/guix/build/gnu-build-system.scm b/guix/build/gnu-build-system.scm index be5ad78b93..e5f3197b0a 100644 --- a/guix/build/gnu-build-system.scm +++ b/guix/build/gnu-build-system.scm @@ -792,26 +792,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. -  (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)) +  (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)) -                   ;; Issue a warning unless the result is #t. -                   (unless (eqv? result #t) -                     (format (current-error-port) "\ +                ;; 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)) +                          name result)) -                   ;; Dump the environment variables as a shell script, for handy debugging. -                   (system "export > $NIX_BUILD_TOP/environment-variables") -                   result)))) -            phases)) +                ;; 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/gremlin.scm b/guix/build/gremlin.scm index bb019967e5..e8ea66dfb3 100644 --- a/guix/build/gremlin.scm +++ b/guix/build/gremlin.scm @@ -41,7 +41,8 @@              elf-dynamic-info-runpath              expand-origin -            validate-needed-in-runpath)) +            validate-needed-in-runpath +            strip-runpath))  ;;; Commentary:  ;;; @@ -99,10 +100,16 @@ dynamic linking information."  ;;     } d_un;  ;; } Elf64_Dyn; +(define-record-type <dynamic-entry> +  (dynamic-entry type value offset) +  dynamic-entry? +  (type   dynamic-entry-type)                     ;DT_* +  (value  dynamic-entry-value)                    ;string | number | ... +  (offset dynamic-entry-offset))                  ;integer +  (define (raw-dynamic-entries elf segment) -  "Return as a list of type/value pairs all the dynamic entries found in -SEGMENT, the 'PT_DYNAMIC' segment of ELF.  In the result, each car is a DT_ -value, and the interpretation of the cdr depends on the type." +  "Return as a list of <dynamic-entry> for the dynamic entries found in +SEGMENT, the 'PT_DYNAMIC' segment of ELF."    (define start      (elf-segment-offset segment))    (define bytes @@ -123,7 +130,9 @@ value, and the interpretation of the cdr depends on the type."            (if (= type DT_NULL)                    ;finished?                (reverse result)                (loop (+ offset (* 2 word-size)) -                    (alist-cons type value result))))))) +                    (cons (dynamic-entry type value +                                         (+ start offset word-size)) +                          result)))))))  (define (vma->offset elf vma)    "Convert VMA, a virtual memory address, to an offset within ELF. @@ -148,35 +157,33 @@ offset."  (define (dynamic-entries elf segment)    "Return all the dynamic entries found in SEGMENT, the 'PT_DYNAMIC' segment -of ELF, as a list of type/value pairs.  The type is a DT_ value, and the value -may be a string or an integer depending on the entry type (for instance, the -value of DT_NEEDED entries is a string.)" +of ELF, as a list of <dynamic-entry>.  The value of each entry may be a string +or an integer depending on the entry type (for instance, the value of +DT_NEEDED entries is a string.)  Likewise the offset is the offset within the +string table if the type is a string."    (define entries      (raw-dynamic-entries elf segment))    (define string-table-offset -    (any (match-lambda -            ((type . value) -             (and (= type DT_STRTAB) value)) -            (_ #f)) +    (any (lambda (entry) +           (and (= (dynamic-entry-type entry) DT_STRTAB) +                (dynamic-entry-value entry)))           entries)) -  (define (interpret-dynamic-entry type value) -    (cond ((memv type (list DT_NEEDED DT_SONAME DT_RPATH DT_RUNPATH)) -           (if string-table-offset -               (pointer->string -                (bytevector->pointer (elf-bytes elf) -                                     (vma->offset -                                      elf -                                      (+ string-table-offset value)))) -               value)) -          (else -           value))) +  (define (interpret-dynamic-entry entry) +    (let ((type  (dynamic-entry-type entry)) +          (value (dynamic-entry-value entry))) +      (cond ((memv type (list DT_NEEDED DT_SONAME DT_RPATH DT_RUNPATH)) +             (if string-table-offset +                 (let* ((offset (vma->offset elf (+ string-table-offset value))) +                        (value  (pointer->string +                                 (bytevector->pointer (elf-bytes elf) offset)))) +                   (dynamic-entry type value offset)) +                 (dynamic-entry type value (dynamic-entry-offset entry)))) +            (else +             (dynamic-entry type value (dynamic-entry-offset entry)))))) -  (map (match-lambda -         ((type . value) -          (cons type (interpret-dynamic-entry type value)))) -       entries)) +  (map interpret-dynamic-entry entries))  ;;; @@ -200,21 +207,29 @@ value of DT_NEEDED entries is a string.)"  (define (elf-dynamic-info elf)    "Return dynamic-link information for ELF as an <elf-dynamic-info> object, or  #f if ELF lacks dynamic-link information." +  (define (matching-entry type) +    (lambda (entry) +      (= type (dynamic-entry-type entry)))) +    (match (dynamic-link-segment elf)      (#f #f)      ((? elf-segment? dynamic)       (let ((entries (dynamic-entries elf dynamic))) -       (%elf-dynamic-info (assv-ref entries DT_SONAME) -                          (filter-map (match-lambda -                                        ((type . value) -                                         (and (= type DT_NEEDED) value)) -                                        (_ #f)) +       (%elf-dynamic-info (find (matching-entry DT_SONAME) entries) +                          (filter-map (lambda (entry) +                                        (and (= (dynamic-entry-type entry) +                                                DT_NEEDED) +                                             (dynamic-entry-value entry)))                                        entries) -                          (or (and=> (assv-ref entries DT_RPATH) -                                     search-path->list) +                          (or (and=> (find (matching-entry DT_RPATH) +                                           entries) +                                     (compose search-path->list +                                              dynamic-entry-value))                                '()) -                          (or (and=> (assv-ref entries DT_RUNPATH) -                                     search-path->list) +                          (or (and=> (find (matching-entry DT_RUNPATH) +                                           entries) +                                     (compose search-path->list +                                              dynamic-entry-value))                                '()))))))  (define %libc-libraries @@ -306,4 +321,47 @@ be found in RUNPATH ~s~%"            ;;   (format (current-error-port) "~a is OK~%" file))            (null? not-found)))))) +(define (strip-runpath file) +  "Remove from the DT_RUNPATH of FILE any entries that are not necessary +according to DT_NEEDED." +  (define (minimal-runpath needed runpath) +    (filter (lambda (directory) +              (and (string-prefix? "/" directory) +                   (any (lambda (lib) +                          (file-exists? (string-append directory "/" lib))) +                        needed))) +            runpath)) + +  (define port +    (open-file file "r+b")) + +  (catch #t +    (lambda () +      (let* ((elf      (parse-elf (get-bytevector-all port))) +             (entries  (dynamic-entries elf (dynamic-link-segment elf))) +             (needed   (filter-map (lambda (entry) +                                     (and (= (dynamic-entry-type entry) +                                             DT_NEEDED) +                                          (dynamic-entry-value entry))) +                                   entries)) +             (runpath  (find (lambda (entry) +                               (= DT_RUNPATH (dynamic-entry-type entry))) +                             entries)) +             (old      (search-path->list +                        (dynamic-entry-value runpath))) +             (new      (minimal-runpath needed old))) +        (unless (equal? old new) +          (format (current-error-port) +                  "~a: stripping RUNPATH to ~s (removed ~s)~%" +                  file new +                  (lset-difference string=? old new)) +          (seek port (dynamic-entry-offset runpath) SEEK_SET) +          (put-bytevector port (string->utf8 (string-join new ":"))) +          (put-u8 port 0)) +        (close-port port) +        new)) +    (lambda (key . args) +      (false-if-exception (close-port port)) +      (apply throw key args)))) +  ;;; gremlin.scm ends here diff --git a/guix/build/haskell-build-system.scm b/guix/build/haskell-build-system.scm index 26519ce5a6..5a72d22842 100644 --- a/guix/build/haskell-build-system.scm +++ b/guix/build/haskell-build-system.scm @@ -2,6 +2,7 @@  ;;; Copyright © 2015 Federico Beffa <beffa@fbengineering.ch>  ;;; Copyright © 2015 Eric Bavier <bavier@member.fsf.org>  ;;; Copyright © 2015 Paul van der Walt <paul@denknerd.org> +;;; Copyright © 2018 Ricardo Wurmus <rekado@elephly.net>  ;;;  ;;; This file is part of GNU Guix.  ;;; @@ -178,9 +179,10 @@ first match and return the content of the group."                    (unless (file-exists? dest)                      (copy-file file dest))))                conf-files) -    (zero? (system* "ghc-pkg" -                    (string-append "--package-db=" %tmp-db-dir) -                    "recache")))) +    (invoke "ghc-pkg" +            (string-append "--package-db=" %tmp-db-dir) +            "recache") +    #t))  (define* (register #:key name system inputs outputs #:allow-other-keys)    "Generate the compiler registration and binary package database files for a @@ -238,32 +240,31 @@ given Haskell package."            (list (string-append "--gen-pkg-config=" config-file))))      (run-setuphs "register" params)      ;; The conf file is created only when there is a library to register. -    (or (not (file-exists? config-file)) -        (begin -          (mkdir-p config-dir) -          (let* ((config-file-name+id -                  (call-with-ascii-input-file config-file (cut grep id-rx <>)))) -            (install-transitive-deps config-file %tmp-db-dir config-dir) -            (rename-file config-file -                         (string-append config-dir "/" -                                        config-file-name+id ".conf")) -            (zero? (system* "ghc-pkg" -                            (string-append "--package-db=" config-dir) -                            "recache"))))))) +    (unless (file-exists? config-file) +      (mkdir-p config-dir) +      (let* ((config-file-name+id +              (call-with-ascii-input-file config-file (cut grep id-rx <>)))) +        (install-transitive-deps config-file %tmp-db-dir config-dir) +        (rename-file config-file +                     (string-append config-dir "/" +                                    config-file-name+id ".conf")) +        (invoke "ghc-pkg" +                (string-append "--package-db=" config-dir) +                "recache"))) +    #t))  (define* (check #:key tests? test-target #:allow-other-keys)    "Run the test suite of a given Haskell package."    (if tests?        (run-setuphs test-target '()) -      (begin -        (format #t "test suite not run~%") -        #t))) +      (format #t "test suite not run~%")) +  #t)  (define* (haddock #:key outputs haddock? haddock-flags #:allow-other-keys)    "Run the test suite of a given Haskell package." -  (if haddock? -      (run-setuphs "haddock" haddock-flags) -      #t)) +  (when haddock? +    (run-setuphs "haddock" haddock-flags)) +  #t)  (define %standard-phases    (modify-phases gnu:%standard-phases diff --git a/guix/build/meson-build-system.scm b/guix/build/meson-build-system.scm index 80e54723c5..d0975fcab0 100644 --- a/guix/build/meson-build-system.scm +++ b/guix/build/meson-build-system.scm @@ -1,5 +1,6 @@  ;;; GNU Guix --- Functional package management for GNU  ;;; Copyright © 2017 Peter Mikkelsen <petermikkelsen10@gmail.com> +;;; Copyright © 2018 Ricardo Wurmus <rekado@elephly.net>  ;;; Copyright © 2018 Marius Bakke <mbakke@fastmail.com>  ;;;  ;;; This file is part of GNU Guix. @@ -21,7 +22,6 @@    #:use-module ((guix build gnu-build-system) #:prefix gnu:)    #:use-module ((guix build glib-or-gtk-build-system) #:prefix glib-or-gtk:)    #:use-module (guix build utils) -  #:use-module (guix build rpath)    #:use-module (guix build gremlin)    #:use-module (guix elf)    #:use-module (ice-9 match) @@ -71,49 +71,19 @@                "1"))    (if tests?        (invoke "ninja" test-target) -      (begin -        (format #t "test suite not run~%") -        #t))) +      (format #t "test suite not run~%")) +  #t)  (define* (install #:rest args)    (invoke "ninja" "install")) -(define* (fix-runpath #:key (elf-directories '("lib" "lib64" "libexec" -                                               "bin" "sbin")) -                      outputs #:allow-other-keys) -  "Try to make sure all ELF files in ELF-DIRECTORIES are able to find their -local dependencies in their RUNPATH, by searching for the needed libraries in -the directories of the package, and adding them to the RUNPATH if needed. -Also shrink the RUNPATH to what is needed, +(define* (shrink-runpath #:key (elf-directories '("lib" "lib64" "libexec" +                                                  "bin" "sbin")) +                         outputs #:allow-other-keys) +  "Go through all ELF files from ELF-DIRECTORIES and shrink the RUNPATH  since a lot of directories are left over from the build phase of meson,  for example libraries only needed for the tests." -  ;; Find the directories (if any) that contains DEP-NAME.  The directories -  ;; searched are the ones that ELF-FILES are in. -  (define (find-deps dep-name elf-files) -    (map dirname (filter (lambda (file) -                           (string=? dep-name (basename file))) -                         elf-files))) - -  ;; Return a list of libraries that FILE needs. -  (define (file-needed file) -    (let* ((elf (call-with-input-file file -                  (compose parse-elf get-bytevector-all))) -           (dyninfo (elf-dynamic-info elf))) -      (if dyninfo -          (elf-dynamic-info-needed dyninfo) -          '()))) - - -  ;; If FILE needs any libs that are part of ELF-FILES, the RUNPATH -  ;; is modified accordingly. -  (define (handle-file file elf-files) -    (let* ((dep-dirs (concatenate (map (lambda (dep-name) -                                         (find-deps dep-name elf-files)) -                                       (file-needed file))))) -      (unless (null? dep-dirs) -        (augment-rpath file (string-join dep-dirs ":"))))) -    (define handle-output      (match-lambda        ((output . directory) @@ -129,10 +99,7 @@ for example libraries only needed for the tests."                (elf-list (concatenate (map (lambda (dir)                                              (find-files dir elf-pred))                                            existing-elf-dirs)))) -         (for-each (lambda (elf-file) -                     (invoke "patchelf" "--shrink-rpath" elf-file) -                     (handle-file elf-file elf-list)) -                   elf-list))))) +         (for-each strip-runpath elf-list)))))    (for-each handle-output outputs)    #t) @@ -144,13 +111,8 @@ for example libraries only needed for the tests."      (replace 'configure configure)      (replace 'build build)      (replace 'check check) -    ;; XXX: We used to have 'fix-runpath' here, but it appears no longer -    ;; necessary with newer Meson.  However on 'core-updates' there is a -    ;; useful 'strip-runpath' procedure to ensure no bogus directories in -    ;; RUNPATH (remember that we tell Meson to not touch RUNPATH in -    ;; (@ (gnu packages build-tools) meson-for-build)), so it should be -    ;; re-added there sans the augment-rpath calls (which are not needed). -    (replace 'install install))) +    (replace 'install install) +    (add-after 'strip 'shrink-runpath shrink-runpath)))  (define* (meson-build #:key inputs phases                        #:allow-other-keys #:rest args) diff --git a/guix/build/python-build-system.scm b/guix/build/python-build-system.scm index 376ea81f1a..5bb0ba49d5 100644 --- a/guix/build/python-build-system.scm +++ b/guix/build/python-build-system.scm @@ -246,8 +246,6 @@ installed with setuptools."  (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) diff --git a/guix/build/r-build-system.scm b/guix/build/r-build-system.scm index 4d8ac5b479..2c0b322da9 100644 --- a/guix/build/r-build-system.scm +++ b/guix/build/r-build-system.scm @@ -44,7 +44,7 @@        (unless (zero? code)          (raise (condition ((@@ (guix build utils) &invoke-error)                             (program "R") -                           (arguments (string-append params " " command)) +                           (arguments (cons command params))                             (exit-status (status:exit-val code))                             (term-signal (status:term-sig code))                             (stop-signal (status:stop-sig code))))))))) diff --git a/guix/build/svn.scm b/guix/build/svn.scm index 252d1d4ee5..913f89471b 100644 --- a/guix/build/svn.scm +++ b/guix/build/svn.scm @@ -51,7 +51,7 @@ valid Subversion revision.  Return #t on success, #f otherwise."    ;; of the repo.  Since we want a fixed output, this directory needs    ;; to be taken out.    (with-directory-excursion directory -    (delete-file-recursively ".svn")) +    (for-each delete-file-recursively (find-files "." "^\\.svn$" #:directories? #t)))    #t) diff --git a/guix/build/utils.scm b/guix/build/utils.scm index c58a1afd1c..5fe3286843 100644 --- a/guix/build/utils.scm +++ b/guix/build/utils.scm @@ -1057,11 +1057,11 @@ with definitions for VARS."         (format #f "export ~a=\"~a\""                 var (string-join rest sep)))        ((var sep 'prefix rest) -       (format #f "export ~a=\"~a${~a~a+~a}$~a\"" -               var (string-join rest sep) var sep sep var)) +       (format #f "export ~a=\"~a${~a:+~a}$~a\"" +               var (string-join rest sep) var sep var))        ((var sep 'suffix rest) -       (format #f "export ~a=\"$~a${~a~a+~a}~a\"" -               var var var sep sep (string-join rest sep))) +       (format #f "export ~a=\"$~a${~a+~a}~a\"" +               var var var sep (string-join rest sep)))        ((var '= rest)         (format #f "export ~a=\"~a\""                 var (string-join rest ":"))) | 
