guix-build: Use `location->string'.
[jackhill/guix/guix.git] / guix-build.in
CommitLineData
14a1c319
LC
1#!/bin/sh
2# aside from this initial boilerplate, this is actually -*- scheme -*- code
3
b8605698
LC
4prefix="@prefix@"
5datarootdir="@datarootdir@"
6
14a1c319
LC
7GUILE_LOAD_COMPILED_PATH="@guilemoduledir@:$GUILE_LOAD_COMPILED_PATH"
8export GUILE_LOAD_COMPILED_PATH
9
10main='(module-ref (resolve-interface '\''(guix-build)) '\'guix-build')'
11exec ${GUILE-@GUILE@} -L "@guilemoduledir@" -l "$0" \
12 -c "(apply $main (cdr (command-line)))" "$@"
13!#
14;;; Guix --- Nix package management from Guile. -*- coding: utf-8 -*-
15;;; Copyright (C) 2012 Ludovic Courtès <ludo@gnu.org>
16;;;
17;;; This file is part of Guix.
18;;;
19;;; Guix is free software; you can redistribute it and/or modify it
20;;; under the terms of the GNU General Public License as published by
21;;; the Free Software Foundation; either version 3 of the License, or (at
22;;; your option) any later version.
23;;;
24;;; Guix is distributed in the hope that it will be useful, but
25;;; WITHOUT ANY WARRANTY; without even the implied warranty of
26;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27;;; GNU General Public License for more details.
28;;;
29;;; You should have received a copy of the GNU General Public License
30;;; along with Guix. If not, see <http://www.gnu.org/licenses/>.
31
32(define-module (guix-build)
073c34d7 33 #:use-module (guix ui)
14a1c319
LC
34 #:use-module (guix store)
35 #:use-module (guix derivations)
36 #:use-module (guix packages)
07783858 37 #:use-module (guix utils)
14a1c319
LC
38 #:use-module (ice-9 format)
39 #:use-module (ice-9 match)
40 #:use-module (srfi srfi-1)
41 #:use-module (srfi srfi-26)
07783858 42 #:use-module (srfi srfi-34)
14a1c319
LC
43 #:use-module (srfi srfi-37)
44 #:autoload (distro) (find-packages-by-name)
45 #:export (guix-build))
46
14a1c319
LC
47(define %store
48 (open-connection))
49
5cc30616
LC
50(define (derivations-from-package-expressions exp system source?)
51 "Eval EXP and return the corresponding derivation path for SYSTEM.
52When SOURCE? is true, return the derivations of the package sources."
14a1c319
LC
53 (let ((p (eval exp (current-module))))
54 (if (package? p)
5dba3149 55 (if source?
912209ee
LC
56 (let ((source (package-source p))
57 (loc (package-location p)))
58 (if source
59 (package-source-derivation %store source)
ef1ee6b2
LC
60 (leave (_ "~a: error: package `~a' has no source~%")
61 (location->string loc) (package-name p))))
5cc30616 62 (package-derivation %store p system))
912209ee
LC
63 (leave (_ "expression `~s' does not evaluate to a package~%")
64 exp))))
14a1c319
LC
65
66\f
67;;;
68;;; Command-line options.
69;;;
70
71(define %default-options
72 ;; Alist of default option values.
692c6c15
LC
73 `((system . ,(%current-system))
74 (substitutes? . #t)))
14a1c319 75
14a1c319
LC
76(define (show-help)
77 (display (_ "Usage: guix-build [OPTION]... PACKAGE-OR-DERIVATION...
78Build the given PACKAGE-OR-DERIVATION and return their output paths.\n"))
79 (display (_ "
80 -e, --expression=EXPR build the package EXPR evaluates to"))
81 (display (_ "
5dba3149
LC
82 -S, --source build the packages' source derivations"))
83 (display (_ "
5cc30616
LC
84 -s, --system=SYSTEM attempt to build for SYSTEM--e.g., \"i686-linux\""))
85 (display (_ "
609354bf
LC
86 -d, --derivations return the derivation paths of the given packages"))
87 (display (_ "
14a1c319
LC
88 -K, --keep-failed keep build tree of failed builds"))
89 (display (_ "
90 -n, --dry-run do not build the derivations"))
1c3972da 91 (display (_ "
692c6c15 92 --no-substitutes build instead of resorting to pre-built substitutes"))
fa14d96e
LC
93 (display (_ "
94 -c, --cores=N allow the use of up to N CPU cores for the build"))
34811f02
LC
95 (display (_ "
96 -r, --root=FILE make FILE a symlink to the result, and register it
97 as a garbage collector root"))
14a1c319
LC
98 (newline)
99 (display (_ "
100 -h, --help display this help and exit"))
101 (display (_ "
102 -V, --version display version information and exit"))
103 (newline)
104 (format #t (_ "
105Report bugs to: ~a.~%") "@PACKAGE_BUGREPORT@"))
106
107(define %options
108 ;; Specifications of the command-line options.
109 (list (option '(#\h "help") #f #f
110 (lambda args
111 (show-help)
112 (exit 0)))
113 (option '(#\V "version") #f #f
114 (lambda args
cdd5d6f9 115 (show-version-and-exit "guix-build")))
14a1c319 116
5dba3149
LC
117 (option '(#\S "source") #f #f
118 (lambda (opt name arg result)
119 (alist-cons 'source? #t result)))
5cc30616
LC
120 (option '(#\s "system") #t #f
121 (lambda (opt name arg result)
122 (alist-cons 'system arg
123 (alist-delete 'system result eq?))))
609354bf
LC
124 (option '(#\d "derivations") #f #f
125 (lambda (opt name arg result)
126 (alist-cons 'derivations-only? #t result)))
14a1c319
LC
127 (option '(#\e "expression") #t #f
128 (lambda (opt name arg result)
129 (alist-cons 'expression
130 (call-with-input-string arg read)
131 result)))
132 (option '(#\K "keep-failed") #f #f
133 (lambda (opt name arg result)
134 (alist-cons 'keep-failed? #t result)))
fa14d96e
LC
135 (option '(#\c "cores") #t #f
136 (lambda (opt name arg result)
137 (let ((c (false-if-exception (string->number arg))))
138 (if c
139 (alist-cons 'cores c result)
140 (leave (_ "~a: not a number~%") arg)))))
1c3972da
LC
141 (option '(#\n "dry-run") #f #f
142 (lambda (opt name arg result)
143 (alist-cons 'dry-run? #t result)))
692c6c15 144 (option '("no-substitutes") #f #f
14a1c319 145 (lambda (opt name arg result)
692c6c15 146 (alist-cons 'substitutes? #f
34811f02
LC
147 (alist-delete 'substitutes? result))))
148 (option '(#\r "root") #t #f
149 (lambda (opt name arg result)
150 (alist-cons 'gc-root arg result)))))
14a1c319
LC
151
152\f
153;;;
154;;; Entry point.
155;;;
156
157(define (guix-build . args)
fa14d96e
LC
158 (define (parse-options)
159 ;; Return the alist of option values.
160 (args-fold args %options
161 (lambda (opt name arg result)
8759a648 162 (leave (_ "~A: unrecognized option~%") name))
fa14d96e
LC
163 (lambda (arg result)
164 (alist-cons 'argument arg result))
165 %default-options))
166
34811f02
LC
167 (define (register-root drv root)
168 ;; Register ROOT as an indirect GC root for DRV's outputs.
169 (let* ((root (string-append (canonicalize-path (dirname root))
170 "/" root))
171 (drv* (call-with-input-file drv read-derivation))
172 (outputs (derivation-outputs drv*))
173 (outputs* (map (compose derivation-output-path cdr) outputs)))
174 (catch 'system-error
175 (lambda ()
176 (match outputs*
177 ((output)
178 (symlink output root)
179 (add-indirect-root %store root))
180 ((outputs ...)
181 (fold (lambda (output count)
182 (let ((root (string-append root "-" (number->string count))))
183 (symlink output root)
184 (add-indirect-root %store root))
185 (+ 1 count))
186 0
187 outputs))))
188 (lambda args
189 (format (current-error-port)
190 (_ "failed to create GC root `~a': ~a~%")
191 root (strerror (system-error-errno args)))
192 (exit 1)))))
193
fa14d96e
LC
194 (setlocale LC_ALL "")
195 (textdomain "guix")
196 (setvbuf (current-output-port) _IOLBF)
197 (setvbuf (current-error-port) _IOLBF)
198
073c34d7 199 (with-error-handling
07783858
LC
200 (let* ((opts (parse-options))
201 (src? (assoc-ref opts 'source?))
202 (sys (assoc-ref opts 'system))
203 (drv (filter-map (match-lambda
204 (('expression . exp)
205 (derivations-from-package-expressions exp sys
206 src?))
207 (('argument . (? derivation-path? drv))
208 drv)
209 (('argument . (? string? x))
210 (match (find-packages-by-name x)
211 ((p _ ...)
212 (if src?
213 (let ((s (package-source p)))
214 (package-source-derivation %store s))
215 (package-derivation %store p sys)))
216 (_
217 (leave (_ "~A: unknown package~%") x))))
218 (_ #f))
219 opts))
220 (req (append-map (lambda (drv-path)
221 (let ((d (call-with-input-file drv-path
609354bf 222 read-derivation)))
07783858
LC
223 (derivation-prerequisites-to-build %store d)))
224 drv))
225 (req* (delete-duplicates
226 (append (remove (compose (cut valid-path? %store <>)
227 derivation-path->output-path)
228 drv)
229 (map derivation-input-path req)))))
230 (if (assoc-ref opts 'dry-run?)
231 (format (current-error-port)
232 (N_ "~:[the following derivation would be built:~%~{ ~a~%~}~;~]"
233 "~:[the following derivations would be built:~%~{ ~a~%~}~;~]"
234 (length req*))
235 (null? req*) req*)
236 (format (current-error-port)
237 (N_ "~:[the following derivation will be built:~%~{ ~a~%~}~;~]"
238 "~:[the following derivations will be built:~%~{ ~a~%~}~;~]"
239 (length req*))
240 (null? req*) req*))
241
242 ;; TODO: Add more options.
243 (set-build-options %store
244 #:keep-failed? (assoc-ref opts 'keep-failed?)
245 #:build-cores (or (assoc-ref opts 'cores) 0)
246 #:use-substitutes? (assoc-ref opts 'substitutes?))
247
248 (if (assoc-ref opts 'derivations-only?)
249 (format #t "~{~a~%~}" drv)
250 (or (assoc-ref opts 'dry-run?)
251 (and (build-derivations %store drv)
252 (for-each (lambda (d)
253 (let ((drv (call-with-input-file d
254 read-derivation)))
255 (format #t "~{~a~%~}"
256 (map (match-lambda
257 ((out-name . out)
258 (derivation-path->output-path
259 d out-name)))
260 (derivation-outputs drv)))))
34811f02
LC
261 drv)
262 (let ((roots (filter-map (match-lambda
263 (('gc-root . root)
264 root)
265 (_ #f))
266 opts)))
267 (when roots
268 (for-each (cut register-root <> <>)
269 drv roots)
270 #t))))))))
07783858
LC
271
272;; Local Variables:
273;; eval: (put 'guard 'scheme-indent-function 1)
274;; End: