2 # aside from this initial boilerplate, this is actually -*- scheme -*- code
5 datarootdir
="@datarootdir@"
7 GUILE_LOAD_COMPILED_PATH
="@guilemoduledir@:$GUILE_LOAD_COMPILED_PATH"
8 export GUILE_LOAD_COMPILED_PATH
10 main
='(module-ref (resolve-interface '\''(guix-build)) '\'guix-build
')'
11 exec ${GUILE-@GUILE@} -L "@guilemoduledir@" -l "$0" \
12 -c "(apply $main (cdr (command-line)))" "$@"
14 ;;; GNU Guix
--- Functional package management
for GNU
15 ;;; Copyright ©
2012, 2013 Ludovic Courtès
<ludo@gnu.org
>
16 ;;; Copyright ©
2013 Mark H Weaver
<mhw@netris.org
>
18 ;;; This
file is part of GNU Guix.
20 ;;; GNU Guix is free software
; you can redistribute it and
/or modify it
21 ;;; under the terms of the GNU General Public License as published by
22 ;;; the Free Software Foundation
; either version
3 of the License
, or
(at
23 ;;; your option
) any later version.
25 ;;; GNU Guix is distributed
in the hope that it will be useful
, but
26 ;;; WITHOUT ANY WARRANTY
; without even the implied warranty of
27 ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28 ;;; GNU General Public License
for more details.
30 ;;; You should have received a copy of the GNU General Public License
31 ;;; along with GNU Guix. If not
, see
<http
://www.gnu.org
/licenses
/>.
33 (define-module
(guix-build
)
34 #:use-module (guix ui)
35 #:use-module (guix store)
36 #:use-module (guix derivations)
37 #:use-module (guix packages)
38 #:use-module (guix utils)
39 #:use-module (ice-9 format)
40 #:use-module (ice-9 match)
41 #:use-module (ice-9 vlist)
42 #:use-module (srfi srfi-1)
43 #:use-module (srfi srfi-11)
44 #:use-module (srfi srfi-26)
45 #:use-module (srfi srfi-34)
46 #:use-module (srfi srfi-37)
47 #:autoload (gnu packages) (find-packages-by-name
48 find-newest-available-packages
)
49 #:export (guix-build))
54 (define
(derivations-from-package-expressions exp system
source?
)
55 "Eval EXP and return the corresponding derivation path for SYSTEM.
56 When SOURCE? is true, return the derivations of the package sources."
57 (let ((p
(eval exp
(current-module
))))
60 (let ((source (package-source p
))
61 (loc
(package-location p
)))
63 (package-source-derivation
(%store
) source)
64 (leave
(_
"~a: error: package `~a' has no source~%")
65 (location-
>string loc
) (package-name p
))))
66 (package-derivation
(%store
) p system
))
67 (leave
(_
"expression `~s' does not evaluate to a package~%")
72 ;;; Command-line options.
75 (define
%default-options
76 ;; Alist of default option values.
77 `((system . ,(%current-system))
82 (display (_ "Usage: guix-build [OPTION]... PACKAGE-OR-DERIVATION...
83 Build the given PACKAGE-OR-DERIVATION and return their output paths.\n"))
85 -e, --expression=EXPR build the package EXPR evaluates to"))
87 -S, --source build the packages' source derivations"))
89 -s, --system=SYSTEM attempt to build for SYSTEM--e.g., \"i686-linux\""))
91 -d, --derivations return the derivation paths of the given packages"))
93 -K, --keep-failed keep build tree of failed builds"))
95 -n, --dry-run do not build the derivations"))
97 --no-substitutes build instead of resorting to pre-built substitutes"))
99 -c, --cores=N allow the use of up to N CPU cores for the build"))
101 -r, --root=FILE make FILE a symlink to the result, and register it
102 as a garbage collector root"))
104 --verbosity=LEVEL use the given verbosity LEVEL"))
107 -h, --help display this help and exit"))
109 -V, --version display version information and exit"))
111 (show-bug-report-information))
114 ;; Specifications of the command-line options.
115 (list (option '(#\h "help") #f #f
119 (option '(#\V "version") #f #f
121 (show-version-and-exit "guix-build")))
123 (option '(#\S "source") #f #f
124 (lambda (opt name arg result)
125 (alist-cons 'source? #t result)))
126 (option '(#\s "system") #t #f
127 (lambda (opt name arg result)
128 (alist-cons 'system arg
129 (alist-delete 'system result eq?))))
130 (option '(#\d "derivations") #f #f
131 (lambda (opt name arg result)
132 (alist-cons 'derivations-only? #t result)))
133 (option '(#\e "expression") #t #f
134 (lambda (opt name arg result)
135 (alist-cons 'expression
136 (call-with-input-string arg read)
138 (option '(#\K "keep-failed") #f #f
139 (lambda (opt name arg result)
140 (alist-cons 'keep-failed? #t result)))
141 (option '(#\c "cores") #t #f
142 (lambda (opt name arg result)
143 (let ((c (false-if-exception (string->number arg))))
145 (alist-cons 'cores c result)
146 (leave (_ "~a: not a number~%") arg)))))
147 (option '(#\n "dry-run") #f #f
148 (lambda (opt name arg result)
149 (alist-cons 'dry-run? #t result)))
150 (option '("no-substitutes") #f #f
151 (lambda (opt name arg result)
152 (alist-cons 'substitutes? #f
153 (alist-delete 'substitutes? result))))
154 (option '(#\r "root") #t #f
155 (lambda (opt name arg result)
156 (alist-cons 'gc-root arg result)))
157 (option '("verbosity") #t #f
158 (lambda (opt name arg result)
159 (let ((level (string->number arg)))
160 (alist-cons 'verbosity level
161 (alist-delete 'verbosity result)))))))
168 (define (guix-build . args)
169 (define (parse-options)
170 ;; Return the alist of option values.
171 (args-fold args %options
172 (lambda (opt name arg result)
173 (leave (_ "~A: unrecognized option~%") name))
175 (alist-cons 'argument arg result))
178 (define (register-root paths root)
179 ;; Register ROOT as an indirect GC root for all of PATHS.
180 (let* ((root (string-append (canonicalize-path (dirname root))
187 (add-indirect-root (%store) root))
189 (fold (lambda (path count)
190 (let ((root (string-append root "-" (number->string count))))
192 (add-indirect-root (%store) root))
197 (format (current-error-port)
198 (_ "failed to create GC root `~a
': ~a~%")
199 root (strerror (system-error-errno args)))
202 (define newest-available-packages
203 (memoize find-newest-available-packages))
205 (define (find-best-packages-by-name name version)
207 (find-packages-by-name name version)
208 (match (vhash-assoc name (newest-available-packages))
209 ((_ version pkgs ...) pkgs)
212 (define
(find-package request
)
213 ;; Return a package matching REQUEST. REQUEST may be a package
214 ;; name
, or a package name followed by a hyphen and a version
215 ;; number. If the version number is not present
, return the
216 ;; preferred newest version.
217 (let-values
(((name version
)
218 (package-name-
>name
+version request
)))
219 (match
(find-best-packages-by-name name version
)
222 ((p x ...
) ; several matches
223 (format
(current-error-port
)
224 (_
"warning: ambiguous package specification `~a'~%")
226 (format
(current-error-port
)
227 (_
"warning: choosing ~a from ~a~%")
228 (package-full-name p
)
229 (location-
>string
(package-location p
)))
233 (leave
(_
"~A: package not found for version ~a~%")
235 (leave
(_
"~A: unknown package~%") name
))))))
239 (setvbuf
(current-output-port
) _IOLBF
)
240 (setvbuf
(current-error-port
) _IOLBF
)
243 (let ((opts
(parse-options
)))
244 (parameterize
((%store
(open-connection
)))
245 (let* ((src?
(assoc-ref opts
'source?))
246 (sys (assoc-ref opts 'system
))
247 (drv
(filter-map
(match-lambda
249 (derivations-from-package-expressions exp sys
251 (('argument .
(? derivation-path? drv
))
253 (('argument . (? string? x))
254 (let ((p (find-package x)))
256 (let ((s (package-source p)))
257 (package-source-derivation
259 (package-derivation (%store) p sys))))
262 (req (append-map (lambda (drv-path)
263 (let ((d (call-with-input-file drv-path
265 (derivation-prerequisites-to-build (%store) d)))
267 (req* (delete-duplicates
268 (append (remove (compose (cut valid-path? (%store) <>)
269 derivation-path->output-path)
271 (map derivation-input-path req))))
272 (roots (filter-map (match-lambda
273 (('gc-root . root
) root
)
276 (if (assoc-ref opts
'dry-run?)
277 (format (current-error-port)
278 (N_ "~:[the following derivation would be built:~%~{ ~a~%~}~;~]"
279 "~:[the following derivations would be built:~%~{ ~a~%~}~;~]"
282 (format (current-error-port)
283 (N_ "~:[the following derivation will be built:~%~{ ~a~%~}~;~]"
284 "~:[the following derivations will be built:~%~{ ~a~%~}~;~]"
288 ;; TODO: Add more options.
289 (set-build-options (%store)
290 #:keep-failed? (assoc-ref opts 'keep-failed?
)
291 #:build-cores (or (assoc-ref opts 'cores) 0)
292 #:use-substitutes? (assoc-ref opts 'substitutes?)
293 #:verbosity (assoc-ref opts 'verbosity))
295 (if (assoc-ref opts
'derivations-only?)
297 (format #t "~{~a~%~}" drv)
298 (for-each (cut register-root <> <>)
299 (map list drv) roots))
300 (or (assoc-ref opts 'dry-run?
)
301 (and
(build-derivations
(%store
) drv
)
302 (for-each
(lambda
(d
)
303 (let ((drv
(call-with-input-file d
305 (format
#t "~{~a~%~}"
308 (derivation-path-
>output-path
310 (derivation-outputs drv
)))))
312 (for-each
(cut register-root
<> <>)
315 (derivation-path-
>output-paths drv
)))