gnu-build-system.scm 39 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938
  1. ;;; GNU Guix --- Functional package management for GNU
  2. ;;; Copyright © 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021 Ludovic Courtès <ludo@gnu.org>
  3. ;;; Copyright © 2018 Mark H Weaver <mhw@netris.org>
  4. ;;; Copyright © 2020 Brendan Tildesley <mail@brendan.scot>
  5. ;;; Copyright © 2021 Maxim Cournoyer <maxim.cournoyer@gmail.com>
  6. ;;;
  7. ;;; This file is part of GNU Guix.
  8. ;;;
  9. ;;; GNU Guix is free software; you can redistribute it and/or modify it
  10. ;;; under the terms of the GNU General Public License as published by
  11. ;;; the Free Software Foundation; either version 3 of the License, or (at
  12. ;;; your option) any later version.
  13. ;;;
  14. ;;; GNU Guix is distributed in the hope that it will be useful, but
  15. ;;; WITHOUT ANY WARRANTY; without even the implied warranty of
  16. ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17. ;;; GNU General Public License for more details.
  18. ;;;
  19. ;;; You should have received a copy of the GNU General Public License
  20. ;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
  21. (define-module (guix build gnu-build-system)
  22. #:use-module (guix build utils)
  23. #:use-module (guix build gremlin)
  24. #:use-module (guix elf)
  25. #:use-module (ice-9 ftw)
  26. #:use-module (ice-9 match)
  27. #:use-module (ice-9 regex)
  28. #:use-module (ice-9 format)
  29. #:use-module (ice-9 ftw)
  30. #:use-module (srfi srfi-1)
  31. #:use-module (srfi srfi-19)
  32. #:use-module (srfi srfi-34)
  33. #:use-module (srfi srfi-35)
  34. #:use-module (srfi srfi-26)
  35. #:use-module (rnrs io ports)
  36. #:export (%standard-phases
  37. %license-file-regexp
  38. %bootstrap-scripts
  39. dump-file-contents
  40. gnu-build))
  41. ;; Commentary:
  42. ;;
  43. ;; Standard build procedure for packages using the GNU Build System or
  44. ;; something compatible ("./configure && make && make install"). This is the
  45. ;; builder-side code.
  46. ;;
  47. ;; Code:
  48. (cond-expand
  49. (guile-2.2
  50. ;; Guile 2.2.2 has a bug whereby 'time-monotonic' objects have seconds and
  51. ;; nanoseconds swapped (fixed in Guile commit 886ac3e). Work around it.
  52. (define time-monotonic time-tai))
  53. (else #t))
  54. (define* (set-SOURCE-DATE-EPOCH #:rest _)
  55. "Set the 'SOURCE_DATE_EPOCH' environment variable. This is used by tools
  56. that incorporate timestamps as a way to tell them to use a fixed timestamp.
  57. See https://reproducible-builds.org/specs/source-date-epoch/."
  58. (setenv "SOURCE_DATE_EPOCH" "1"))
  59. (define (first-subdirectory directory)
  60. "Return the file name of the first sub-directory of DIRECTORY or false, when
  61. there are none."
  62. (match (scandir directory
  63. (lambda (file)
  64. (and (not (member file '("." "..")))
  65. (file-is-directory? (string-append directory "/"
  66. file)))))
  67. ((first . _) first)
  68. (_ #f)))
  69. (define* (set-paths #:key target inputs native-inputs
  70. (search-paths '()) (native-search-paths '())
  71. #:allow-other-keys)
  72. (define input-directories
  73. ;; The "source" input can be a directory, but we don't want it for search
  74. ;; paths. See <https://issues.guix.gnu.org/44924>.
  75. (match (alist-delete "source" inputs)
  76. (((_ . dir) ...)
  77. dir)))
  78. (define native-input-directories
  79. (match native-inputs
  80. (((_ . dir) ...)
  81. dir)
  82. (#f ; not cross compiling
  83. '())))
  84. ;; Tell 'ld-wrapper' to disallow non-store libraries.
  85. (setenv "GUIX_LD_WRAPPER_ALLOW_IMPURITIES" "no")
  86. ;; When cross building, $PATH must refer only to native (host) inputs since
  87. ;; target inputs are not executable.
  88. (set-path-environment-variable "PATH" '("bin" "sbin")
  89. (append native-input-directories
  90. (if target
  91. '()
  92. input-directories)))
  93. (for-each (match-lambda
  94. ((env-var (files ...) separator type pattern)
  95. (set-path-environment-variable env-var files
  96. input-directories
  97. #:separator separator
  98. #:type type
  99. #:pattern pattern)))
  100. search-paths)
  101. (when native-search-paths
  102. ;; Search paths for native inputs, when cross building.
  103. (for-each (match-lambda
  104. ((env-var (files ...) separator type pattern)
  105. (set-path-environment-variable env-var files
  106. native-input-directories
  107. #:separator separator
  108. #:type type
  109. #:pattern pattern)))
  110. native-search-paths)))
  111. (define* (install-locale #:key
  112. (locale "en_US.utf8")
  113. (locale-category LC_ALL)
  114. #:allow-other-keys)
  115. "Try to install LOCALE; emit a warning if that fails. The main goal is to
  116. use a UTF-8 locale so that Guile correctly interprets UTF-8 file names.
  117. This phase must typically happen after 'set-paths' so that $LOCPATH has a
  118. chance to be set."
  119. (catch 'system-error
  120. (lambda ()
  121. (setlocale locale-category locale)
  122. ;; While we're at it, pass it to sub-processes.
  123. (setenv (locale-category->string locale-category) locale)
  124. (format (current-error-port) "using '~a' locale for category ~s~%"
  125. locale (locale-category->string locale-category)))
  126. (lambda args
  127. ;; This is known to fail for instance in early bootstrap where locales
  128. ;; are not available.
  129. (format (current-error-port)
  130. "warning: failed to install '~a' locale: ~a~%"
  131. locale (strerror (system-error-errno args))))))
  132. (define* (unpack #:key source #:allow-other-keys)
  133. "Unpack SOURCE in the working directory, and change directory within the
  134. source. When SOURCE is a directory, copy it in a sub-directory of the current
  135. working directory."
  136. (if (file-is-directory? source)
  137. (begin
  138. (mkdir "source")
  139. (chdir "source")
  140. ;; Preserve timestamps (set to the Epoch) on the copied tree so that
  141. ;; things work deterministically.
  142. (copy-recursively source "."
  143. #:keep-mtime? #t)
  144. ;; Make the source checkout files writable, for convenience.
  145. (for-each (lambda (f)
  146. (false-if-exception (make-file-writable f)))
  147. (find-files ".")))
  148. (begin
  149. (cond
  150. ((string-suffix? ".zip" source)
  151. (invoke "unzip" source))
  152. ((tarball? source)
  153. (invoke "tar" "xvf" source))
  154. (else
  155. (let ((name (strip-store-file-name source))
  156. (command (compressor source)))
  157. (copy-file source name)
  158. (when command
  159. (invoke command "--decompress" name)))))
  160. ;; Attempt to change into child directory.
  161. (and=> (first-subdirectory ".") chdir))))
  162. (define %bootstrap-scripts
  163. ;; Typical names of Autotools "bootstrap" scripts.
  164. '("bootstrap" "bootstrap.sh" "autogen.sh"))
  165. (define* (bootstrap #:key (bootstrap-scripts %bootstrap-scripts)
  166. #:allow-other-keys)
  167. "If the code uses Autotools and \"configure\" is missing, run
  168. \"autoreconf\". Otherwise do nothing."
  169. ;; Note: Run that right after 'unpack' so that the generated files are
  170. ;; visible when the 'patch-source-shebangs' phase runs.
  171. (define (script-exists? file)
  172. (and (file-exists? file)
  173. (not (file-is-directory? file))))
  174. (if (not (script-exists? "configure"))
  175. ;; First try one of the BOOTSTRAP-SCRIPTS. If none exists, and it's
  176. ;; clearly an Autoconf-based project, run 'autoreconf'. Otherwise, do
  177. ;; nothing (perhaps the user removed or overrode the 'configure' phase.)
  178. (let ((script (find script-exists? bootstrap-scripts)))
  179. ;; GNU packages often invoke the 'git-version-gen' script from
  180. ;; 'configure.ac' so make sure it has a valid shebang.
  181. (false-if-file-not-found
  182. (patch-shebang "build-aux/git-version-gen"))
  183. (if script
  184. (let ((script (string-append "./" script)))
  185. (setenv "NOCONFIGURE" "true")
  186. (format #t "running '~a'~%" script)
  187. (if (executable-file? script)
  188. (begin
  189. (patch-shebang script)
  190. (invoke script))
  191. (invoke "sh" script))
  192. ;; Let's clean up after ourselves.
  193. (unsetenv "NOCONFIGURE"))
  194. (if (or (file-exists? "configure.ac")
  195. (file-exists? "configure.in"))
  196. (invoke "autoreconf" "-vif")
  197. (format #t "no 'configure.ac' or anything like that, \
  198. doing nothing~%"))))
  199. (format #t "GNU build system bootstrapping not needed~%")))
  200. ;; See <http://bugs.gnu.org/17840>.
  201. (define* (patch-usr-bin-file #:key native-inputs inputs
  202. (patch-/usr/bin/file? #t)
  203. #:allow-other-keys)
  204. "Patch occurrences of \"/usr/bin/file\" in all the executable 'configure'
  205. files found in the source tree. This works around Libtool's Autoconf macros,
  206. which generates invocations of \"/usr/bin/file\" that are used to determine
  207. things like the ABI being used."
  208. (when patch-/usr/bin/file?
  209. (for-each (lambda (file)
  210. (when (executable-file? file)
  211. (patch-/usr/bin/file file)))
  212. (find-files "." "^configure$"))))
  213. (define* (patch-source-shebangs #:key source #:allow-other-keys)
  214. "Patch shebangs in all source files; this includes non-executable
  215. files such as `.in' templates. Most scripts honor $SHELL and
  216. $CONFIG_SHELL, but some don't, such as `mkinstalldirs' or Automake's
  217. `missing' script."
  218. (for-each patch-shebang
  219. (find-files "."
  220. (lambda (file stat)
  221. ;; Filter out symlinks.
  222. (eq? 'regular (stat:type stat)))
  223. #:stat lstat)))
  224. (define (patch-generated-file-shebangs . rest)
  225. "Patch shebangs in generated files, including `SHELL' variables in
  226. makefiles."
  227. ;; Patch executable regular files, some of which might have been generated
  228. ;; by `configure'.
  229. (for-each patch-shebang
  230. (find-files "."
  231. (lambda (file stat)
  232. (and (eq? 'regular (stat:type stat))
  233. (not (zero? (logand (stat:mode stat) #o100)))))
  234. #:stat lstat))
  235. ;; Patch `SHELL' in generated makefiles.
  236. (for-each patch-makefile-SHELL (find-files "." "^(GNU)?[mM]akefile$")))
  237. (define* (configure #:key build target native-inputs inputs outputs
  238. (configure-flags '()) out-of-source?
  239. #:allow-other-keys)
  240. (define (package-name)
  241. (let* ((out (assoc-ref outputs "out"))
  242. (base (basename out))
  243. (dash (string-rindex base #\-)))
  244. ;; XXX: We'd rather use `package-name->name+version' or similar.
  245. (string-drop (if dash
  246. (substring base 0 dash)
  247. base)
  248. (+ 1 (string-index base #\-)))))
  249. (let* ((prefix (assoc-ref outputs "out"))
  250. (bindir (assoc-ref outputs "bin"))
  251. (libdir (assoc-ref outputs "lib"))
  252. (includedir (assoc-ref outputs "include"))
  253. (docdir (assoc-ref outputs "doc"))
  254. (bash (or (and=> (assoc-ref (or native-inputs inputs) "bash")
  255. (cut string-append <> "/bin/bash"))
  256. "/bin/sh"))
  257. (flags `(,@(if target ; cross building
  258. '("CC_FOR_BUILD=gcc")
  259. '())
  260. ,(string-append "CONFIG_SHELL=" bash)
  261. ,(string-append "SHELL=" bash)
  262. ,(string-append "--prefix=" prefix)
  263. "--enable-fast-install" ; when using Libtool
  264. ;; Produce multiple outputs when specific output names
  265. ;; are recognized.
  266. ,@(if bindir
  267. (list (string-append "--bindir=" bindir "/bin"))
  268. '())
  269. ,@(if libdir
  270. (cons (string-append "--libdir=" libdir "/lib")
  271. (if includedir
  272. '()
  273. (list
  274. (string-append "--includedir="
  275. libdir "/include"))))
  276. '())
  277. ,@(if includedir
  278. (list (string-append "--includedir="
  279. includedir "/include"))
  280. '())
  281. ,@(if docdir
  282. (list (string-append "--docdir=" docdir
  283. "/share/doc/" (package-name)))
  284. '())
  285. ,@(if build
  286. (list (string-append "--build=" build))
  287. '())
  288. ,@(if target ; cross building
  289. (list (string-append "--host=" target))
  290. '())
  291. ,@configure-flags))
  292. (abs-srcdir (getcwd))
  293. (srcdir (if out-of-source?
  294. (string-append "../" (basename abs-srcdir))
  295. ".")))
  296. (format #t "source directory: ~s (relative from build: ~s)~%"
  297. abs-srcdir srcdir)
  298. (if out-of-source?
  299. (begin
  300. (mkdir "../build")
  301. (chdir "../build")))
  302. (format #t "build directory: ~s~%" (getcwd))
  303. (format #t "configure flags: ~s~%" flags)
  304. ;; Use BASH to reduce reliance on /bin/sh since it may not always be
  305. ;; reliable (see
  306. ;; <http://thread.gmane.org/gmane.linux.distributions.nixos/9748>
  307. ;; for a summary of the situation.)
  308. ;;
  309. ;; Call `configure' with a relative path. Otherwise, GCC's build system
  310. ;; (for instance) records absolute source file names, which typically
  311. ;; contain the hash part of the `.drv' file, leading to a reference leak.
  312. (apply invoke bash
  313. (string-append srcdir "/configure")
  314. flags)))
  315. (define* (build #:key (make-flags '()) (parallel-build? #t)
  316. #:allow-other-keys)
  317. (apply invoke "make"
  318. `(,@(if parallel-build?
  319. `("-j" ,(number->string (parallel-job-count)))
  320. '())
  321. ,@make-flags)))
  322. (define* (dump-file-contents directory file-regexp
  323. #:optional (port (current-error-port)))
  324. "Dump to PORT the contents of files in DIRECTORY that match FILE-REGEXP."
  325. (define (dump file)
  326. (let ((prefix (string-append "\n--- " file " ")))
  327. (display (if (< (string-length prefix) 78)
  328. (string-pad-right prefix 78 #\-)
  329. prefix)
  330. port)
  331. (display "\n\n" port)
  332. (call-with-input-file file
  333. (lambda (log)
  334. (dump-port log port)))
  335. (display "\n" port)))
  336. (for-each dump (find-files directory file-regexp)))
  337. (define %test-suite-log-regexp
  338. ;; Name of test suite log files as commonly found in GNU-based build systems
  339. ;; and CMake.
  340. "^(test-?suite\\.log|LastTestFailed\\.log)$")
  341. (define* (check #:key target (make-flags '()) (tests? (not target))
  342. (test-target "check") (parallel-tests? #t)
  343. (test-suite-log-regexp %test-suite-log-regexp)
  344. #:allow-other-keys)
  345. (if tests?
  346. (guard (c ((invoke-error? c)
  347. ;; Dump the test suite log to facilitate debugging.
  348. (display "\nTest suite failed, dumping logs.\n"
  349. (current-error-port))
  350. (dump-file-contents "." test-suite-log-regexp)
  351. (raise c)))
  352. (apply invoke "make" test-target
  353. `(,@(if parallel-tests?
  354. `("-j" ,(number->string (parallel-job-count)))
  355. '())
  356. ,@make-flags)))
  357. (format #t "test suite not run~%")))
  358. (define* (install #:key (make-flags '()) #:allow-other-keys)
  359. (apply invoke "make" "install" make-flags))
  360. (define* (patch-shebangs #:key inputs outputs (patch-shebangs? #t)
  361. #:allow-other-keys)
  362. (define (list-of-files dir)
  363. (map (cut string-append dir "/" <>)
  364. (or (scandir dir (lambda (f)
  365. (let ((s (lstat (string-append dir "/" f))))
  366. (eq? 'regular (stat:type s)))))
  367. '())))
  368. (define bin-directories
  369. (match-lambda
  370. ((_ . dir)
  371. (list (string-append dir "/bin")
  372. (string-append dir "/sbin")
  373. (string-append dir "/libexec")))))
  374. (define output-bindirs
  375. (append-map bin-directories outputs))
  376. (define input-bindirs
  377. ;; Shebangs should refer to binaries of the target system---i.e., from
  378. ;; "inputs", not from "native-inputs".
  379. (append-map bin-directories inputs))
  380. (when patch-shebangs?
  381. (let ((path (append output-bindirs input-bindirs)))
  382. (for-each (lambda (dir)
  383. (let ((files (list-of-files dir)))
  384. (for-each (cut patch-shebang <> path) files)))
  385. output-bindirs))))
  386. (define* (strip #:key target outputs (strip-binaries? #t)
  387. (strip-command (if target
  388. (string-append target "-strip")
  389. "strip"))
  390. (objcopy-command (if target
  391. (string-append target "-objcopy")
  392. "objcopy"))
  393. (strip-flags '("--strip-unneeded"
  394. "--enable-deterministic-archives"))
  395. (strip-directories '("lib" "lib64" "libexec"
  396. "bin" "sbin"))
  397. #:allow-other-keys)
  398. (define debug-output
  399. ;; If an output is called "debug", then that's where debugging information
  400. ;; will be stored instead of being discarded.
  401. (assoc-ref outputs "debug"))
  402. (define debug-file-extension
  403. ;; File name extension for debugging information.
  404. ".debug")
  405. (define (debug-file file)
  406. ;; Return the name of the debug file for FILE, an absolute file name.
  407. ;; Once installed in the user's profile, it is in $PROFILE/lib/debug/FILE,
  408. ;; which is where GDB looks for it (info "(gdb) Separate Debug Files").
  409. (string-append debug-output "/lib/debug/"
  410. file debug-file-extension))
  411. (define (make-debug-file file)
  412. ;; Create a file in DEBUG-OUTPUT containing the debugging info of FILE.
  413. (let ((debug (debug-file file)))
  414. (mkdir-p (dirname debug))
  415. (copy-file file debug)
  416. (invoke strip-command "--only-keep-debug" debug)
  417. (chmod debug #o400)))
  418. (define (add-debug-link file)
  419. ;; Add a debug link in FILE (info "(binutils) strip").
  420. ;; `objcopy --add-gnu-debuglink' wants to have the target of the debug
  421. ;; link around so it can compute a CRC of that file (see the
  422. ;; `bfd_fill_in_gnu_debuglink_section' function.) No reference to
  423. ;; DEBUG-OUTPUT is kept because bfd keeps only the basename of the debug
  424. ;; file.
  425. (invoke objcopy-command "--enable-deterministic-archives"
  426. (string-append "--add-gnu-debuglink="
  427. (debug-file file))
  428. file))
  429. (define (strip-dir dir)
  430. (format #t "stripping binaries in ~s with ~s and flags ~s~%"
  431. dir strip-command strip-flags)
  432. (when debug-output
  433. (format #t "debugging output written to ~s using ~s~%"
  434. debug-output objcopy-command))
  435. (for-each (lambda (file)
  436. (when (or (elf-file? file) (ar-file? file))
  437. ;; If an error occurs while processing a file, issue a
  438. ;; warning and continue to the next file.
  439. (guard (c ((invoke-error? c)
  440. (format (current-error-port)
  441. "warning: ~a: program ~s exited\
  442. ~@[ with non-zero exit status ~a~]\
  443. ~@[ terminated by signal ~a~]~%"
  444. file
  445. (invoke-error-program c)
  446. (invoke-error-exit-status c)
  447. (invoke-error-term-signal c))))
  448. (when debug-output
  449. (make-debug-file file))
  450. ;; Ensure the file is writable.
  451. (make-file-writable file)
  452. (apply invoke strip-command
  453. (append strip-flags (list file)))
  454. (when debug-output
  455. (add-debug-link file)))))
  456. (find-files dir
  457. (lambda (file stat)
  458. ;; Ignore symlinks such as:
  459. ;; libfoo.so -> libfoo.so.0.0.
  460. (eq? 'regular (stat:type stat)))
  461. #:stat lstat)))
  462. (when strip-binaries?
  463. (for-each
  464. strip-dir
  465. (append-map (match-lambda
  466. ((_ . dir)
  467. (filter-map (lambda (d)
  468. (let ((sub (string-append dir "/" d)))
  469. (and (directory-exists? sub) sub)))
  470. strip-directories)))
  471. outputs))))
  472. (define* (validate-runpath #:key
  473. (validate-runpath? #t)
  474. (elf-directories '("lib" "lib64" "libexec"
  475. "bin" "sbin"))
  476. outputs #:allow-other-keys)
  477. "When VALIDATE-RUNPATH? is true, validate that all the ELF files in
  478. ELF-DIRECTORIES have their dependencies found in their 'RUNPATH'.
  479. Since the ELF parser needs to have a copy of files in memory, better run this
  480. phase after stripping."
  481. (define (sub-directory parent)
  482. (lambda (directory)
  483. (let ((directory (string-append parent "/" directory)))
  484. (and (directory-exists? directory) directory))))
  485. (define (validate directory)
  486. (define (file=? file1 file2)
  487. (let ((st1 (stat file1))
  488. (st2 (stat file2)))
  489. (= (stat:ino st1) (stat:ino st2))))
  490. ;; There are always symlinks from '.so' to '.so.1' and so on, so delete
  491. ;; duplicates.
  492. (let ((files (delete-duplicates (find-files directory (lambda (file stat)
  493. (elf-file? file)))
  494. file=?)))
  495. (format (current-error-port)
  496. "validating RUNPATH of ~a binaries in ~s...~%"
  497. (length files) directory)
  498. (every* validate-needed-in-runpath files)))
  499. (if validate-runpath?
  500. (let ((dirs (append-map (match-lambda
  501. (("debug" . _)
  502. ;; The "debug" output is full of ELF files
  503. ;; that are not worth checking.
  504. '())
  505. ((name . output)
  506. (filter-map (sub-directory output)
  507. elf-directories)))
  508. outputs)))
  509. (unless (every* validate dirs)
  510. (error "RUNPATH validation failed")))
  511. (format (current-error-port) "skipping RUNPATH validation~%")))
  512. (define* (validate-documentation-location #:key outputs
  513. #:allow-other-keys)
  514. "Documentation should go to 'share/info' and 'share/man', not just 'info/'
  515. and 'man/'. This phase moves directories to the right place if needed."
  516. (define (validate-sub-directory output sub-directory)
  517. (let ((directory (string-append output "/" sub-directory)))
  518. (when (directory-exists? directory)
  519. (let ((target (string-append output "/share/" sub-directory)))
  520. (format #t "moving '~a' to '~a'~%" directory target)
  521. (mkdir-p (dirname target))
  522. (rename-file directory target)))))
  523. (define (validate-output output)
  524. (for-each (cut validate-sub-directory output <>)
  525. '("man" "info")))
  526. (match outputs
  527. (((names . directories) ...)
  528. (for-each validate-output directories))))
  529. (define* (reset-gzip-timestamps #:key outputs #:allow-other-keys)
  530. "Reset embedded timestamps in gzip files found in OUTPUTS."
  531. (define (process-directory directory)
  532. (let ((files (find-files directory
  533. (lambda (file stat)
  534. (and (eq? 'regular (stat:type stat))
  535. (or (string-suffix? ".gz" file)
  536. (string-suffix? ".tgz" file))
  537. (gzip-file? file)))
  538. #:stat lstat)))
  539. ;; Ensure the files are writable.
  540. (for-each make-file-writable files)
  541. (for-each reset-gzip-timestamp files)))
  542. (match outputs
  543. (((names . directories) ...)
  544. (for-each process-directory directories))))
  545. (define* (compress-documentation #:key outputs
  546. (compress-documentation? #t)
  547. (documentation-compressor "gzip")
  548. (documentation-compressor-flags
  549. '("--best" "--no-name"))
  550. (compressed-documentation-extension ".gz")
  551. #:allow-other-keys)
  552. "When COMPRESS-DOCUMENTATION? is true, compress man pages and Info files
  553. found in OUTPUTS using DOCUMENTATION-COMPRESSOR, called with
  554. DOCUMENTATION-COMPRESSOR-FLAGS."
  555. (define (retarget-symlink link)
  556. (let ((target (readlink link)))
  557. (delete-file link)
  558. (symlink (string-append target compressed-documentation-extension)
  559. (string-append link compressed-documentation-extension))))
  560. (define (has-links? file)
  561. ;; Return #t if FILE has hard links.
  562. (> (stat:nlink (lstat file)) 1))
  563. (define (points-to-symlink? symlink)
  564. ;; Return #t if SYMLINK points to another symbolic link.
  565. (let* ((target (readlink symlink))
  566. (target-absolute (if (string-prefix? "/" target)
  567. target
  568. (string-append (dirname symlink)
  569. "/" target))))
  570. (catch 'system-error
  571. (lambda ()
  572. (symbolic-link? target-absolute))
  573. (lambda args
  574. (if (= ENOENT (system-error-errno args))
  575. (begin
  576. (format (current-error-port)
  577. "The symbolic link '~a' target is missing: '~a'\n"
  578. symlink target-absolute)
  579. #f)
  580. (apply throw args))))))
  581. (define (maybe-compress-directory directory regexp)
  582. (when (directory-exists? directory)
  583. (match (find-files directory regexp)
  584. (() ;nothing to compress
  585. #t)
  586. ((files ...) ;one or more files
  587. (format #t
  588. "compressing documentation in '~a' with ~s and flags ~s~%"
  589. directory documentation-compressor
  590. documentation-compressor-flags)
  591. (call-with-values
  592. (lambda ()
  593. (partition symbolic-link? files))
  594. (lambda (symlinks regular-files)
  595. ;; Compress the non-symlink files, and adjust symlinks to refer
  596. ;; to the compressed files. Leave files that have hard links
  597. ;; unchanged ('gzip' would refuse to compress them anyway.)
  598. ;; Also, do not retarget symbolic links pointing to other
  599. ;; symbolic links, since these are not compressed.
  600. (for-each retarget-symlink
  601. (filter (lambda (symlink)
  602. (and (not (points-to-symlink? symlink))
  603. (string-match regexp symlink)))
  604. symlinks))
  605. (apply invoke documentation-compressor
  606. (append documentation-compressor-flags
  607. (remove has-links? regular-files)))))))))
  608. (define (maybe-compress output)
  609. (maybe-compress-directory (string-append output "/share/man")
  610. "\\.[0-9]+$")
  611. (maybe-compress-directory (string-append output "/share/info")
  612. "\\.info(-[0-9]+)?$"))
  613. (if compress-documentation?
  614. (match outputs
  615. (((names . directories) ...)
  616. (for-each maybe-compress directories)))
  617. (format #t "not compressing documentation~%")))
  618. (define* (delete-info-dir-file #:key outputs #:allow-other-keys)
  619. "Delete any 'share/info/dir' file from OUTPUTS."
  620. (for-each (match-lambda
  621. ((output . directory)
  622. (let ((info-dir-file (string-append directory "/share/info/dir")))
  623. (when (file-exists? info-dir-file)
  624. (delete-file info-dir-file)))))
  625. outputs))
  626. (define* (patch-dot-desktop-files #:key outputs inputs #:allow-other-keys)
  627. "Replace any references to executables in '.desktop' files with their
  628. absolute file names."
  629. (define bin-directories
  630. (append-map (match-lambda
  631. ((_ . directory)
  632. (list (string-append directory "/bin")
  633. (string-append directory "/sbin"))))
  634. outputs))
  635. (define (which program)
  636. (or (search-path bin-directories program)
  637. (begin
  638. (format (current-error-port)
  639. "warning: '.desktop' file refers to '~a', \
  640. which cannot be found~%"
  641. program)
  642. program)))
  643. (for-each (match-lambda
  644. ((_ . directory)
  645. (let ((applications (string-append directory
  646. "/share/applications")))
  647. (when (directory-exists? applications)
  648. (let ((files (find-files applications "\\.desktop$")))
  649. (format #t "adjusting ~a '.desktop' files in ~s~%"
  650. (length files) applications)
  651. ;; '.desktop' files contain translations and are always
  652. ;; UTF-8-encoded.
  653. (with-fluids ((%default-port-encoding "UTF-8"))
  654. (substitute* files
  655. (("^Exec=([^/[:blank:]\r\n]*)(.*)$" _ binary rest)
  656. (string-append "Exec=" (which binary) rest))
  657. (("^TryExec=([^/[:blank:]\r\n]*)(.*)$" _ binary rest)
  658. (string-append "TryExec="
  659. (which binary) rest)))))))))
  660. outputs))
  661. (define* (make-dynamic-linker-cache #:key outputs
  662. (make-dynamic-linker-cache? #t)
  663. #:allow-other-keys)
  664. "Create a dynamic linker cache under 'etc/ld.so.cache' in each of the
  665. OUTPUTS. This reduces application startup time by avoiding the 'stat' storm
  666. that traversing all the RUNPATH entries entails."
  667. (define (make-cache-for-output directory)
  668. (define bin-directories
  669. (filter-map (lambda (sub-directory)
  670. (let ((directory (string-append directory "/"
  671. sub-directory)))
  672. (and (directory-exists? directory)
  673. directory)))
  674. '("bin" "sbin" "libexec")))
  675. (define programs
  676. ;; Programs that can benefit from the ld.so cache.
  677. (append-map (lambda (directory)
  678. (if (directory-exists? directory)
  679. (find-files directory
  680. (lambda (file stat)
  681. (and (executable-file? file)
  682. (elf-file? file))))
  683. '()))
  684. bin-directories))
  685. (define library-path
  686. ;; Directories containing libraries that PROGRAMS depend on,
  687. ;; recursively.
  688. (delete-duplicates
  689. (append-map (lambda (program)
  690. (map dirname (file-needed/recursive program)))
  691. programs)))
  692. (define cache-file
  693. (string-append directory "/etc/ld.so.cache"))
  694. (define ld.so.conf
  695. (string-append (or (getenv "TMPDIR") "/tmp")
  696. "/ld.so.conf"))
  697. (unless (null? library-path)
  698. (mkdir-p (dirname cache-file))
  699. (guard (c ((invoke-error? c)
  700. ;; Do not treat 'ldconfig' failure as an error.
  701. (format (current-error-port)
  702. "warning: 'ldconfig' failed:~%")
  703. (report-invoke-error c (current-error-port))))
  704. ;; Create a config file to tell 'ldconfig' where to look for the
  705. ;; libraries that PROGRAMS need.
  706. (call-with-output-file ld.so.conf
  707. (lambda (port)
  708. (for-each (lambda (directory)
  709. (display directory port)
  710. (newline port))
  711. library-path)))
  712. (invoke "ldconfig" "-f" ld.so.conf "-C" cache-file)
  713. (format #t "created '~a' from ~a library search path entries~%"
  714. cache-file (length library-path)))))
  715. (if make-dynamic-linker-cache?
  716. (match outputs
  717. (((_ . directories) ...)
  718. (for-each make-cache-for-output directories)))
  719. (format #t "ld.so cache not built~%")))
  720. (define %license-file-regexp
  721. ;; Regexp matching license files.
  722. "^(COPYING.*|LICEN[CS]E.*|[Ll]icen[cs]e.*|Copy[Rr]ight(\\.(txt|md))?)$")
  723. (define* (install-license-files #:key outputs
  724. (license-file-regexp %license-file-regexp)
  725. out-of-source?
  726. #:allow-other-keys)
  727. "Install license files matching LICENSE-FILE-REGEXP to 'share/doc'."
  728. (define (find-source-directory package)
  729. ;; For an out-of-source build, guess the source directory location
  730. ;; relative to the current directory. Return #f on failure.
  731. (match (scandir ".."
  732. (lambda (file)
  733. (and (not (member file '("." ".." "build")))
  734. (file-is-directory?
  735. (string-append "../" file)))))
  736. (() ;hmm, no source
  737. #f)
  738. ((source) ;only one other file
  739. (string-append "../" source))
  740. ((directories ...) ;pick the most likely one
  741. ;; This happens for example with libstdc++, which lives within the GCC
  742. ;; source tree.
  743. (any (lambda (directory)
  744. (and (string-prefix? package directory)
  745. (string-append "../" directory)))
  746. directories))))
  747. (define (copy-to-directories directories sub-directory)
  748. (lambda (file)
  749. (for-each (if (file-is-directory? file)
  750. (cut copy-recursively file <>)
  751. (cut install-file file <>))
  752. (map (cut string-append <> "/" sub-directory)
  753. directories))))
  754. (let* ((regexp (make-regexp license-file-regexp))
  755. (out (or (assoc-ref outputs "out")
  756. (match outputs
  757. (((_ . output) _ ...)
  758. output))))
  759. (package (strip-store-file-name out))
  760. (outputs (match outputs
  761. (((_ . outputs) ...)
  762. outputs)))
  763. (source (if out-of-source?
  764. (find-source-directory
  765. (package-name->name+version package))
  766. "."))
  767. (files (and source
  768. (scandir source
  769. (lambda (file)
  770. (regexp-exec regexp file))))))
  771. (if files
  772. (begin
  773. (format #t "installing ~a license files from '~a'~%"
  774. (length files) source)
  775. (for-each (copy-to-directories outputs
  776. (string-append "share/doc/"
  777. package))
  778. (map (cut string-append source "/" <>) files)))
  779. (format (current-error-port)
  780. "failed to find license files~%"))))
  781. (define %standard-phases
  782. ;; Standard build phases, as a list of symbol/procedure pairs.
  783. (let-syntax ((phases (syntax-rules ()
  784. ((_ p ...) `((p . ,p) ...)))))
  785. (phases set-SOURCE-DATE-EPOCH set-paths install-locale unpack
  786. bootstrap
  787. patch-usr-bin-file
  788. patch-source-shebangs configure patch-generated-file-shebangs
  789. build check install
  790. patch-shebangs strip
  791. validate-runpath
  792. validate-documentation-location
  793. delete-info-dir-file
  794. patch-dot-desktop-files
  795. make-dynamic-linker-cache
  796. install-license-files
  797. reset-gzip-timestamps
  798. compress-documentation)))
  799. (define* (gnu-build #:key (source #f) (outputs #f) (inputs #f)
  800. (phases %standard-phases)
  801. #:allow-other-keys
  802. #:rest args)
  803. "Build from SOURCE to OUTPUTS, using INPUTS, and by running all of PHASES
  804. in order. Return #t if all the PHASES succeeded, #f otherwise."
  805. (define (elapsed-time end start)
  806. (let ((diff (time-difference end start)))
  807. (+ (time-second diff)
  808. (/ (time-nanosecond diff) 1e9))))
  809. (setvbuf (current-output-port) 'line)
  810. (setvbuf (current-error-port) 'line)
  811. ;; Encoding/decoding errors shouldn't be silent.
  812. (fluid-set! %default-port-conversion-strategy 'error)
  813. (guard (c ((invoke-error? c)
  814. (report-invoke-error c)
  815. (exit 1)))
  816. ;; The trick is to #:allow-other-keys everywhere, so that each procedure in
  817. ;; PHASES can pick the keyword arguments it's interested in.
  818. (for-each (match-lambda
  819. ((name . proc)
  820. (let ((start (current-time time-monotonic)))
  821. (define (end-of-phase success?)
  822. (let ((end (current-time time-monotonic)))
  823. (format #t "phase `~a' ~:[failed~;succeeded~] after ~,1f seconds~%"
  824. name success?
  825. (elapsed-time end start))
  826. ;; Dump the environment variables as a shell script,
  827. ;; for handy debugging.
  828. (system "export > $NIX_BUILD_TOP/environment-variables")))
  829. (format #t "starting phase `~a'~%" name)
  830. (with-throw-handler #t
  831. (lambda ()
  832. (apply proc args)
  833. (end-of-phase #t))
  834. (lambda args
  835. ;; This handler executes before the stack is unwound.
  836. ;; The exception is automatically re-thrown from here,
  837. ;; and we should get a proper backtrace.
  838. (format (current-error-port)
  839. "error: in phase '~a': uncaught exception:
  840. ~{~s ~}~%" name args)
  841. (end-of-phase #f))))))
  842. phases)))