~ruther/guix-local

c089511288820cfb3efc5295e572be24aa83f068 — Ludovic Courtès 13 years ago 8722e80
build-system/gnu: Patch shebangs in all the source; patch SHELL in makefiles.

* guix/build/utils.scm (call-with-ascii-input-file): New procedure.
  (patch-shebang): Use it.
  (patch-makefile-SHELL): New procedure.
* guix/build/gnu-build-system.scm (patch-source-shebangs): Patch all the
  files, not just executables; remove `po/Makefile.in.in' patching.
  (patch-generated-files): Rename to...
  (patch-generated-file-shebangs): ... this.  Patch executables and
  makefiles.
  (%standard-phases): Adjust accordingly.

* distro/packages/autotools.scm (libtool): Remove call to `patch-shebang'.
* distro/packages/base.scm (gcc-4.7): Likewise.
  (guile-final): Remove hack to skip `test-command-line-encoding2'.
* distro/packages/bash.scm (bash): Remove `pre-configure-phase'.
* distro/packages/readline.scm (readline): Likewise.
* distro/packages/ncurses.scm (ncurses): Remove `pre-install-phase'.
M distro/packages/autotools.scm => distro/packages/autotools.scm +0 -1
@@ 118,7 118,6 @@ Standards.  Automake requires the use of Autoconf.")
                            (string-append "-j" ncores)))

                   ;; Path references to /bin/sh.
                   (patch-shebang "libtoolize")
                   (let ((bash (assoc-ref inputs "bash")))
                     (substitute* "tests/testsuite"
                       (("/bin/sh")

M distro/packages/base.scm => distro/packages/base.scm +5 -26
@@ 428,9 428,6 @@ BFD (Binary File Descriptor) library, `gprof', `nm', `strip', etc.")
~a~%"
                            libc line))))

               ;; Adjust hard-coded #!/bin/sh.
               (patch-shebang "gcc/exec-tool.in")

               ;; Don't retain a dependency on the build-time sed.
               (substitute* "fixincludes/fixincl.x"
                 (("static char const sed_cmd_z\\[\\] =.*;")


@@ 967,29 964,11 @@ store.")
  ;; FIXME: The Libtool used here, specifically its `bin/libtool' script,
  ;; holds a dependency on the bootstrap Binutils.  Use multiple outputs for
  ;; Libtool, so that that dependency is isolated in the "bin" output.
  (let ((guile (package (inherit guile-2.0/fixed)
                 (arguments
                  (substitute-keyword-arguments
                      (package-arguments guile-2.0/fixed)
                    ((#:phases phases)
                     `(alist-cons-before
                       'patch-source-shebangs 'delete-encoded-test
                       (lambda* (#:key inputs #:allow-other-keys)
                         ;; %BOOTSTRAP-GUILE doesn't know about encodings other
                         ;; than UTF-8.  That test declares an ISO-8859-1
                         ;; encoding, which prevents `patch-shebang' from
                         ;; working, so skip it.
                         (call-with-output-file
                             "test-suite/standalone/test-command-line-encoding2"
                           (lambda (p)
                             (format p "#!~a/bin/bash\nexit 77"
                                     (assoc-ref inputs "bash")))))
                       ,phases)))))))
    (package-with-bootstrap-guile
     (package-with-explicit-inputs guile
                                   %boot4-inputs
                                   (current-source-location)
                                   #:guile %bootstrap-guile))))
  (package-with-bootstrap-guile
   (package-with-explicit-inputs guile-2.0/fixed
                                 %boot4-inputs
                                 (current-source-location)
                                 #:guile %bootstrap-guile)))

(define-public ld-wrapper
  ;; The final `ld' wrapper, which uses the final Guile.

M distro/packages/bash.scm => distro/packages/bash.scm +3 -13
@@ 33,13 33,6 @@
                                 "-DNON_INTERACTIVE_LOGIN_SHELLS"
                                 "-DSSH_SOURCE_BASHRC")
                               " "))
        (pre-configure-phase
         '(lambda* (#:key inputs #:allow-other-keys)
            ;; Use the right shell for makefiles.
            (let ((bash (assoc-ref inputs "bash")))
              (substitute* "configure"
                (("MAKE_SHELL=[^ ]+")
                 (format #f "MAKE_SHELL=~a/bin/bash" bash))))))
        (post-install-phase
         '(lambda* (#:key outputs #:allow-other-keys)
            ;; Add a `bash' -> `sh' link.


@@ 80,12 73,9 @@
        ;; for now.
        #:tests? #f

        #:phases (alist-cons-before
                  'configure 'pre-configure
                  ,pre-configure-phase
                  (alist-cons-after 'install 'post-install
                                    ,post-install-phase
                                    %standard-phases))))
        #:phases (alist-cons-after 'install 'post-install
                                   ,post-install-phase
                                   %standard-phases)))
     (synopsis "GNU Bourne-Again Shell")
     (description
      "Bash is the shell, or command language interpreter, that will appear in

M distro/packages/ncurses.scm => distro/packages/ncurses.scm +1 -7
@@ 28,9 28,6 @@
         '(lambda _
            (substitute* (find-files "." "Makefile.in")
              (("^SHELL[[:blank:]]*=.*$") ""))))
        (pre-install-phase
         '(lambda _
            (for-each patch-shebang (find-files "." "\\.sh$"))))
        (post-install-phase
         '(lambda* (#:key outputs #:allow-other-keys)
            (let ((out (assoc-ref outputs "out")))


@@ 93,10 90,7 @@
                     (alist-cons-before
                      'configure 'patch-makefile-SHELL
                      ,patch-makefile-phase
                      (alist-cons-before
                       'install 'pre-install-phase
                       ,pre-install-phase
                       %standard-phases)))
                      %standard-phases))

           ;; The `ncursesw5-config' has a #!/bin/sh that we don't want to
           ;; patch, to avoid retaining a reference to the build-time Bash.

M distro/packages/readline.scm => distro/packages/readline.scm +2 -12
@@ 36,14 36,7 @@
              (for-each (lambda (f) (chmod f #o755))
                        (find-files lib "\\.so"))
              (for-each (lambda (f) (chmod f #o644))
                        (find-files lib "\\.a")))))
        (pre-configure-phase
         '(lambda* (#:key inputs #:allow-other-keys)
            ;; Use the right shell for makefiles.
            (let ((bash (assoc-ref inputs "bash")))
              (substitute* "configure"
                (("^MAKE_SHELL=.*")
                 (format #f "MAKE_SHELL=~a/bin/bash" bash)))))))
                        (find-files lib "\\.a"))))))
    (package
      (name "readline")
      (version "6.2")


@@ 69,10 62,7 @@
                   #:phases (alist-cons-after
                             'install 'post-install
                             ,post-install-phase
                             (alist-cons-before
                              'configure 'pre-configure
                              ,pre-configure-phase
                              %standard-phases))))
                             %standard-phases)))
      (synopsis "GNU Readline, a library for interactive line editing")
      (description
       "The GNU Readline library provides a set of functions for use by

M guix/build/gnu-build-system.scm => guix/build/gnu-build-system.scm +15 -13
@@ 84,24 84,26 @@
       (chdir (first-subdirectory "."))))

(define* (patch-source-shebangs #:key source #:allow-other-keys)
  ;; Patch shebangs in executable source files.  Most scripts honor
  ;; $SHELL and $CONFIG_SHELL, but some don't, such as `mkinstalldirs'
  ;; or Automake's `missing' script.
  "Patch shebangs in all source files; this includes non-executable
files such as `.in' templates.  Most scripts honor $SHELL and
$CONFIG_SHELL, but some don't, such as `mkinstalldirs' or Automake's
`missing' script."
  (for-each patch-shebang
            (remove file-is-directory? (find-files "." ".*"))))

(define (patch-generated-file-shebangs . rest)
  "Patch shebangs in generated files, including `SHELL' variables in
makefiles."
  ;; Patch executable files, some of which might have been generated by
  ;; `configure'.
  (for-each patch-shebang
            (filter (lambda (file)
                      (and (executable-file? file)
                           (not (file-is-directory? file))))
                    (find-files "." ".*")))

  ;; Gettext-generated po/Makefile.in.in does not honor $SHELL.
  (let ((bash (search-path (search-path-as-string->list (getenv "PATH"))
                           "bash")))
    (when (file-exists? "po/Makefile.in.in")
      (substitute* "po/Makefile.in.in"
        (("^SHELL[[:blank:]]*=.*$")
         (string-append "SHELL = " bash "\n"))))))

(define patch-generated-files patch-source-shebangs)
  ;; Patch `SHELL' in generated makefiles.
  (for-each patch-makefile-SHELL (find-files "." "^(GNU)?[mM]akefile$")))

(define* (patch #:key (patches '()) (patch-flags '("--batch" "-p1"))
                #:allow-other-keys)


@@ 253,7 255,7 @@
  (let-syntax ((phases (syntax-rules ()
                         ((_ p ...) `((p . ,p) ...)))))
    (phases set-paths unpack patch
            patch-source-shebangs configure patch-generated-files
            patch-source-shebangs configure patch-generated-file-shebangs
            build check install
            patch-shebangs strip)))


M guix/build/utils.scm => guix/build/utils.scm +66 -24
@@ 27,6 27,7 @@
  #:use-module (rnrs io ports)
  #:export (directory-exists?
            executable-file?
            call-with-ascii-input-file
            with-directory-excursion
            mkdir-p
            copy-recursively


@@ 43,6 44,7 @@
            substitute*
            dump-port
            patch-shebang
            patch-makefile-SHELL
            fold-port-matches
            remove-store-references))



@@ 63,6 65,21 @@
    (and s
         (not (zero? (logand (stat:mode s) #o100))))))

(define (call-with-ascii-input-file file proc)
  "Open FILE as an ASCII or binary file, and pass the resulting port to
PROC.  FILE is closed when PROC's dynamic extent is left.  Return the
return values of applying PROC to the port."
  (let ((port (with-fluids ((%default-port-encoding #f))
                ;; Use "b" so that `open-file' ignores `coding:' cookies.
                (open-file file "rb"))))
    (dynamic-wind
      (lambda ()
        #t)
      (lambda ()
        (proc port))
      (lambda ()
        (close-input-port port)))))

(define-syntax-rule (with-directory-excursion dir body ...)
  "Run BODY with DIR as the process's current directory."
  (let ((init (getcwd)))


@@ 418,30 435,55 @@ patched, #f otherwise."
              (false-if-exception (delete-file template))
              #f))))

      (with-fluids ((%default-port-encoding #f))  ; ASCII
        (call-with-input-file file
          (lambda (p)
            (and (eq? #\# (read-char p))
                 (eq? #\! (read-char p))
                 (let ((line (false-if-exception (read-line p))))
                   (and=> (and line (regexp-exec shebang-rx line))
                          (lambda (m)
                            (let* ((cmd (match:substring m 1))
                                   (bin (search-path path
                                                     (basename cmd))))
                              (if bin
                                  (if (string=? bin cmd)
                                      #f          ; nothing to do
                                      (begin
                                        (format (current-error-port)
                                                "patch-shebang: ~a: changing `~a' to `~a'~%"
                                                file cmd bin)
                                        (patch p bin (match:substring m 2))))
                                  (begin
                                    (format (current-error-port)
                                            "patch-shebang: ~a: warning: no binary for interpreter `~a' found in $PATH~%"
                                            file (basename cmd))
                                    #f)))))))))))))
      (call-with-ascii-input-file file
        (lambda (p)
          (and (eq? #\# (read-char p))
               (eq? #\! (read-char p))
               (let ((line (false-if-exception (read-line p))))
                 (and=> (and line (regexp-exec shebang-rx line))
                        (lambda (m)
                          (let* ((cmd (match:substring m 1))
                                 (bin (search-path path (basename cmd))))
                            (if bin
                                (if (string=? bin cmd)
                                    #f            ; nothing to do
                                    (begin
                                      (format (current-error-port)
                                              "patch-shebang: ~a: changing `~a' to `~a'~%"
                                              file cmd bin)
                                      (patch p bin (match:substring m 2))))
                                (begin
                                  (format (current-error-port)
                                          "patch-shebang: ~a: warning: no binary for interpreter `~a' found in $PATH~%"
                                          file (basename cmd))
                                  #f))))))))))))

(define (patch-makefile-SHELL file)
  "Patch the `SHELL' variable in FILE, which is supposedly a makefile."

  ;; For instance, Gettext-generated po/Makefile.in.in do not honor $SHELL.

  ;; XXX: Unlike with `patch-shebang', FILE is always touched.

  (define (find-shell name)
    (let ((shell
           (search-path (search-path-as-string->list (getenv "PATH"))
                        name)))
      (unless shell
        (format (current-error-port)
                "patch-makefile-SHELL: warning: no binary for shell `~a' found in $PATH~%"
                name))
      shell))

  (substitute* file
    (("^ *SHELL[[:blank:]]*=[[:blank:]]*([[:graph:]]*/)([[:graph:]]+)[[:blank:]]*" _ dir shell)
     (let* ((old (string-append dir shell))
            (new (or (find-shell shell) old)))
       (unless (string=? new old)
         (format (current-error-port)
                 "patch-makefile-SHELL: ~a: changing `SHELL' from `~a' to `~a'~%"
                 file old new))
       (string-append "SHELL = " new "\n")))))

(define* (fold-port-matches proc init pattern port
                            #:optional (unmatched (lambda (_ r) r)))