1 ;;; GNU Guix --- Functional package management for GNU
2 ;;; Copyright © 2012, 2013, 2014, 2015, 2016, 2017 Ludovic Courtès <ludo@gnu.org>
4 ;;; This file is part of GNU Guix.
6 ;;; GNU Guix is free software; you can redistribute it and/or modify it
7 ;;; under the terms of the GNU General Public License as published by
8 ;;; the Free Software Foundation; either version 3 of the License, or (at
9 ;;; your option) any later version.
11 ;;; GNU Guix is distributed in the hope that it will be useful, but
12 ;;; WITHOUT ANY WARRANTY; without even the implied warranty of
13 ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 ;;; GNU General Public License for more details.
16 ;;; You should have received a copy of the GNU General Public License
17 ;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
19 (define-module (guix build gnu-build-system)
20 #:use-module (guix build utils)
21 #:use-module (guix build gremlin)
22 #:use-module (guix elf)
23 #:use-module (ice-9 ftw)
24 #:use-module (ice-9 match)
25 #:use-module (ice-9 regex)
26 #:use-module (ice-9 format)
27 #:use-module (srfi srfi-1)
28 #:use-module (srfi srfi-19)
29 #:use-module (srfi srfi-26)
30 #:use-module (rnrs io ports)
31 #:export (%standard-phases
36 ;; Standard build procedure for packages using the GNU Build System or
37 ;; something compatible ("./configure && make && make install"). This is the
44 ;; Guile 2.2.2 has a bug whereby 'time-monotonic' objects have seconds and
45 ;; nanoseconds swapped (fixed in Guile commit 886ac3e). Work around it.
46 (define time-monotonic time-tai))
49 (define* (set-SOURCE-DATE-EPOCH #:rest _)
50 "Set the 'SOURCE_DATE_EPOCH' environment variable. This is used by tools
51 that incorporate timestamps as a way to tell them to use a fixed timestamp.
52 See https://reproducible-builds.org/specs/source-date-epoch/."
53 (setenv "SOURCE_DATE_EPOCH" "1")
56 (define (first-subdirectory dir)
57 "Return the path of the first sub-directory of DIR."
58 (file-system-fold (lambda (path stat result)
60 (lambda (path stat result) result) ; leaf
61 (lambda (path stat result) result) ; down
62 (lambda (path stat result) result) ; up
63 (lambda (path stat result) ; skip
65 (lambda (path stat errno result) ; error
66 (error "first-subdirectory" (strerror errno)))
70 (define* (set-paths #:key target inputs native-inputs
71 (search-paths '()) (native-search-paths '())
73 (define input-directories
78 (define native-input-directories
82 (#f ; not cross compiling
85 ;; When cross building, $PATH must refer only to native (host) inputs since
86 ;; target inputs are not executable.
87 (set-path-environment-variable "PATH" '("bin" "sbin")
88 (append native-input-directories
93 (for-each (match-lambda
94 ((env-var (files ...) separator type pattern)
95 (set-path-environment-variable env-var files
102 (when native-search-paths
103 ;; Search paths for native inputs, when cross building.
104 (for-each (match-lambda
105 ((env-var (files ...) separator type pattern)
106 (set-path-environment-variable env-var files
107 native-input-directories
108 #:separator separator
111 native-search-paths))
115 (define* (install-locale #:key
116 (locale "en_US.utf8")
117 (locale-category LC_ALL)
119 "Try to install LOCALE; emit a warning if that fails. The main goal is to
120 use a UTF-8 locale so that Guile correctly interprets UTF-8 file names.
122 This phase must typically happen after 'set-paths' so that $LOCPATH has a
126 (setlocale locale-category locale)
128 ;; While we're at it, pass it to sub-processes.
129 (setenv (locale-category->string locale-category) locale)
131 (format (current-error-port) "using '~a' locale for category ~s~%"
132 locale (locale-category->string locale-category))
135 ;; This is known to fail for instance in early bootstrap where locales
136 ;; are not available.
137 (format (current-error-port)
138 "warning: failed to install '~a' locale: ~a~%"
139 locale (strerror (system-error-errno args)))
142 (define* (unpack #:key source #:allow-other-keys)
143 "Unpack SOURCE in the working directory, and change directory within the
144 source. When SOURCE is a directory, copy it in a sub-directory of the current
146 (if (file-is-directory? source)
151 ;; Preserve timestamps (set to the Epoch) on the copied tree so that
152 ;; things work deterministically.
153 (copy-recursively source "."
156 (and (if (string-suffix? ".zip" source)
157 (zero? (system* "unzip" source))
158 (zero? (system* "tar" "xvf" source)))
159 (chdir (first-subdirectory ".")))))
161 ;; See <http://bugs.gnu.org/17840>.
162 (define* (patch-usr-bin-file #:key native-inputs inputs
163 (patch-/usr/bin/file? #t)
165 "Patch occurrences of \"/usr/bin/file\" in all the executable 'configure'
166 files found in the source tree. This works around Libtool's Autoconf macros,
167 which generates invocations of \"/usr/bin/file\" that are used to determine
168 things like the ABI being used."
169 (when patch-/usr/bin/file?
170 (for-each (lambda (file)
171 (when (executable-file? file)
172 (patch-/usr/bin/file file)))
173 (find-files "." "^configure$")))
176 (define* (patch-source-shebangs #:key source #:allow-other-keys)
177 "Patch shebangs in all source files; this includes non-executable
178 files such as `.in' templates. Most scripts honor $SHELL and
179 $CONFIG_SHELL, but some don't, such as `mkinstalldirs' or Automake's
181 (for-each patch-shebang
184 ;; Filter out symlinks.
185 (eq? 'regular (stat:type stat)))
188 (define (patch-generated-file-shebangs . rest)
189 "Patch shebangs in generated files, including `SHELL' variables in
191 ;; Patch executable regular files, some of which might have been generated
193 (for-each patch-shebang
196 (and (eq? 'regular (stat:type stat))
197 (not (zero? (logand (stat:mode stat) #o100)))))
200 ;; Patch `SHELL' in generated makefiles.
201 (for-each patch-makefile-SHELL (find-files "." "^(GNU)?[mM]akefile$")))
203 (define* (configure #:key build target native-inputs inputs outputs
204 (configure-flags '()) out-of-source?
206 (define (package-name)
207 (let* ((out (assoc-ref outputs "out"))
208 (base (basename out))
209 (dash (string-rindex base #\-)))
210 ;; XXX: We'd rather use `package-name->name+version' or similar.
211 (string-drop (if dash
212 (substring base 0 dash)
214 (+ 1 (string-index base #\-)))))
216 (let* ((prefix (assoc-ref outputs "out"))
217 (bindir (assoc-ref outputs "bin"))
218 (libdir (assoc-ref outputs "lib"))
219 (includedir (assoc-ref outputs "include"))
220 (docdir (assoc-ref outputs "doc"))
221 (bash (or (and=> (assoc-ref (or native-inputs inputs) "bash")
222 (cut string-append <> "/bin/bash"))
224 (flags `(,@(if target ; cross building
225 '("CC_FOR_BUILD=gcc")
227 ,(string-append "CONFIG_SHELL=" bash)
228 ,(string-append "SHELL=" bash)
229 ,(string-append "--prefix=" prefix)
230 "--enable-fast-install" ; when using Libtool
232 ;; Produce multiple outputs when specific output names
235 (list (string-append "--bindir=" bindir "/bin"))
238 (cons (string-append "--libdir=" libdir "/lib")
242 (string-append "--includedir="
243 libdir "/include"))))
246 (list (string-append "--includedir="
247 includedir "/include"))
250 (list (string-append "--docdir=" docdir
251 "/share/doc/" (package-name)))
254 (list (string-append "--build=" build))
256 ,@(if target ; cross building
257 (list (string-append "--host=" target))
260 (abs-srcdir (getcwd))
261 (srcdir (if out-of-source?
262 (string-append "../" (basename abs-srcdir))
264 (format #t "source directory: ~s (relative from build: ~s)~%"
270 (format #t "build directory: ~s~%" (getcwd))
271 (format #t "configure flags: ~s~%" flags)
273 ;; Use BASH to reduce reliance on /bin/sh since it may not always be
275 ;; <http://thread.gmane.org/gmane.linux.distributions.nixos/9748>
276 ;; for a summary of the situation.)
278 ;; Call `configure' with a relative path. Otherwise, GCC's build system
279 ;; (for instance) records absolute source file names, which typically
280 ;; contain the hash part of the `.drv' file, leading to a reference leak.
281 (zero? (apply system* bash
282 (string-append srcdir "/configure")
285 (define* (build #:key (make-flags '()) (parallel-build? #t)
287 (zero? (apply system* "make"
288 `(,@(if parallel-build?
289 `("-j" ,(number->string (parallel-job-count)))
293 (define* (check #:key target (make-flags '()) (tests? (not target))
294 (test-target "check") (parallel-tests? #t)
297 (zero? (apply system* "make" test-target
298 `(,@(if parallel-tests?
299 `("-j" ,(number->string (parallel-job-count)))
303 (format #t "test suite not run~%")
306 (define* (install #:key (make-flags '()) #:allow-other-keys)
307 (zero? (apply system* "make" "install" make-flags)))
309 (define* (patch-shebangs #:key inputs outputs (patch-shebangs? #t)
311 (define (list-of-files dir)
312 (map (cut string-append dir "/" <>)
313 (or (scandir dir (lambda (f)
314 (let ((s (lstat (string-append dir "/" f))))
315 (eq? 'regular (stat:type s)))))
318 (define bin-directories
321 (list (string-append dir "/bin")
322 (string-append dir "/sbin")))))
324 (define output-bindirs
325 (append-map bin-directories outputs))
327 (define input-bindirs
328 ;; Shebangs should refer to binaries of the target system---i.e., from
329 ;; "inputs", not from "native-inputs".
330 (append-map bin-directories inputs))
332 (when patch-shebangs?
333 (let ((path (append output-bindirs input-bindirs)))
334 (for-each (lambda (dir)
335 (let ((files (list-of-files dir)))
336 (for-each (cut patch-shebang <> path) files)))
340 (define* (strip #:key target outputs (strip-binaries? #t)
341 (strip-command (if target
342 (string-append target "-strip")
344 (objcopy-command (if target
345 (string-append target "-objcopy")
347 (strip-flags '("--strip-debug"
348 "--enable-deterministic-archives"))
349 (strip-directories '("lib" "lib64" "libexec"
353 ;; If an output is called "debug", then that's where debugging information
354 ;; will be stored instead of being discarded.
355 (assoc-ref outputs "debug"))
357 (define debug-file-extension
358 ;; File name extension for debugging information.
361 (define (debug-file file)
362 ;; Return the name of the debug file for FILE, an absolute file name.
363 ;; Once installed in the user's profile, it is in $PROFILE/lib/debug/FILE,
364 ;; which is where GDB looks for it (info "(gdb) Separate Debug Files").
365 (string-append debug-output "/lib/debug/"
366 file debug-file-extension))
368 (define (make-debug-file file)
369 ;; Create a file in DEBUG-OUTPUT containing the debugging info of FILE.
370 (let ((debug (debug-file file)))
371 (mkdir-p (dirname debug))
372 (copy-file file debug)
373 (and (zero? (system* strip-command "--only-keep-debug" debug))
378 (define (add-debug-link file)
379 ;; Add a debug link in FILE (info "(binutils) strip").
381 ;; `objcopy --add-gnu-debuglink' wants to have the target of the debug
382 ;; link around so it can compute a CRC of that file (see the
383 ;; `bfd_fill_in_gnu_debuglink_section' function.) No reference to
384 ;; DEBUG-OUTPUT is kept because bfd keeps only the basename of the debug
386 (zero? (system* objcopy-command "--enable-deterministic-archives"
387 (string-append "--add-gnu-debuglink="
391 (define (strip-dir dir)
392 (format #t "stripping binaries in ~s with ~s and flags ~s~%"
393 dir strip-command strip-flags)
395 (format #t "debugging output written to ~s using ~s~%"
396 debug-output objcopy-command))
398 (for-each (lambda (file)
399 (and (or (elf-file? file) (ar-file? file))
400 (or (not debug-output)
401 (make-debug-file file))
403 ;; Ensure the file is writable.
404 (begin (make-file-writable file) #t)
406 (zero? (apply system* strip-command
407 (append strip-flags (list file))))
408 (or (not debug-output)
409 (add-debug-link file))))
412 ;; Ignore symlinks such as:
413 ;; libfoo.so -> libfoo.so.0.0.
414 (eq? 'regular (stat:type stat)))
417 (or (not strip-binaries?)
419 (append-map (match-lambda
421 (filter-map (lambda (d)
422 (let ((sub (string-append dir "/" d)))
423 (and (directory-exists? sub) sub)))
427 (define* (validate-runpath #:key
428 (validate-runpath? #t)
429 (elf-directories '("lib" "lib64" "libexec"
431 outputs #:allow-other-keys)
432 "When VALIDATE-RUNPATH? is true, validate that all the ELF files in
433 ELF-DIRECTORIES have their dependencies found in their 'RUNPATH'.
435 Since the ELF parser needs to have a copy of files in memory, better run this
436 phase after stripping."
437 (define (sub-directory parent)
439 (let ((directory (string-append parent "/" directory)))
440 (and (directory-exists? directory) directory))))
442 (define (validate directory)
443 (define (file=? file1 file2)
444 (let ((st1 (stat file1))
446 (= (stat:ino st1) (stat:ino st2))))
448 ;; There are always symlinks from '.so' to '.so.1' and so on, so delete
450 (let ((files (delete-duplicates (find-files directory (lambda (file stat)
453 (format (current-error-port)
454 "validating RUNPATH of ~a binaries in ~s...~%"
455 (length files) directory)
456 (every* validate-needed-in-runpath files)))
458 (if validate-runpath?
459 (let ((dirs (append-map (match-lambda
461 ;; The "debug" output is full of ELF files
462 ;; that are not worth checking.
465 (filter-map (sub-directory output)
468 (every* validate dirs))
470 (format (current-error-port) "skipping RUNPATH validation~%")
473 (define* (validate-documentation-location #:key outputs
475 "Documentation should go to 'share/info' and 'share/man', not just 'info/'
476 and 'man/'. This phase moves directories to the right place if needed."
477 (define (validate-sub-directory output sub-directory)
478 (let ((directory (string-append output "/" sub-directory)))
479 (when (directory-exists? directory)
480 (let ((target (string-append output "/share/" sub-directory)))
481 (format #t "moving '~a' to '~a'~%" directory target)
482 (mkdir-p (dirname target))
483 (rename-file directory target)))))
485 (define (validate-output output)
486 (for-each (cut validate-sub-directory output <>)
490 (((names . directories) ...)
491 (for-each validate-output directories)))
494 (define* (reset-gzip-timestamps #:key outputs #:allow-other-keys)
495 "Reset embedded timestamps in gzip files found in OUTPUTS."
496 (define (process-directory directory)
497 (let ((files (find-files directory
499 (and (eq? 'regular (stat:type stat))
500 (or (string-suffix? ".gz" file)
501 (string-suffix? ".tgz" file))
504 (for-each reset-gzip-timestamp files)))
507 (((names . directories) ...)
508 (for-each process-directory directories)))
511 (define* (compress-documentation #:key outputs
512 (compress-documentation? #t)
513 (documentation-compressor "gzip")
514 (documentation-compressor-flags
515 '("--best" "--no-name"))
516 (compressed-documentation-extension ".gz")
518 "When COMPRESS-DOCUMENTATION? is true, compress man pages and Info files
519 found in OUTPUTS using DOCUMENTATION-COMPRESSOR, called with
520 DOCUMENTATION-COMPRESSOR-FLAGS."
521 (define (retarget-symlink link)
522 (let ((target (readlink link)))
524 (symlink (string-append target compressed-documentation-extension)
527 (define (has-links? file)
528 ;; Return #t if FILE has hard links.
529 (> (stat:nlink (lstat file)) 1))
531 (define (points-to-symlink? symlink)
532 ;; Return #t if SYMLINK points to another symbolic link.
533 (let* ((target (readlink symlink))
534 (target-absolute (if (string-prefix? "/" target)
536 (string-append (dirname symlink)
540 (symbolic-link? target-absolute))
542 (if (= ENOENT (system-error-errno args))
544 (format (current-error-port)
545 "The symbolic link '~a' target is missing: '~a'\n"
546 symlink target-absolute)
548 (apply throw args))))))
550 (define (maybe-compress-directory directory regexp)
551 (or (not (directory-exists? directory))
552 (match (find-files directory regexp)
553 (() ;nothing to compress
555 ((files ...) ;one or more files
557 "compressing documentation in '~a' with ~s and flags ~s~%"
558 directory documentation-compressor
559 documentation-compressor-flags)
562 (partition symbolic-link? files))
563 (lambda (symlinks regular-files)
564 ;; Compress the non-symlink files, and adjust symlinks to refer
565 ;; to the compressed files. Leave files that have hard links
566 ;; unchanged ('gzip' would refuse to compress them anyway.)
567 ;; Also, do not retarget symbolic links pointing to other
568 ;; symbolic links, since these are not compressed.
569 (and (every retarget-symlink
570 (filter (lambda (symlink)
571 (and (not (points-to-symlink? symlink))
572 (string-match regexp symlink)))
575 (apply system* documentation-compressor
576 (append documentation-compressor-flags
577 (remove has-links? regular-files)))))))))))
579 (define (maybe-compress output)
580 (and (maybe-compress-directory (string-append output "/share/man")
582 (maybe-compress-directory (string-append output "/share/info")
583 "\\.info(-[0-9]+)?$")))
585 (if compress-documentation?
587 (((names . directories) ...)
588 (every maybe-compress directories)))
590 (format #t "not compressing documentation~%")
593 (define* (delete-info-dir-file #:key outputs #:allow-other-keys)
594 "Delete any 'share/info/dir' file from OUTPUTS."
595 (for-each (match-lambda
596 ((output . directory)
597 (let ((info-dir-file (string-append directory "/share/info/dir")))
598 (when (file-exists? info-dir-file)
599 (delete-file info-dir-file)))))
604 (define* (patch-dot-desktop-files #:key outputs inputs #:allow-other-keys)
605 "Replace any references to executables in '.desktop' files with their
606 absolute file names."
607 (define bin-directories
608 (append-map (match-lambda
610 (list (string-append directory "/bin")
611 (string-append directory "/sbin"))))
614 (define (which program)
615 (or (search-path bin-directories program)
617 (format (current-error-port)
618 "warning: '.desktop' file refers to '~a', \
619 which cannot be found~%"
623 (for-each (match-lambda
625 (let ((applications (string-append directory
626 "/share/applications")))
627 (when (directory-exists? applications)
628 (let ((files (find-files applications "\\.desktop$")))
629 (format #t "adjusting ~a '.desktop' files in ~s~%"
630 (length files) applications)
632 ;; '.desktop' files contain translations and are always
634 (with-fluids ((%default-port-encoding "UTF-8"))
636 (("^Exec=([^/[:blank:]\r\n]*)(.*)$" _ binary rest)
637 (string-append "Exec=" (which binary) rest))
638 (("^TryExec=([^/[:blank:]\r\n]*)(.*)$" _ binary rest)
639 (string-append "TryExec="
640 (which binary) rest)))))))))
644 (define %standard-phases
645 ;; Standard build phases, as a list of symbol/procedure pairs.
646 (let-syntax ((phases (syntax-rules ()
647 ((_ p ...) `((p . ,p) ...)))))
648 (phases set-SOURCE-DATE-EPOCH set-paths install-locale unpack
650 patch-source-shebangs configure patch-generated-file-shebangs
654 validate-documentation-location
656 patch-dot-desktop-files
657 reset-gzip-timestamps
658 compress-documentation)))
661 (define* (gnu-build #:key (source #f) (outputs #f) (inputs #f)
662 (phases %standard-phases)
665 "Build from SOURCE to OUTPUTS, using INPUTS, and by running all of PHASES
666 in order. Return #t if all the PHASES succeeded, #f otherwise."
667 (define (elapsed-time end start)
668 (let ((diff (time-difference end start)))
669 (+ (time-second diff)
670 (/ (time-nanosecond diff) 1e9))))
672 (setvbuf (current-output-port) _IOLBF)
673 (setvbuf (current-error-port) _IOLBF)
675 ;; Encoding/decoding errors shouldn't be silent.
676 (fluid-set! %default-port-conversion-strategy 'error)
678 ;; The trick is to #:allow-other-keys everywhere, so that each procedure in
679 ;; PHASES can pick the keyword arguments it's interested in.
682 (let ((start (current-time time-monotonic)))
683 (format #t "starting phase `~a'~%" name)
684 (let ((result (apply proc args))
685 (end (current-time time-monotonic)))
686 (format #t "phase `~a' ~:[failed~;succeeded~] after ~,1f seconds~%"
688 (elapsed-time end start))
690 ;; Dump the environment variables as a shell script, for handy debugging.
691 (system "export > $NIX_BUILD_TOP/environment-variables")