gnu.scm 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616
  1. ;;; GNU Guix --- Functional package management for GNU
  2. ;;; Copyright © 2012, 2013, 2014, 2015, 2016, 2017, 2019, 2020 Ludovic Courtès <ludo@gnu.org>
  3. ;;;
  4. ;;; This file is part of GNU Guix.
  5. ;;;
  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.
  10. ;;;
  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.
  15. ;;;
  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/>.
  18. (define-module (guix build-system gnu)
  19. #:use-module (guix store)
  20. #:use-module (guix utils)
  21. #:use-module (guix memoization)
  22. #:use-module (guix derivations)
  23. #:use-module (guix search-paths)
  24. #:use-module (guix build-system)
  25. #:use-module (guix packages)
  26. #:use-module (srfi srfi-1)
  27. #:use-module (ice-9 match)
  28. #:export (%gnu-build-system-modules
  29. gnu-build
  30. gnu-build-system
  31. standard-packages
  32. standard-cross-packages
  33. package-with-explicit-inputs
  34. package-with-extra-configure-variable
  35. static-libgcc-package
  36. static-package
  37. dist-package
  38. package-with-restricted-references))
  39. ;; Commentary:
  40. ;;
  41. ;; Standard build procedure for packages using the GNU Build System or
  42. ;; something compatible ("./configure && make && make install").
  43. ;;
  44. ;; Code:
  45. (define %gnu-build-system-modules
  46. ;; Build-side modules imported and used by default.
  47. '((guix build gnu-build-system)
  48. (guix build utils)
  49. (guix build gremlin)
  50. (guix elf)))
  51. (define %default-modules
  52. ;; Modules in scope in the build-side environment.
  53. '((guix build gnu-build-system)
  54. (guix build utils)))
  55. (define* (package-with-explicit-inputs/deprecated p inputs
  56. #:optional
  57. (loc (current-source-location))
  58. #:key (native-inputs '())
  59. guile)
  60. "This variant is deprecated because it is inefficient: it memoizes only
  61. temporarily instead of memoizing across all transformations where INPUTS is
  62. the same.
  63. Rewrite P, which is assumed to use GNU-BUILD-SYSTEM, to take INPUTS and
  64. NATIVE-INPUTS as explicit inputs instead of the implicit default, and return
  65. it. INPUTS and NATIVE-INPUTS can be either input lists or thunks; in the
  66. latter case, they will be called in a context where the `%current-system' and
  67. `%current-target-system' are suitably parametrized. Use GUILE to run the
  68. builder, or the distro's final Guile when GUILE is #f."
  69. (define inputs* inputs)
  70. (define native-inputs* native-inputs)
  71. (define (call inputs)
  72. (if (procedure? inputs)
  73. (inputs)
  74. inputs))
  75. (define (duplicate-filter inputs)
  76. (let ((names (match (call inputs)
  77. (((name _ ...) ...)
  78. name))))
  79. (lambda (inputs)
  80. (fold alist-delete inputs names))))
  81. (let loop ((p p))
  82. (define rewritten-input
  83. (mlambda (input)
  84. (match input
  85. ((name (? package? p) sub-drv ...)
  86. ;; XXX: Check whether P's build system knows #:implicit-inputs, for
  87. ;; things like `cross-pkg-config'.
  88. (if (eq? (package-build-system p) gnu-build-system)
  89. (cons* name (loop p) sub-drv)
  90. (cons* name p sub-drv)))
  91. (x x))))
  92. (package (inherit p)
  93. (location (if (pair? loc) (source-properties->location loc) loc))
  94. (arguments
  95. ;; 'ensure-keyword-arguments' guarantees that this procedure is
  96. ;; idempotent.
  97. (ensure-keyword-arguments (package-arguments p)
  98. `(#:guile ,guile
  99. #:implicit-inputs? #f)))
  100. (replacement
  101. (let ((replacement (package-replacement p)))
  102. (and replacement
  103. (package-with-explicit-inputs replacement inputs loc
  104. #:native-inputs
  105. native-inputs
  106. #:guile guile))))
  107. (native-inputs
  108. (let ((filtered (duplicate-filter native-inputs*)))
  109. `(,@(call native-inputs*)
  110. ,@(map rewritten-input
  111. (filtered (package-native-inputs p))))))
  112. (propagated-inputs
  113. (map rewritten-input
  114. (package-propagated-inputs p)))
  115. (inputs
  116. (let ((filtered (duplicate-filter inputs*)))
  117. `(,@(call inputs*)
  118. ,@(map rewritten-input
  119. (filtered (package-inputs p)))))))))
  120. (define* (package-with-explicit-inputs* inputs #:optional guile)
  121. "Return a procedure that rewrites the given package and all its dependencies
  122. so that they use INPUTS (a thunk) instead of implicit inputs."
  123. (define (duplicate-filter package-inputs)
  124. (let ((names (match (inputs)
  125. (((name _ ...) ...)
  126. name))))
  127. (fold alist-delete package-inputs names)))
  128. (define (add-explicit-inputs p)
  129. (if (and (eq? (package-build-system p) gnu-build-system)
  130. (not (memq #:implicit-inputs? (package-arguments p))))
  131. (package
  132. (inherit p)
  133. (inputs (append (inputs)
  134. (duplicate-filter (package-inputs p))))
  135. (arguments
  136. (ensure-keyword-arguments (package-arguments p)
  137. `(#:implicit-inputs? #f
  138. #:guile ,guile))))
  139. p))
  140. (define (cut? p)
  141. (or (not (eq? (package-build-system p) gnu-build-system))
  142. (memq #:implicit-inputs? (package-arguments p))))
  143. (package-mapping add-explicit-inputs cut?))
  144. (define package-with-explicit-inputs
  145. (case-lambda*
  146. ((inputs #:optional guile)
  147. (package-with-explicit-inputs* inputs guile))
  148. ((p inputs #:optional (loc (current-source-location))
  149. #:key (native-inputs '()) guile)
  150. ;; deprecated
  151. (package-with-explicit-inputs/deprecated p inputs
  152. loc
  153. #:native-inputs
  154. native-inputs
  155. #:guile guile))))
  156. (define (package-with-extra-configure-variable p variable value)
  157. "Return a version of P with VARIABLE=VALUE specified as an extra `configure'
  158. flag, recursively. An example is LDFLAGS=-static. If P already has configure
  159. flags for VARIABLE, the associated value is augmented."
  160. (let loop ((p p))
  161. (define (rewritten-inputs inputs)
  162. (map (match-lambda
  163. ((name (? package? p) sub ...)
  164. `(,name ,(loop p) ,@sub))
  165. (input input))
  166. inputs))
  167. (package (inherit p)
  168. (arguments
  169. (let ((args (package-arguments p)))
  170. (substitute-keyword-arguments args
  171. ((#:configure-flags flags)
  172. (let* ((var= (string-append variable "="))
  173. (len (string-length var=)))
  174. `(cons ,(string-append var= value)
  175. (map (lambda (flag)
  176. (if (string-prefix? ,var= flag)
  177. (string-append
  178. ,(string-append var= value " ")
  179. (substring flag ,len))
  180. flag))
  181. ,flags)))))))
  182. (replacement
  183. (let ((replacement (package-replacement p)))
  184. (and replacement
  185. (package-with-extra-configure-variable replacement
  186. variable value))))
  187. (inputs (rewritten-inputs (package-inputs p)))
  188. (propagated-inputs (rewritten-inputs (package-propagated-inputs p))))))
  189. (define (static-libgcc-package p)
  190. "A version of P linked with `-static-gcc'."
  191. (package-with-extra-configure-variable p "LDFLAGS" "-static-libgcc"))
  192. (define* (static-package p #:key (strip-all? #t))
  193. "Return a statically-linked version of package P. If STRIP-ALL? is true,
  194. use `--strip-all' as the arguments to `strip'."
  195. (package (inherit p)
  196. (arguments
  197. (let ((a (default-keyword-arguments (package-arguments p)
  198. '(#:configure-flags '()
  199. #:strip-flags '("--strip-debug")))))
  200. (substitute-keyword-arguments a
  201. ((#:configure-flags flags)
  202. `(cons* "--disable-shared" "LDFLAGS=-static" ,flags))
  203. ((#:strip-flags flags)
  204. (if strip-all?
  205. ''("--strip-all")
  206. flags)))))
  207. (replacement (and=> (package-replacement p) static-package))))
  208. (define* (dist-package p source #:key (phases '%dist-phases))
  209. "Return a package that runs takes source files from the SOURCE directory,
  210. runs `make distcheck' and whose result is one or more source tarballs. The
  211. exact build phases are defined by PHASES."
  212. (let ((s source))
  213. (package (inherit p)
  214. (name (string-append (package-name p) "-dist"))
  215. (source s)
  216. (arguments
  217. ;; Use the right phases and modules.
  218. (substitute-keyword-arguments (package-arguments p)
  219. ((#:modules modules %default-modules)
  220. `((guix build gnu-dist)
  221. ,@modules))
  222. ((#:imported-modules modules %gnu-build-system-modules)
  223. `((guix build gnu-dist)
  224. ,@modules))
  225. ((#:phases _ #f)
  226. phases)))
  227. (native-inputs
  228. ;; Add autotools & co. as inputs.
  229. (let ((ref (lambda (module var)
  230. (module-ref (resolve-interface module) var))))
  231. `(,@(package-native-inputs p)
  232. ("autoconf" ,(ref '(gnu packages autotools) 'autoconf-wrapper))
  233. ("automake" ,(ref '(gnu packages autotools) 'automake))
  234. ("libtool" ,(ref '(gnu packages autotools) 'libtool))
  235. ("gettext" ,(ref '(gnu packages gettext) 'gnu-gettext))
  236. ("texinfo" ,(ref '(gnu packages texinfo) 'texinfo))))))))
  237. (define (package-with-restricted-references p refs)
  238. "Return a package whose outputs are guaranteed to only refer to the packages
  239. listed in REFS."
  240. (if (eq? (package-build-system p) gnu-build-system) ; XXX: dirty
  241. (package (inherit p)
  242. (arguments `(#:allowed-references ,refs
  243. ,@(package-arguments p))))
  244. p))
  245. (define (standard-packages)
  246. "Return the list of (NAME PACKAGE OUTPUT) or (NAME PACKAGE) tuples of
  247. standard packages used as implicit inputs of the GNU build system."
  248. ;; Resolve (gnu packages commencement) lazily to hide circular dependency.
  249. (let ((distro (resolve-module '(gnu packages commencement))))
  250. (module-ref distro '%final-inputs)))
  251. (define* (lower name
  252. #:key source inputs native-inputs outputs target
  253. (implicit-inputs? #t) (implicit-cross-inputs? #t)
  254. (strip-binaries? #t) system
  255. #:allow-other-keys
  256. #:rest arguments)
  257. "Return a bag for NAME from the given arguments."
  258. (define private-keywords
  259. `(#:source #:inputs #:native-inputs #:outputs
  260. #:implicit-inputs? #:implicit-cross-inputs?
  261. ,@(if target '() '(#:target))))
  262. (bag
  263. (name name)
  264. (system system) (target target)
  265. (build-inputs `(,@(if source
  266. `(("source" ,source))
  267. '())
  268. ,@native-inputs
  269. ;; When not cross-compiling, ensure implicit inputs come
  270. ;; last. That way, libc headers come last, which allows
  271. ;; #include_next to work correctly; see
  272. ;; <https://bugs.gnu.org/30756>.
  273. ,@(if target '() inputs)
  274. ,@(if (and target implicit-cross-inputs?)
  275. (standard-cross-packages target 'host)
  276. '())
  277. ,@(if implicit-inputs?
  278. (standard-packages)
  279. '())))
  280. (host-inputs (if target inputs '()))
  281. ;; The cross-libc is really a target package, but for bootstrapping
  282. ;; reasons, we can't put it in 'host-inputs'. Namely, 'cross-gcc' is a
  283. ;; native package, so it would end up using a "native" variant of
  284. ;; 'cross-libc' (built with 'gnu-build'), whereas all the other packages
  285. ;; would use a target variant (built with 'gnu-cross-build'.)
  286. (target-inputs (if (and target implicit-cross-inputs?)
  287. (standard-cross-packages target 'target)
  288. '()))
  289. (outputs (if strip-binaries?
  290. outputs
  291. (delete "debug" outputs)))
  292. (build (if target gnu-cross-build gnu-build))
  293. (arguments (strip-keyword-arguments private-keywords arguments))))
  294. (define %license-file-regexp
  295. ;; Regexp matching license files.
  296. "^(COPYING.*|LICEN[CS]E.*|[Ll]icen[cs]e.*|Copy[Rr]ight(\\.(txt|md))?)$")
  297. (define* (gnu-build store name input-drvs
  298. #:key (guile #f)
  299. (outputs '("out"))
  300. (search-paths '())
  301. (configure-flags ''())
  302. (make-flags ''())
  303. (out-of-source? #f)
  304. (tests? #t)
  305. (test-target "check")
  306. (parallel-build? #t)
  307. (parallel-tests? #t)
  308. (patch-shebangs? #t)
  309. (strip-binaries? #t)
  310. (strip-flags ''("--strip-debug"
  311. "--enable-deterministic-archives"))
  312. (strip-directories ''("lib" "lib64" "libexec"
  313. "bin" "sbin"))
  314. (validate-runpath? #t)
  315. (license-file-regexp %license-file-regexp)
  316. (phases '%standard-phases)
  317. (locale "en_US.utf8")
  318. (system (%current-system))
  319. (build (nix-system->gnu-triplet system))
  320. (imported-modules %gnu-build-system-modules)
  321. (modules %default-modules)
  322. (substitutable? #t)
  323. allowed-references
  324. disallowed-references)
  325. "Return a derivation called NAME that builds from tarball SOURCE, with
  326. input derivation INPUTS, using the usual procedure of the GNU Build
  327. System. The builder is run with GUILE, or with the distro's final Guile
  328. package if GUILE is #f or omitted.
  329. The builder is run in a context where MODULES are used; IMPORTED-MODULES
  330. specifies modules not provided by Guile itself that must be imported in
  331. the builder's environment, from the host. Note that we distinguish
  332. between both, because for Guile's own modules like (ice-9 foo), we want
  333. to use GUILE's own version of it, rather than import the user's one,
  334. which could lead to gratuitous input divergence.
  335. SUBSTITUTABLE? determines whether users may be able to use substitutes of the
  336. returned derivations, or whether they should always build it locally.
  337. ALLOWED-REFERENCES can be either #f, or a list of packages that the outputs
  338. are allowed to refer to. Likewise for DISALLOWED-REFERENCES, which lists
  339. packages that must not be referenced."
  340. (define canonicalize-reference
  341. (match-lambda
  342. ((? package? p)
  343. (derivation->output-path (package-derivation store p system
  344. #:graft? #f)))
  345. (((? package? p) output)
  346. (derivation->output-path (package-derivation store p system
  347. #:graft? #f)
  348. output))
  349. ((? string? output)
  350. output)))
  351. (define builder
  352. `(begin
  353. (use-modules ,@modules)
  354. (gnu-build #:source ,(match (assoc-ref input-drvs "source")
  355. (((? derivation? source))
  356. (derivation->output-path source))
  357. ((source)
  358. source)
  359. (source
  360. source))
  361. #:system ,system
  362. #:build ,build
  363. #:outputs %outputs
  364. #:inputs %build-inputs
  365. #:search-paths ',(map search-path-specification->sexp
  366. search-paths)
  367. #:phases ,phases
  368. #:locale ,locale
  369. #:configure-flags ,configure-flags
  370. #:make-flags ,make-flags
  371. #:out-of-source? ,out-of-source?
  372. #:tests? ,tests?
  373. #:test-target ,test-target
  374. #:parallel-build? ,parallel-build?
  375. #:parallel-tests? ,parallel-tests?
  376. #:patch-shebangs? ,patch-shebangs?
  377. #:strip-binaries? ,strip-binaries?
  378. #:validate-runpath? ,validate-runpath?
  379. #:license-file-regexp ,license-file-regexp
  380. #:strip-flags ,strip-flags
  381. #:strip-directories ,strip-directories)))
  382. (define guile-for-build
  383. (match guile
  384. ((? package?)
  385. (package-derivation store guile system #:graft? #f))
  386. (#f ; the default
  387. (let* ((distro (resolve-interface '(gnu packages commencement)))
  388. (guile (module-ref distro 'guile-final)))
  389. (package-derivation store guile system
  390. #:graft? #f)))))
  391. (build-expression->derivation store name builder
  392. #:system system
  393. #:inputs input-drvs
  394. #:outputs outputs
  395. #:modules imported-modules
  396. #:substitutable? substitutable?
  397. #:allowed-references
  398. (and allowed-references
  399. (map canonicalize-reference
  400. allowed-references))
  401. #:disallowed-references
  402. (and disallowed-references
  403. (map canonicalize-reference
  404. disallowed-references))
  405. #:guile-for-build guile-for-build))
  406. ;;;
  407. ;;; Cross-compilation.
  408. ;;;
  409. (define standard-cross-packages
  410. (mlambda (target kind)
  411. "Return the list of name/package tuples to cross-build for TARGET. KIND
  412. is one of `host' or `target'."
  413. (let* ((cross (resolve-interface '(gnu packages cross-base)))
  414. (gcc (module-ref cross 'cross-gcc))
  415. (binutils (module-ref cross 'cross-binutils))
  416. (libc (module-ref cross 'cross-libc)))
  417. (case kind
  418. ((host)
  419. ;; Cross-GCC appears once here, so that it's in $PATH...
  420. `(("cross-gcc" ,(gcc target
  421. #:xbinutils (binutils target)
  422. #:libc (libc target)))
  423. ("cross-binutils" ,(binutils target))))
  424. ((target)
  425. (let ((libc (libc target)))
  426. ;; ... and once here, so that libstdc++ & co. are in
  427. ;; CROSS_CPLUS_INCLUDE_PATH, etc.
  428. `(("cross-gcc" ,(gcc target
  429. #:xbinutils (binutils target)
  430. #:libc libc))
  431. ("cross-libc" ,libc)
  432. ;; MinGW's libc doesn't have a "static" output.
  433. ,@(if (member "static" (package-outputs libc))
  434. `(("cross-libc:static" ,libc "static"))
  435. '()))))))))
  436. (define* (gnu-cross-build store name
  437. #:key
  438. target native-drvs target-drvs
  439. (guile #f)
  440. source
  441. (outputs '("out"))
  442. (search-paths '())
  443. (native-search-paths '())
  444. (configure-flags ''())
  445. (make-flags ''())
  446. (out-of-source? #f)
  447. (tests? #f) ; nothing can be done
  448. (test-target "check")
  449. (parallel-build? #t) (parallel-tests? #t)
  450. (patch-shebangs? #t)
  451. (strip-binaries? #t)
  452. (strip-flags ''("--strip-debug"
  453. "--enable-deterministic-archives"))
  454. (strip-directories ''("lib" "lib64" "libexec"
  455. "bin" "sbin"))
  456. (validate-runpath? #t)
  457. (license-file-regexp %license-file-regexp)
  458. (phases '%standard-phases)
  459. (locale "en_US.utf8")
  460. (system (%current-system))
  461. (build (nix-system->gnu-triplet system))
  462. (imported-modules %gnu-build-system-modules)
  463. (modules %default-modules)
  464. (substitutable? #t)
  465. allowed-references
  466. disallowed-references)
  467. "Cross-build NAME for TARGET, where TARGET is a GNU triplet. INPUTS are
  468. cross-built inputs, and NATIVE-INPUTS are inputs that run on the build
  469. platform."
  470. (define canonicalize-reference
  471. (match-lambda
  472. ((? package? p)
  473. (derivation->output-path (package-cross-derivation store p
  474. target system)))
  475. (((? package? p) output)
  476. (derivation->output-path (package-cross-derivation store p
  477. target system)
  478. output))
  479. ((? string? output)
  480. output)))
  481. (define builder
  482. `(begin
  483. (use-modules ,@modules)
  484. (let ()
  485. (define %build-host-inputs
  486. ',(map (match-lambda
  487. ((name (? derivation? drv) sub ...)
  488. `(,name . ,(apply derivation->output-path drv sub)))
  489. ((name path)
  490. `(,name . ,path)))
  491. native-drvs))
  492. (define %build-target-inputs
  493. ',(map (match-lambda
  494. ((name (? derivation? drv) sub ...)
  495. `(,name . ,(apply derivation->output-path drv sub)))
  496. ((name (? package? pkg) sub ...)
  497. (let ((drv (package-cross-derivation store pkg
  498. target system)))
  499. `(,name . ,(apply derivation->output-path drv sub))))
  500. ((name path)
  501. `(,name . ,path)))
  502. target-drvs))
  503. (gnu-build #:source ,(match (assoc-ref native-drvs "source")
  504. (((? derivation? source))
  505. (derivation->output-path source))
  506. ((source)
  507. source)
  508. (source
  509. source))
  510. #:system ,system
  511. #:build ,build
  512. #:target ,target
  513. #:outputs %outputs
  514. #:inputs %build-target-inputs
  515. #:native-inputs %build-host-inputs
  516. #:search-paths ',(map search-path-specification->sexp
  517. search-paths)
  518. #:native-search-paths ',(map
  519. search-path-specification->sexp
  520. native-search-paths)
  521. #:phases ,phases
  522. #:locale ,locale
  523. #:configure-flags ,configure-flags
  524. #:make-flags ,make-flags
  525. #:out-of-source? ,out-of-source?
  526. #:tests? ,tests?
  527. #:test-target ,test-target
  528. #:parallel-build? ,parallel-build?
  529. #:parallel-tests? ,parallel-tests?
  530. #:patch-shebangs? ,patch-shebangs?
  531. #:strip-binaries? ,strip-binaries?
  532. #:validate-runpath? ,validate-runpath?
  533. #:license-file-regexp ,license-file-regexp
  534. #:strip-flags ,strip-flags
  535. #:strip-directories ,strip-directories))))
  536. (define guile-for-build
  537. (match guile
  538. ((? package?)
  539. (package-derivation store guile system #:graft? #f))
  540. (#f ; the default
  541. (let* ((distro (resolve-interface '(gnu packages commencement)))
  542. (guile (module-ref distro 'guile-final)))
  543. (package-derivation store guile system #:graft? #f)))))
  544. (build-expression->derivation store name builder
  545. #:system system
  546. #:inputs (append native-drvs target-drvs)
  547. #:outputs outputs
  548. #:modules imported-modules
  549. #:substitutable? substitutable?
  550. #:allowed-references
  551. (and allowed-references
  552. (map canonicalize-reference
  553. allowed-references))
  554. #:disallowed-references
  555. (and disallowed-references
  556. (map canonicalize-reference
  557. disallowed-references))
  558. #:guile-for-build guile-for-build))
  559. (define gnu-build-system
  560. (build-system
  561. (name 'gnu)
  562. (description
  563. "The GNU Build System—i.e., ./configure && make && make install")
  564. (lower lower)))