2013-01-05 18:47:50 -05:00
|
|
|
|
;;; GNU Guix --- Functional package management for GNU
|
|
|
|
|
;;; Copyright © 2012, 2013 Ludovic Courtès <ludo@gnu.org>
|
2012-04-18 17:34:12 -04:00
|
|
|
|
;;;
|
2013-01-05 18:47:50 -05:00
|
|
|
|
;;; This file is part of GNU Guix.
|
2012-04-18 17:34:12 -04:00
|
|
|
|
;;;
|
2013-01-05 18:47:50 -05:00
|
|
|
|
;;; GNU Guix is free software; you can redistribute it and/or modify it
|
2012-04-18 17:34:12 -04:00
|
|
|
|
;;; under the terms of the GNU General Public License as published by
|
|
|
|
|
;;; the Free Software Foundation; either version 3 of the License, or (at
|
|
|
|
|
;;; your option) any later version.
|
|
|
|
|
;;;
|
2013-01-05 18:47:50 -05:00
|
|
|
|
;;; GNU Guix is distributed in the hope that it will be useful, but
|
2012-04-18 17:34:12 -04:00
|
|
|
|
;;; WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
|
;;; GNU General Public License for more details.
|
|
|
|
|
;;;
|
|
|
|
|
;;; You should have received a copy of the GNU General Public License
|
2013-01-05 18:47:50 -05:00
|
|
|
|
;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
|
2012-04-18 17:34:12 -04:00
|
|
|
|
|
|
|
|
|
(define-module (guix derivations)
|
|
|
|
|
#:use-module (srfi srfi-1)
|
|
|
|
|
#:use-module (srfi srfi-9)
|
|
|
|
|
#:use-module (srfi srfi-26)
|
|
|
|
|
#:use-module (rnrs io ports)
|
|
|
|
|
#:use-module (rnrs bytevectors)
|
|
|
|
|
#:use-module (ice-9 match)
|
|
|
|
|
#:use-module (ice-9 rdelim)
|
2012-06-01 17:29:55 -04:00
|
|
|
|
#:use-module (guix store)
|
2012-06-01 17:29:55 -04:00
|
|
|
|
#:use-module (guix utils)
|
2013-07-01 17:28:21 -04:00
|
|
|
|
#:use-module (guix hash)
|
Move base32 code to (guix base32).
* guix/utils.scm (bytevector-quintet-ref, bytevector-quintet-ref-right,
bytevector-quintet-length, bytevector-quintet-fold,
bytevector-quintet-fold-right, make-bytevector->base32-string,
%nix-base32-chars, %rfc4648-base32-chars, bytevector->base32-string,
bytevector->nix-base32-string, bytevector-quintet-set!,
bytevector-quintet-set-right!, base32-string-unfold,
base32-string-unfold-right, make-base32-string->bytevector,
base32-string->bytevector, nix-base32-string->bytevector): Move to...
* guix/base32.scm: ... here. New file.
* tests/utils.scm (%nix-hash, "bytevector->base32-string",
"base32-string->bytevector", "nix-base32-string->bytevector", "sha256
& bytevector->base32-string"): Move to...
* tests/base32.scm: ... here. New file
* guix-download.in, guix/derivations.scm, guix/packages.scm,
guix/snix.scm, tests/builders.scm, tests/derivations.scm: Adjust
accordingly.
* guix.scm (%public-modules): Add `base32'.
2012-11-11 16:33:28 -05:00
|
|
|
|
#:use-module (guix base32)
|
2012-06-30 18:37:03 -04:00
|
|
|
|
#:export (<derivation>
|
|
|
|
|
derivation?
|
2012-04-18 17:34:12 -04:00
|
|
|
|
derivation-outputs
|
|
|
|
|
derivation-inputs
|
|
|
|
|
derivation-sources
|
|
|
|
|
derivation-system
|
|
|
|
|
derivation-builder-arguments
|
|
|
|
|
derivation-builder-environment-vars
|
2013-09-17 17:00:55 -04:00
|
|
|
|
derivation-file-name
|
2012-06-30 18:37:03 -04:00
|
|
|
|
derivation-prerequisites
|
|
|
|
|
derivation-prerequisites-to-build
|
2012-04-18 17:34:12 -04:00
|
|
|
|
|
2012-06-30 18:37:03 -04:00
|
|
|
|
<derivation-output>
|
2012-04-18 17:34:12 -04:00
|
|
|
|
derivation-output?
|
|
|
|
|
derivation-output-path
|
|
|
|
|
derivation-output-hash-algo
|
|
|
|
|
derivation-output-hash
|
|
|
|
|
|
2012-06-30 18:37:03 -04:00
|
|
|
|
<derivation-input>
|
2012-04-18 17:34:12 -04:00
|
|
|
|
derivation-input?
|
|
|
|
|
derivation-input-path
|
|
|
|
|
derivation-input-sub-derivations
|
2013-04-16 18:06:59 -04:00
|
|
|
|
derivation-input-output-paths
|
2012-04-18 17:34:12 -04:00
|
|
|
|
|
|
|
|
|
fixed-output-derivation?
|
2012-04-19 17:09:55 -04:00
|
|
|
|
derivation-hash
|
|
|
|
|
|
|
|
|
|
read-derivation
|
2012-06-01 17:29:55 -04:00
|
|
|
|
write-derivation
|
2012-06-07 17:15:00 -04:00
|
|
|
|
derivation-path->output-path
|
2013-01-05 17:51:13 -05:00
|
|
|
|
derivation-path->output-paths
|
2012-06-08 15:31:01 -04:00
|
|
|
|
derivation
|
|
|
|
|
|
|
|
|
|
%guile-for-build
|
2013-08-28 17:59:14 -04:00
|
|
|
|
imported-modules
|
|
|
|
|
compiled-modules
|
2012-06-11 17:12:55 -04:00
|
|
|
|
build-expression->derivation
|
|
|
|
|
imported-files))
|
2012-04-18 17:34:12 -04:00
|
|
|
|
|
|
|
|
|
;;;
|
|
|
|
|
;;; Nix derivations, as implemented in Nix's `derivations.cc'.
|
|
|
|
|
;;;
|
|
|
|
|
|
|
|
|
|
(define-record-type <derivation>
|
2013-09-17 17:00:55 -04:00
|
|
|
|
(make-derivation outputs inputs sources system builder args env-vars
|
|
|
|
|
file-name)
|
2012-04-18 17:34:12 -04:00
|
|
|
|
derivation?
|
|
|
|
|
(outputs derivation-outputs) ; list of name/<derivation-output> pairs
|
|
|
|
|
(inputs derivation-inputs) ; list of <derivation-input>
|
|
|
|
|
(sources derivation-sources) ; list of store paths
|
|
|
|
|
(system derivation-system) ; string
|
|
|
|
|
(builder derivation-builder) ; store path
|
|
|
|
|
(args derivation-builder-arguments) ; list of strings
|
2013-09-17 17:00:55 -04:00
|
|
|
|
(env-vars derivation-builder-environment-vars) ; list of name/value pairs
|
|
|
|
|
(file-name derivation-file-name)) ; the .drv file name
|
2012-04-18 17:34:12 -04:00
|
|
|
|
|
|
|
|
|
(define-record-type <derivation-output>
|
|
|
|
|
(make-derivation-output path hash-algo hash)
|
|
|
|
|
derivation-output?
|
|
|
|
|
(path derivation-output-path) ; store path
|
|
|
|
|
(hash-algo derivation-output-hash-algo) ; symbol | #f
|
2012-06-09 12:49:19 -04:00
|
|
|
|
(hash derivation-output-hash)) ; bytevector | #f
|
2012-04-18 17:34:12 -04:00
|
|
|
|
|
|
|
|
|
(define-record-type <derivation-input>
|
|
|
|
|
(make-derivation-input path sub-derivations)
|
|
|
|
|
derivation-input?
|
|
|
|
|
(path derivation-input-path) ; store path
|
|
|
|
|
(sub-derivations derivation-input-sub-derivations)) ; list of strings
|
|
|
|
|
|
|
|
|
|
(define (fixed-output-derivation? drv)
|
|
|
|
|
"Return #t if DRV is a fixed-output derivation, such as the result of a
|
|
|
|
|
download with a fixed hash (aka. `fetchurl')."
|
|
|
|
|
(match drv
|
|
|
|
|
(($ <derivation>
|
|
|
|
|
(($ <derivation-output> _ (? symbol?) (? string?))))
|
|
|
|
|
#t)
|
|
|
|
|
(_ #f)))
|
|
|
|
|
|
2013-04-16 18:06:59 -04:00
|
|
|
|
(define (derivation-input-output-paths input)
|
|
|
|
|
"Return the list of output paths corresponding to INPUT, a
|
|
|
|
|
<derivation-input>."
|
|
|
|
|
(match input
|
|
|
|
|
(($ <derivation-input> path sub-drvs)
|
|
|
|
|
(map (cut derivation-path->output-path path <>)
|
|
|
|
|
sub-drvs))))
|
|
|
|
|
|
2012-06-30 18:37:03 -04:00
|
|
|
|
(define (derivation-prerequisites drv)
|
|
|
|
|
"Return the list of derivation-inputs required to build DRV, recursively."
|
|
|
|
|
(let loop ((drv drv)
|
|
|
|
|
(result '()))
|
|
|
|
|
(let ((inputs (remove (cut member <> result) ; XXX: quadratic
|
|
|
|
|
(derivation-inputs drv))))
|
|
|
|
|
(fold loop
|
|
|
|
|
(append inputs result)
|
|
|
|
|
(map (lambda (i)
|
|
|
|
|
(call-with-input-file (derivation-input-path i)
|
|
|
|
|
read-derivation))
|
|
|
|
|
inputs)))))
|
|
|
|
|
|
2013-01-09 02:38:57 -05:00
|
|
|
|
(define* (derivation-prerequisites-to-build store drv
|
2013-04-16 18:06:59 -04:00
|
|
|
|
#:key
|
|
|
|
|
(outputs
|
|
|
|
|
(map
|
|
|
|
|
car
|
|
|
|
|
(derivation-outputs drv)))
|
|
|
|
|
(use-substitutes? #t))
|
|
|
|
|
"Return two values: the list of derivation-inputs required to build the
|
|
|
|
|
OUTPUTS of DRV and not already available in STORE, recursively, and the list
|
|
|
|
|
of required store paths that can be substituted. When USE-SUBSTITUTES? is #f,
|
|
|
|
|
that second value is the empty list."
|
|
|
|
|
(define (derivation-output-paths drv sub-drvs)
|
|
|
|
|
(match drv
|
|
|
|
|
(($ <derivation> outputs)
|
|
|
|
|
(map (lambda (sub-drv)
|
|
|
|
|
(derivation-output-path (assoc-ref outputs sub-drv)))
|
|
|
|
|
sub-drvs))))
|
|
|
|
|
|
2013-01-09 02:38:57 -05:00
|
|
|
|
(define built?
|
|
|
|
|
(cut valid-path? store <>))
|
|
|
|
|
|
2013-04-16 18:06:59 -04:00
|
|
|
|
(define substitutable?
|
|
|
|
|
;; Return true if the given path is substitutable. Call
|
|
|
|
|
;; `substitutable-paths' upfront, to benefit from parallelism in the
|
|
|
|
|
;; substituter.
|
|
|
|
|
(if use-substitutes?
|
|
|
|
|
(let ((s (substitutable-paths store
|
|
|
|
|
(append
|
|
|
|
|
(derivation-output-paths drv outputs)
|
|
|
|
|
(append-map
|
|
|
|
|
derivation-input-output-paths
|
|
|
|
|
(derivation-prerequisites drv))))))
|
|
|
|
|
(cut member <> s))
|
|
|
|
|
(const #f)))
|
|
|
|
|
|
2012-06-30 18:37:03 -04:00
|
|
|
|
(define input-built?
|
2013-04-16 18:06:59 -04:00
|
|
|
|
(compose (cut any built? <>) derivation-input-output-paths))
|
|
|
|
|
|
|
|
|
|
(define input-substitutable?
|
|
|
|
|
;; Return true if and only if all of SUB-DRVS are subsitutable. If at
|
|
|
|
|
;; least one is missing, then everything must be rebuilt.
|
|
|
|
|
(compose (cut every substitutable? <>) derivation-input-output-paths))
|
2013-01-09 02:38:57 -05:00
|
|
|
|
|
|
|
|
|
(define (derivation-built? drv sub-drvs)
|
2013-04-16 18:06:59 -04:00
|
|
|
|
(every built? (derivation-output-paths drv sub-drvs)))
|
|
|
|
|
|
|
|
|
|
(define (derivation-substitutable? drv sub-drvs)
|
|
|
|
|
(every substitutable? (derivation-output-paths drv sub-drvs)))
|
|
|
|
|
|
|
|
|
|
(let loop ((drv drv)
|
|
|
|
|
(sub-drvs outputs)
|
|
|
|
|
(build '())
|
|
|
|
|
(substitute '()))
|
|
|
|
|
(cond ((derivation-built? drv sub-drvs)
|
|
|
|
|
(values build substitute))
|
|
|
|
|
((derivation-substitutable? drv sub-drvs)
|
|
|
|
|
(values build
|
|
|
|
|
(append (derivation-output-paths drv sub-drvs)
|
|
|
|
|
substitute)))
|
|
|
|
|
(else
|
|
|
|
|
(let ((inputs (remove (lambda (i)
|
|
|
|
|
(or (member i build) ; XXX: quadratic
|
|
|
|
|
(input-built? i)
|
|
|
|
|
(input-substitutable? i)))
|
|
|
|
|
(derivation-inputs drv))))
|
|
|
|
|
(fold2 loop
|
|
|
|
|
(append inputs build)
|
|
|
|
|
(append (append-map (lambda (input)
|
|
|
|
|
(if (and (not (input-built? input))
|
|
|
|
|
(input-substitutable? input))
|
|
|
|
|
(derivation-input-output-paths
|
|
|
|
|
input)
|
|
|
|
|
'()))
|
|
|
|
|
(derivation-inputs drv))
|
|
|
|
|
substitute)
|
|
|
|
|
(map (lambda (i)
|
|
|
|
|
(call-with-input-file (derivation-input-path i)
|
|
|
|
|
read-derivation))
|
|
|
|
|
inputs)
|
|
|
|
|
(map derivation-input-sub-derivations inputs)))))))
|
2012-06-30 18:37:03 -04:00
|
|
|
|
|
2013-01-30 12:56:20 -05:00
|
|
|
|
(define (%read-derivation drv-port)
|
|
|
|
|
;; Actually read derivation from DRV-PORT.
|
2012-04-18 17:34:12 -04:00
|
|
|
|
|
|
|
|
|
(define comma (string->symbol ","))
|
|
|
|
|
|
|
|
|
|
(define (ununquote x)
|
|
|
|
|
(match x
|
|
|
|
|
(('unquote x) (ununquote x))
|
|
|
|
|
((x ...) (map ununquote x))
|
|
|
|
|
(_ x)))
|
|
|
|
|
|
|
|
|
|
(define (outputs->alist x)
|
|
|
|
|
(fold-right (lambda (output result)
|
|
|
|
|
(match output
|
|
|
|
|
((name path "" "")
|
|
|
|
|
(alist-cons name
|
|
|
|
|
(make-derivation-output path #f #f)
|
|
|
|
|
result))
|
|
|
|
|
((name path hash-algo hash)
|
|
|
|
|
;; fixed-output
|
2012-06-09 12:49:19 -04:00
|
|
|
|
(let ((algo (string->symbol hash-algo))
|
|
|
|
|
(hash (base16-string->bytevector hash)))
|
2012-04-18 17:34:12 -04:00
|
|
|
|
(alist-cons name
|
|
|
|
|
(make-derivation-output path algo hash)
|
|
|
|
|
result)))))
|
|
|
|
|
'()
|
|
|
|
|
x))
|
|
|
|
|
|
|
|
|
|
(define (make-input-drvs x)
|
|
|
|
|
(fold-right (lambda (input result)
|
|
|
|
|
(match input
|
|
|
|
|
((path (sub-drvs ...))
|
|
|
|
|
(cons (make-derivation-input path sub-drvs)
|
|
|
|
|
result))))
|
|
|
|
|
'()
|
|
|
|
|
x))
|
|
|
|
|
|
2012-10-05 19:24:46 -04:00
|
|
|
|
;; The contents of a derivation are typically ASCII, but choosing
|
|
|
|
|
;; UTF-8 allows us to take the fast path for Guile's `scm_getc'.
|
|
|
|
|
(set-port-encoding! drv-port "UTF-8")
|
|
|
|
|
|
2012-04-18 17:34:12 -04:00
|
|
|
|
(let loop ((exp (read drv-port))
|
|
|
|
|
(result '()))
|
|
|
|
|
(match exp
|
|
|
|
|
((? eof-object?)
|
|
|
|
|
(let ((result (reverse result)))
|
|
|
|
|
(match result
|
|
|
|
|
(('Derive ((outputs ...) (input-drvs ...)
|
|
|
|
|
(input-srcs ...)
|
|
|
|
|
(? string? system)
|
|
|
|
|
(? string? builder)
|
|
|
|
|
((? string? args) ...)
|
|
|
|
|
((var value) ...)))
|
|
|
|
|
(make-derivation (outputs->alist outputs)
|
|
|
|
|
(make-input-drvs input-drvs)
|
|
|
|
|
input-srcs
|
|
|
|
|
system builder args
|
2013-09-17 17:00:55 -04:00
|
|
|
|
(fold-right alist-cons '() var value)
|
|
|
|
|
(port-filename drv-port)))
|
2012-04-18 17:34:12 -04:00
|
|
|
|
(_
|
|
|
|
|
(error "failed to parse derivation" drv-port result)))))
|
|
|
|
|
((? (cut eq? <> comma))
|
|
|
|
|
(loop (read drv-port) result))
|
|
|
|
|
(_
|
|
|
|
|
(loop (read drv-port)
|
|
|
|
|
(cons (ununquote exp) result))))))
|
|
|
|
|
|
2013-01-30 12:56:20 -05:00
|
|
|
|
(define read-derivation
|
|
|
|
|
(let ((cache (make-weak-value-hash-table 200)))
|
|
|
|
|
(lambda (drv-port)
|
|
|
|
|
"Read the derivation from DRV-PORT and return the corresponding
|
|
|
|
|
<derivation> object."
|
|
|
|
|
;; Memoize that operation because `%read-derivation' is quite expensive,
|
|
|
|
|
;; and because the same argument is read more than 15 times on average
|
|
|
|
|
;; during something like (package-derivation s gdb).
|
|
|
|
|
(let ((file (and=> (port-filename drv-port) basename)))
|
|
|
|
|
(or (and file (hash-ref cache file))
|
|
|
|
|
(let ((drv (%read-derivation drv-port)))
|
|
|
|
|
(hash-set! cache file drv)
|
|
|
|
|
drv))))))
|
|
|
|
|
|
2013-03-16 11:46:46 -04:00
|
|
|
|
(define-inlinable (write-sequence lst write-item port)
|
|
|
|
|
;; Write each element of LST with WRITE-ITEM to PORT, separating them with a
|
|
|
|
|
;; comma.
|
|
|
|
|
(match lst
|
|
|
|
|
(()
|
|
|
|
|
#t)
|
|
|
|
|
((prefix (... ...) last)
|
|
|
|
|
(for-each (lambda (item)
|
|
|
|
|
(write-item item port)
|
|
|
|
|
(display "," port))
|
|
|
|
|
prefix)
|
|
|
|
|
(write-item last port))))
|
|
|
|
|
|
|
|
|
|
(define-inlinable (write-list lst write-item port)
|
|
|
|
|
;; Write LST as a derivation list to PORT, using WRITE-ITEM to write each
|
|
|
|
|
;; element.
|
|
|
|
|
(display "[" port)
|
|
|
|
|
(write-sequence lst write-item port)
|
|
|
|
|
(display "]" port))
|
|
|
|
|
|
|
|
|
|
(define-inlinable (write-tuple lst write-item port)
|
|
|
|
|
;; Same, but write LST as a tuple.
|
|
|
|
|
(display "(" port)
|
|
|
|
|
(write-sequence lst write-item port)
|
|
|
|
|
(display ")" port))
|
|
|
|
|
|
2012-04-18 17:34:12 -04:00
|
|
|
|
(define (write-derivation drv port)
|
|
|
|
|
"Write the ATerm-like serialization of DRV to PORT. See Section 2.4 of
|
|
|
|
|
Eelco Dolstra's PhD dissertation for an overview of a previous version of
|
|
|
|
|
that form."
|
2012-09-01 13:21:06 -04:00
|
|
|
|
|
|
|
|
|
;; Make sure we're using the faster implementation.
|
|
|
|
|
(define format simple-format)
|
|
|
|
|
|
2013-03-16 11:46:46 -04:00
|
|
|
|
(define (write-string-list lst)
|
|
|
|
|
(write-list lst write port))
|
2012-04-18 17:34:12 -04:00
|
|
|
|
|
2012-07-01 19:23:39 -04:00
|
|
|
|
(define (coalesce-duplicate-inputs inputs)
|
|
|
|
|
;; Return a list of inputs, such that when INPUTS contains the same DRV
|
|
|
|
|
;; twice, they are coalesced, with their sub-derivations merged. This is
|
|
|
|
|
;; needed because Nix itself keeps only one of them.
|
|
|
|
|
(fold (lambda (input result)
|
|
|
|
|
(match input
|
|
|
|
|
(($ <derivation-input> path sub-drvs)
|
|
|
|
|
;; XXX: quadratic
|
|
|
|
|
(match (find (match-lambda
|
|
|
|
|
(($ <derivation-input> p s)
|
|
|
|
|
(string=? p path)))
|
|
|
|
|
result)
|
|
|
|
|
(#f
|
|
|
|
|
(cons input result))
|
|
|
|
|
((and dup ($ <derivation-input> _ sub-drvs2))
|
|
|
|
|
;; Merge DUP with INPUT.
|
|
|
|
|
(let ((sub-drvs (delete-duplicates
|
|
|
|
|
(append sub-drvs sub-drvs2))))
|
|
|
|
|
(cons (make-derivation-input path sub-drvs)
|
|
|
|
|
(delq dup result))))))))
|
|
|
|
|
'()
|
|
|
|
|
inputs))
|
|
|
|
|
|
2013-03-16 11:46:46 -04:00
|
|
|
|
(define (write-output output port)
|
|
|
|
|
(match output
|
|
|
|
|
((name . ($ <derivation-output> path hash-algo hash))
|
|
|
|
|
(write-tuple (list name path
|
|
|
|
|
(or (and=> hash-algo symbol->string) "")
|
|
|
|
|
(or (and=> hash bytevector->base16-string)
|
|
|
|
|
""))
|
|
|
|
|
write
|
|
|
|
|
port))))
|
|
|
|
|
|
|
|
|
|
(define (write-input input port)
|
|
|
|
|
(match input
|
|
|
|
|
(($ <derivation-input> path sub-drvs)
|
|
|
|
|
(display "(" port)
|
|
|
|
|
(write path port)
|
|
|
|
|
(display "," port)
|
|
|
|
|
(write-string-list (sort sub-drvs string<?))
|
|
|
|
|
(display ")" port))))
|
|
|
|
|
|
|
|
|
|
(define (write-env-var env-var port)
|
|
|
|
|
(match env-var
|
|
|
|
|
((name . value)
|
|
|
|
|
(display "(" port)
|
|
|
|
|
(write name port)
|
|
|
|
|
(display "," port)
|
|
|
|
|
(write value port)
|
|
|
|
|
(display ")" port))))
|
|
|
|
|
|
2012-07-01 16:55:49 -04:00
|
|
|
|
;; Note: lists are sorted alphabetically, to conform with the behavior of
|
|
|
|
|
;; C++ `std::map' in Nix itself.
|
|
|
|
|
|
2012-04-18 17:34:12 -04:00
|
|
|
|
(match drv
|
|
|
|
|
(($ <derivation> outputs inputs sources
|
|
|
|
|
system builder args env-vars)
|
|
|
|
|
(display "Derive(" port)
|
2013-03-16 11:46:46 -04:00
|
|
|
|
(write-list (sort outputs
|
|
|
|
|
(lambda (o1 o2)
|
|
|
|
|
(string<? (car o1) (car o2))))
|
|
|
|
|
write-output
|
|
|
|
|
port)
|
2012-04-18 17:34:12 -04:00
|
|
|
|
(display "," port)
|
2013-03-16 11:46:46 -04:00
|
|
|
|
(write-list (sort (coalesce-duplicate-inputs inputs)
|
|
|
|
|
(lambda (i1 i2)
|
|
|
|
|
(string<? (derivation-input-path i1)
|
|
|
|
|
(derivation-input-path i2))))
|
|
|
|
|
write-input
|
|
|
|
|
port)
|
2012-04-18 17:34:12 -04:00
|
|
|
|
(display "," port)
|
2013-03-16 11:46:46 -04:00
|
|
|
|
(write-string-list (sort sources string<?))
|
2012-04-18 17:34:12 -04:00
|
|
|
|
(format port ",~s,~s," system builder)
|
2013-03-16 11:46:46 -04:00
|
|
|
|
(write-string-list args)
|
2012-04-18 17:34:12 -04:00
|
|
|
|
(display "," port)
|
2013-03-16 11:46:46 -04:00
|
|
|
|
(write-list (sort env-vars
|
|
|
|
|
(lambda (e1 e2)
|
|
|
|
|
(string<? (car e1) (car e2))))
|
|
|
|
|
write-env-var
|
|
|
|
|
port)
|
2012-04-18 17:34:12 -04:00
|
|
|
|
(display ")" port))))
|
|
|
|
|
|
2012-09-01 13:21:06 -04:00
|
|
|
|
(define derivation-path->output-path
|
|
|
|
|
;; This procedure is called frequently, so memoize it.
|
|
|
|
|
(memoize
|
|
|
|
|
(lambda* (path #:optional (output "out"))
|
|
|
|
|
"Read the derivation from PATH (`/nix/store/xxx.drv'), and return the store
|
2012-06-07 17:15:00 -04:00
|
|
|
|
path of its output OUTPUT."
|
2012-09-01 13:21:06 -04:00
|
|
|
|
(let* ((drv (call-with-input-file path read-derivation))
|
|
|
|
|
(outputs (derivation-outputs drv)))
|
|
|
|
|
(and=> (assoc-ref outputs output) derivation-output-path)))))
|
2012-06-07 17:15:00 -04:00
|
|
|
|
|
2013-01-05 17:51:13 -05:00
|
|
|
|
(define (derivation-path->output-paths path)
|
|
|
|
|
"Read the derivation from PATH (`/nix/store/xxx.drv'), and return the
|
|
|
|
|
list of name/path pairs of its outputs."
|
|
|
|
|
(let* ((drv (call-with-input-file path read-derivation))
|
|
|
|
|
(outputs (derivation-outputs drv)))
|
|
|
|
|
(map (match-lambda
|
|
|
|
|
((name . output)
|
|
|
|
|
(cons name (derivation-output-path output))))
|
|
|
|
|
outputs)))
|
|
|
|
|
|
2012-06-07 17:15:00 -04:00
|
|
|
|
|
|
|
|
|
;;;
|
|
|
|
|
;;; Derivation primitive.
|
|
|
|
|
;;;
|
|
|
|
|
|
2012-06-01 17:29:55 -04:00
|
|
|
|
(define (compressed-hash bv size) ; `compressHash'
|
|
|
|
|
"Given the hash stored in BV, return a compressed version thereof that fits
|
|
|
|
|
in SIZE bytes."
|
|
|
|
|
(define new (make-bytevector size 0))
|
|
|
|
|
(define old-size (bytevector-length bv))
|
|
|
|
|
(let loop ((i 0))
|
|
|
|
|
(if (= i old-size)
|
|
|
|
|
new
|
|
|
|
|
(let* ((j (modulo i size))
|
|
|
|
|
(o (bytevector-u8-ref new j)))
|
|
|
|
|
(bytevector-u8-set! new j
|
|
|
|
|
(logxor o (bytevector-u8-ref bv i)))
|
|
|
|
|
(loop (+ 1 i))))))
|
2012-04-18 17:34:12 -04:00
|
|
|
|
|
2012-06-07 17:15:00 -04:00
|
|
|
|
(define derivation-hash ; `hashDerivationModulo' in derivations.cc
|
|
|
|
|
(memoize
|
|
|
|
|
(lambda (drv)
|
|
|
|
|
"Return the hash of DRV, modulo its fixed-output inputs, as a bytevector."
|
|
|
|
|
(match drv
|
|
|
|
|
(($ <derivation> ((_ . ($ <derivation-output> path
|
2012-06-09 12:49:19 -04:00
|
|
|
|
(? symbol? hash-algo) (? bytevector? hash)))))
|
2012-06-07 17:15:00 -04:00
|
|
|
|
;; A fixed-output derivation.
|
2012-04-18 17:34:12 -04:00
|
|
|
|
(sha256
|
2012-06-07 17:15:00 -04:00
|
|
|
|
(string->utf8
|
|
|
|
|
(string-append "fixed:out:" (symbol->string hash-algo)
|
2012-06-09 12:49:19 -04:00
|
|
|
|
":" (bytevector->base16-string hash)
|
|
|
|
|
":" path))))
|
2012-06-07 17:15:00 -04:00
|
|
|
|
(($ <derivation> outputs inputs sources
|
|
|
|
|
system builder args env-vars)
|
|
|
|
|
;; A regular derivation: replace the path of each input with that
|
|
|
|
|
;; input's hash; return the hash of serialization of the resulting
|
2012-07-01 16:55:49 -04:00
|
|
|
|
;; derivation.
|
|
|
|
|
(let* ((inputs (map (match-lambda
|
|
|
|
|
(($ <derivation-input> path sub-drvs)
|
|
|
|
|
(let ((hash (call-with-input-file path
|
|
|
|
|
(compose bytevector->base16-string
|
|
|
|
|
derivation-hash
|
|
|
|
|
read-derivation))))
|
|
|
|
|
(make-derivation-input hash sub-drvs))))
|
|
|
|
|
inputs))
|
|
|
|
|
(drv (make-derivation outputs inputs sources
|
2013-09-17 17:00:55 -04:00
|
|
|
|
system builder args env-vars
|
|
|
|
|
#f)))
|
2013-07-02 19:17:11 -04:00
|
|
|
|
|
|
|
|
|
;; XXX: At this point this remains faster than `port-sha256', because
|
|
|
|
|
;; the SHA256 port's `write' method gets called for every single
|
|
|
|
|
;; character.
|
2012-06-07 17:15:00 -04:00
|
|
|
|
(sha256
|
2013-06-14 09:48:29 -04:00
|
|
|
|
(with-fluids ((%default-port-encoding "UTF-8"))
|
|
|
|
|
(string->utf8 (call-with-output-string
|
|
|
|
|
(cut write-derivation drv <>)))))))))))
|
2012-04-18 17:34:12 -04:00
|
|
|
|
|
2012-06-01 17:29:55 -04:00
|
|
|
|
(define (store-path type hash name) ; makeStorePath
|
|
|
|
|
"Return the store path for NAME/HASH/TYPE."
|
|
|
|
|
(let* ((s (string-append type ":sha256:"
|
|
|
|
|
(bytevector->base16-string hash) ":"
|
|
|
|
|
(%store-prefix) ":" name))
|
|
|
|
|
(h (sha256 (string->utf8 s)))
|
|
|
|
|
(c (compressed-hash h 20)))
|
|
|
|
|
(string-append (%store-prefix) "/"
|
|
|
|
|
(bytevector->nix-base32-string c) "-"
|
|
|
|
|
name)))
|
|
|
|
|
|
|
|
|
|
(define (output-path output hash name) ; makeOutputPath
|
|
|
|
|
"Return an output path for OUTPUT (the name of the output as a string) of
|
|
|
|
|
the derivation called NAME with hash HASH."
|
|
|
|
|
(store-path (string-append "output:" output) hash
|
|
|
|
|
(if (string=? output "out")
|
|
|
|
|
name
|
|
|
|
|
(string-append name "-" output))))
|
|
|
|
|
|
2013-08-26 16:11:04 -04:00
|
|
|
|
(define* (derivation store name builder args
|
|
|
|
|
#:key
|
|
|
|
|
(system (%current-system)) (env-vars '())
|
|
|
|
|
(inputs '()) (outputs '("out"))
|
2013-08-26 16:12:46 -04:00
|
|
|
|
hash hash-algo hash-mode
|
2013-08-27 12:34:49 -04:00
|
|
|
|
references-graphs)
|
2012-06-01 17:29:55 -04:00
|
|
|
|
"Build a derivation with the given arguments. Return the resulting
|
2012-06-04 18:04:07 -04:00
|
|
|
|
store path and <derivation> object. When HASH, HASH-ALGO, and HASH-MODE
|
2012-06-01 17:29:55 -04:00
|
|
|
|
are given, a fixed-output derivation is created---i.e., one whose result is
|
2013-08-26 16:12:46 -04:00
|
|
|
|
known in advance, such as a file download.
|
|
|
|
|
|
2013-08-27 12:34:49 -04:00
|
|
|
|
When REFERENCES-GRAPHS is true, it must be a list of file name/store path
|
2013-08-26 16:12:46 -04:00
|
|
|
|
pairs. In that case, the reference graph of each store path is exported in
|
|
|
|
|
the build environment in the corresponding file, in a simple text format."
|
2012-12-09 18:44:17 -05:00
|
|
|
|
(define direct-store-path?
|
|
|
|
|
(let ((len (+ 1 (string-length (%store-prefix)))))
|
|
|
|
|
(lambda (p)
|
|
|
|
|
;; Return #t if P is a store path, and not a sub-directory of a
|
|
|
|
|
;; store path. This predicate is needed because files *under* a
|
|
|
|
|
;; store path are not valid inputs.
|
|
|
|
|
(and (store-path? p)
|
|
|
|
|
(not (string-index (substring p len) #\/))))))
|
|
|
|
|
|
2012-06-01 17:29:55 -04:00
|
|
|
|
(define (add-output-paths drv)
|
|
|
|
|
;; Return DRV with an actual store path for each of its output and the
|
|
|
|
|
;; corresponding environment variable.
|
|
|
|
|
(match drv
|
|
|
|
|
(($ <derivation> outputs inputs sources
|
|
|
|
|
system builder args env-vars)
|
|
|
|
|
(let* ((drv-hash (derivation-hash drv))
|
|
|
|
|
(outputs (map (match-lambda
|
2012-06-08 15:31:01 -04:00
|
|
|
|
((output-name . ($ <derivation-output>
|
|
|
|
|
_ algo hash))
|
|
|
|
|
(let ((path (output-path output-name
|
|
|
|
|
drv-hash name)))
|
|
|
|
|
(cons output-name
|
|
|
|
|
(make-derivation-output path algo
|
|
|
|
|
hash)))))
|
|
|
|
|
outputs)))
|
2012-06-01 17:29:55 -04:00
|
|
|
|
(make-derivation outputs inputs sources system builder args
|
|
|
|
|
(map (match-lambda
|
|
|
|
|
((name . value)
|
|
|
|
|
(cons name
|
|
|
|
|
(or (and=> (assoc-ref outputs name)
|
|
|
|
|
derivation-output-path)
|
|
|
|
|
value))))
|
2013-09-17 17:00:55 -04:00
|
|
|
|
env-vars)
|
|
|
|
|
#f)))))
|
2012-06-01 17:29:55 -04:00
|
|
|
|
|
2013-08-26 16:12:46 -04:00
|
|
|
|
(define (user+system-env-vars)
|
|
|
|
|
;; Some options are passed to the build daemon via the env. vars of
|
|
|
|
|
;; derivations (urgh!). We hide that from our API, but here is the place
|
|
|
|
|
;; where we kludgify those options.
|
2013-08-27 12:34:49 -04:00
|
|
|
|
(match references-graphs
|
2013-08-26 16:12:46 -04:00
|
|
|
|
(((file . path) ...)
|
|
|
|
|
(let ((value (map (cut string-append <> " " <>)
|
|
|
|
|
file path)))
|
|
|
|
|
;; XXX: This all breaks down if an element of FILE or PATH contains
|
|
|
|
|
;; white space.
|
|
|
|
|
`(("exportReferencesGraph" . ,(string-join value " "))
|
|
|
|
|
,@env-vars)))
|
|
|
|
|
(#f
|
|
|
|
|
env-vars)))
|
|
|
|
|
|
|
|
|
|
(define (env-vars-with-empty-outputs env-vars)
|
2012-06-01 17:29:55 -04:00
|
|
|
|
;; Return a variant of ENV-VARS where each OUTPUTS is associated with an
|
2012-07-01 16:55:49 -04:00
|
|
|
|
;; empty string, even outputs that do not appear in ENV-VARS.
|
2012-06-01 17:29:55 -04:00
|
|
|
|
(let ((e (map (match-lambda
|
|
|
|
|
((name . val)
|
|
|
|
|
(if (member name outputs)
|
|
|
|
|
(cons name "")
|
|
|
|
|
(cons name val))))
|
|
|
|
|
env-vars)))
|
2012-07-01 16:55:49 -04:00
|
|
|
|
(fold (lambda (output-name env-vars)
|
|
|
|
|
(if (assoc output-name env-vars)
|
|
|
|
|
env-vars
|
|
|
|
|
(append env-vars `((,output-name . "")))))
|
|
|
|
|
e
|
|
|
|
|
outputs)))
|
2012-06-01 17:29:55 -04:00
|
|
|
|
|
2013-09-17 17:00:55 -04:00
|
|
|
|
(define (set-file-name drv file)
|
|
|
|
|
;; Set FILE as the 'file-name' field of DRV.
|
|
|
|
|
(match drv
|
|
|
|
|
(($ <derivation> outputs inputs sources system builder
|
|
|
|
|
args env-vars)
|
|
|
|
|
(make-derivation outputs inputs sources system builder
|
|
|
|
|
args env-vars file))))
|
|
|
|
|
|
2012-06-01 17:29:55 -04:00
|
|
|
|
(let* ((outputs (map (lambda (name)
|
|
|
|
|
;; Return outputs with an empty path.
|
|
|
|
|
(cons name
|
|
|
|
|
(make-derivation-output "" hash-algo hash)))
|
|
|
|
|
outputs))
|
|
|
|
|
(inputs (map (match-lambda
|
2012-12-09 18:44:17 -05:00
|
|
|
|
(((? direct-store-path? input))
|
2012-06-07 17:15:00 -04:00
|
|
|
|
(make-derivation-input input '("out")))
|
2012-12-09 18:44:17 -05:00
|
|
|
|
(((? direct-store-path? input) sub-drvs ...)
|
2012-06-01 17:29:55 -04:00
|
|
|
|
(make-derivation-input input sub-drvs))
|
|
|
|
|
((input . _)
|
|
|
|
|
(let ((path (add-to-store store
|
|
|
|
|
(basename input)
|
2013-01-30 10:30:49 -05:00
|
|
|
|
#t "sha256" input)))
|
2012-06-01 17:29:55 -04:00
|
|
|
|
(make-derivation-input path '()))))
|
2012-06-28 18:27:32 -04:00
|
|
|
|
(delete-duplicates inputs)))
|
2013-08-26 16:12:46 -04:00
|
|
|
|
(env-vars (env-vars-with-empty-outputs (user+system-env-vars)))
|
2012-06-01 17:29:55 -04:00
|
|
|
|
(drv-masked (make-derivation outputs
|
|
|
|
|
(filter (compose derivation-path?
|
|
|
|
|
derivation-input-path)
|
|
|
|
|
inputs)
|
|
|
|
|
(filter-map (lambda (i)
|
|
|
|
|
(let ((p (derivation-input-path i)))
|
|
|
|
|
(and (not (derivation-path? p))
|
|
|
|
|
p)))
|
|
|
|
|
inputs)
|
2013-09-17 17:00:55 -04:00
|
|
|
|
system builder args env-vars #f))
|
2012-06-01 17:29:55 -04:00
|
|
|
|
(drv (add-output-paths drv-masked)))
|
2012-06-07 17:15:00 -04:00
|
|
|
|
|
2013-09-17 17:00:55 -04:00
|
|
|
|
(let ((file (add-text-to-store store (string-append name ".drv")
|
|
|
|
|
(call-with-output-string
|
|
|
|
|
(cut write-derivation drv <>))
|
|
|
|
|
(map derivation-input-path
|
|
|
|
|
inputs))))
|
|
|
|
|
(values file (set-file-name drv file)))))
|
2012-06-08 15:31:01 -04:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
;;;
|
|
|
|
|
;;; Guile-based builders.
|
|
|
|
|
;;;
|
|
|
|
|
|
|
|
|
|
(define %guile-for-build
|
|
|
|
|
;; The derivation of the Guile to be used within the build environment,
|
|
|
|
|
;; when using `build-expression->derivation'.
|
2012-10-25 12:03:48 -04:00
|
|
|
|
(make-parameter #f))
|
2012-06-08 15:31:01 -04:00
|
|
|
|
|
2012-10-22 17:30:35 -04:00
|
|
|
|
(define (parent-directories file-name)
|
|
|
|
|
"Return the list of parent dirs of FILE-NAME, in the order in which an
|
|
|
|
|
`mkdir -p' implementation would make them."
|
|
|
|
|
(let ((not-slash (char-set-complement (char-set #\/))))
|
|
|
|
|
(reverse
|
|
|
|
|
(fold (lambda (dir result)
|
|
|
|
|
(match result
|
|
|
|
|
(()
|
|
|
|
|
(list dir))
|
|
|
|
|
((prev _ ...)
|
|
|
|
|
(cons (string-append prev "/" dir)
|
|
|
|
|
result))))
|
|
|
|
|
'()
|
|
|
|
|
(remove (cut string=? <> ".")
|
|
|
|
|
(string-tokenize (dirname file-name) not-slash))))))
|
|
|
|
|
|
2012-06-11 17:12:55 -04:00
|
|
|
|
(define* (imported-files store files
|
2012-10-25 12:03:48 -04:00
|
|
|
|
#:key (name "file-import")
|
|
|
|
|
(system (%current-system))
|
|
|
|
|
(guile (%guile-for-build)))
|
2012-06-11 17:12:55 -04:00
|
|
|
|
"Return a derivation that imports FILES into STORE. FILES must be a list
|
|
|
|
|
of (FINAL-PATH . FILE-NAME) pairs; each FILE-NAME is read from the file
|
|
|
|
|
system, imported, and appears under FINAL-PATH in the resulting store path."
|
|
|
|
|
(let* ((files (map (match-lambda
|
|
|
|
|
((final-path . file-name)
|
2012-06-13 11:21:27 -04:00
|
|
|
|
(list final-path
|
2013-01-30 10:30:49 -05:00
|
|
|
|
(add-to-store store (basename final-path) #f
|
2012-06-11 17:12:55 -04:00
|
|
|
|
"sha256" file-name))))
|
|
|
|
|
files))
|
|
|
|
|
(builder
|
|
|
|
|
`(begin
|
|
|
|
|
(mkdir %output) (chdir %output)
|
|
|
|
|
,@(append-map (match-lambda
|
2012-06-13 11:21:27 -04:00
|
|
|
|
((final-path store-path)
|
2012-10-22 17:30:35 -04:00
|
|
|
|
(append (match (parent-directories final-path)
|
2012-06-11 17:12:55 -04:00
|
|
|
|
(() '())
|
|
|
|
|
((head ... tail)
|
|
|
|
|
(append (map (lambda (d)
|
|
|
|
|
`(false-if-exception
|
|
|
|
|
(mkdir ,d)))
|
|
|
|
|
head)
|
2012-06-12 17:30:00 -04:00
|
|
|
|
`((or (file-exists? ,tail)
|
|
|
|
|
(mkdir ,tail))))))
|
2012-06-11 17:12:55 -04:00
|
|
|
|
`((symlink ,store-path ,final-path)))))
|
|
|
|
|
files))))
|
2012-10-25 17:14:27 -04:00
|
|
|
|
(build-expression->derivation store name system
|
2012-10-25 12:03:48 -04:00
|
|
|
|
builder files
|
|
|
|
|
#:guile-for-build guile)))
|
2012-06-11 17:12:55 -04:00
|
|
|
|
|
2012-06-11 18:18:14 -04:00
|
|
|
|
(define* (imported-modules store modules
|
|
|
|
|
#:key (name "module-import")
|
2012-10-25 12:03:48 -04:00
|
|
|
|
(system (%current-system))
|
2013-02-20 15:08:09 -05:00
|
|
|
|
(guile (%guile-for-build))
|
|
|
|
|
(module-path %load-path))
|
2012-06-11 18:18:14 -04:00
|
|
|
|
"Return a derivation that contains the source files of MODULES, a list of
|
2013-02-20 15:08:09 -05:00
|
|
|
|
module names such as `(ice-9 q)'. All of MODULES must be in the MODULE-PATH
|
2012-06-11 18:18:14 -04:00
|
|
|
|
search path."
|
|
|
|
|
;; TODO: Determine the closure of MODULES, build the `.go' files,
|
|
|
|
|
;; canonicalize the source files through read/write, etc.
|
|
|
|
|
(let ((files (map (lambda (m)
|
|
|
|
|
(let ((f (string-append
|
|
|
|
|
(string-join (map symbol->string m) "/")
|
|
|
|
|
".scm")))
|
2013-02-20 15:08:09 -05:00
|
|
|
|
(cons f (search-path module-path f))))
|
2012-06-11 18:18:14 -04:00
|
|
|
|
modules)))
|
2012-10-25 12:03:48 -04:00
|
|
|
|
(imported-files store files #:name name #:system system
|
|
|
|
|
#:guile guile)))
|
2012-06-11 18:18:14 -04:00
|
|
|
|
|
2012-10-22 17:30:35 -04:00
|
|
|
|
(define* (compiled-modules store modules
|
|
|
|
|
#:key (name "module-import-compiled")
|
2012-10-25 12:03:48 -04:00
|
|
|
|
(system (%current-system))
|
2013-02-20 15:08:09 -05:00
|
|
|
|
(guile (%guile-for-build))
|
|
|
|
|
(module-path %load-path))
|
2012-10-22 17:30:35 -04:00
|
|
|
|
"Return a derivation that builds a tree containing the `.go' files
|
|
|
|
|
corresponding to MODULES. All the MODULES are built in a context where
|
|
|
|
|
they can refer to each other."
|
|
|
|
|
(let* ((module-drv (imported-modules store modules
|
2012-10-25 12:03:48 -04:00
|
|
|
|
#:system system
|
2013-02-20 15:08:09 -05:00
|
|
|
|
#:guile guile
|
|
|
|
|
#:module-path module-path))
|
2012-10-22 17:30:35 -04:00
|
|
|
|
(module-dir (derivation-path->output-path module-drv))
|
|
|
|
|
(files (map (lambda (m)
|
|
|
|
|
(let ((f (string-join (map symbol->string m)
|
|
|
|
|
"/")))
|
|
|
|
|
(cons (string-append f ".go")
|
|
|
|
|
(string-append module-dir "/" f ".scm"))))
|
|
|
|
|
modules)))
|
|
|
|
|
(define builder
|
|
|
|
|
`(begin
|
|
|
|
|
(use-modules (system base compile))
|
|
|
|
|
(let ((out (assoc-ref %outputs "out")))
|
|
|
|
|
(mkdir out)
|
|
|
|
|
(chdir out))
|
|
|
|
|
|
|
|
|
|
(set! %load-path
|
|
|
|
|
(cons ,module-dir %load-path))
|
|
|
|
|
|
|
|
|
|
,@(map (match-lambda
|
|
|
|
|
((output . input)
|
|
|
|
|
(let ((make-parent-dirs (map (lambda (dir)
|
|
|
|
|
`(unless (file-exists? ,dir)
|
|
|
|
|
(mkdir ,dir)))
|
|
|
|
|
(parent-directories output))))
|
|
|
|
|
`(begin
|
|
|
|
|
,@make-parent-dirs
|
|
|
|
|
(compile-file ,input
|
|
|
|
|
#:output-file ,output
|
|
|
|
|
#:opts %auto-compilation-options)))))
|
|
|
|
|
files)))
|
|
|
|
|
|
|
|
|
|
(build-expression->derivation store name system builder
|
2012-10-25 12:03:48 -04:00
|
|
|
|
`(("modules" ,module-drv))
|
|
|
|
|
#:guile-for-build guile)))
|
2012-06-11 18:18:14 -04:00
|
|
|
|
|
2012-06-08 15:31:01 -04:00
|
|
|
|
(define* (build-expression->derivation store name system exp inputs
|
2012-06-09 17:16:55 -04:00
|
|
|
|
#:key (outputs '("out"))
|
2012-06-11 18:18:14 -04:00
|
|
|
|
hash hash-algo
|
2012-09-01 05:33:20 -04:00
|
|
|
|
(env-vars '())
|
2012-09-01 05:45:52 -04:00
|
|
|
|
(modules '())
|
2013-08-26 16:19:21 -04:00
|
|
|
|
guile-for-build
|
2013-08-27 12:34:49 -04:00
|
|
|
|
references-graphs)
|
2013-01-16 17:09:06 -05:00
|
|
|
|
"Return a derivation that executes Scheme expression EXP as a builder
|
|
|
|
|
for derivation NAME. INPUTS must be a list of (NAME DRV-PATH SUB-DRV)
|
|
|
|
|
tuples; when SUB-DRV is omitted, \"out\" is assumed. MODULES is a list
|
|
|
|
|
of names of Guile modules from the current search path to be copied in
|
|
|
|
|
the store, compiled, and made available in the load path during the
|
|
|
|
|
execution of EXP.
|
|
|
|
|
|
|
|
|
|
EXP is evaluated in an environment where %OUTPUT is bound to the main
|
|
|
|
|
output path, %OUTPUTS is bound to a list of output/path pairs, and where
|
|
|
|
|
%BUILD-INPUTS is bound to an alist of string/output-path pairs made from
|
|
|
|
|
INPUTS. Optionally, ENV-VARS is a list of string pairs specifying the
|
|
|
|
|
name and value of environment variables visible to the builder. The
|
|
|
|
|
builder terminates by passing the result of EXP to `exit'; thus, when
|
|
|
|
|
EXP returns #f, the build is considered to have failed.
|
2012-09-01 05:45:52 -04:00
|
|
|
|
|
|
|
|
|
EXP is built using GUILE-FOR-BUILD (a derivation). When GUILE-FOR-BUILD is
|
2013-08-26 16:19:21 -04:00
|
|
|
|
omitted or is #f, the value of the `%guile-for-build' fluid is used instead.
|
|
|
|
|
|
2013-08-27 12:34:49 -04:00
|
|
|
|
See the `derivation' procedure for the meaning of REFERENCES-GRAPHS."
|
2012-10-25 12:03:48 -04:00
|
|
|
|
(define guile-drv
|
|
|
|
|
(or guile-for-build (%guile-for-build)))
|
|
|
|
|
|
2012-06-08 15:31:01 -04:00
|
|
|
|
(define guile
|
2012-10-25 12:03:48 -04:00
|
|
|
|
(string-append (derivation-path->output-path guile-drv)
|
2012-06-08 15:31:01 -04:00
|
|
|
|
"/bin/guile"))
|
|
|
|
|
|
2012-06-17 10:43:40 -04:00
|
|
|
|
(define module-form?
|
|
|
|
|
(match-lambda
|
2013-08-26 16:11:04 -04:00
|
|
|
|
(((or 'define-module 'use-modules) _ ...) #t)
|
|
|
|
|
(_ #f)))
|
2012-06-17 10:43:40 -04:00
|
|
|
|
|
2012-11-08 18:07:10 -05:00
|
|
|
|
(define source-path
|
|
|
|
|
;; When passed an input that is a source, return its path; otherwise
|
|
|
|
|
;; return #f.
|
|
|
|
|
(match-lambda
|
|
|
|
|
((_ path _ ...)
|
|
|
|
|
(and (not (derivation-path? path))
|
|
|
|
|
path))))
|
|
|
|
|
|
2012-06-08 15:31:01 -04:00
|
|
|
|
(let* ((prologue `(begin
|
2012-06-17 10:43:40 -04:00
|
|
|
|
,@(match exp
|
|
|
|
|
((_ ...)
|
|
|
|
|
;; Module forms must appear at the top-level so
|
|
|
|
|
;; that any macros they export can be expanded.
|
|
|
|
|
(filter module-form? exp))
|
|
|
|
|
(_ `(,exp)))
|
|
|
|
|
|
2012-06-08 15:31:01 -04:00
|
|
|
|
(define %output (getenv "out"))
|
2012-06-09 17:16:55 -04:00
|
|
|
|
(define %outputs
|
|
|
|
|
(map (lambda (o)
|
|
|
|
|
(cons o (getenv o)))
|
|
|
|
|
',outputs))
|
2012-06-08 15:31:01 -04:00
|
|
|
|
(define %build-inputs
|
|
|
|
|
',(map (match-lambda
|
2012-06-13 11:21:27 -04:00
|
|
|
|
((name drv . rest)
|
|
|
|
|
(let ((sub (match rest
|
|
|
|
|
(() "out")
|
|
|
|
|
((x) x))))
|
|
|
|
|
(cons name
|
|
|
|
|
(if (derivation-path? drv)
|
|
|
|
|
(derivation-path->output-path drv
|
|
|
|
|
sub)
|
|
|
|
|
drv)))))
|
2012-07-07 16:38:08 -04:00
|
|
|
|
inputs))
|
|
|
|
|
|
2012-10-22 17:30:35 -04:00
|
|
|
|
,@(if (null? modules)
|
|
|
|
|
'()
|
|
|
|
|
;; Remove our own settings.
|
|
|
|
|
'((unsetenv "GUILE_LOAD_COMPILED_PATH")))
|
|
|
|
|
|
2012-07-07 16:38:08 -04:00
|
|
|
|
;; Guile sets it, but remove it to avoid conflicts when
|
|
|
|
|
;; building Guile-using packages.
|
|
|
|
|
(unsetenv "LD_LIBRARY_PATH")))
|
2012-06-08 15:31:01 -04:00
|
|
|
|
(builder (add-text-to-store store
|
|
|
|
|
(string-append name "-guile-builder")
|
2013-03-16 12:22:20 -04:00
|
|
|
|
|
|
|
|
|
;; Explicitly use UTF-8 for determinism,
|
|
|
|
|
;; and also because UTF-8 output is faster.
|
|
|
|
|
(with-fluids ((%default-port-encoding
|
|
|
|
|
"UTF-8"))
|
|
|
|
|
(call-with-output-string
|
|
|
|
|
(lambda (port)
|
|
|
|
|
(write prologue port)
|
|
|
|
|
(write
|
|
|
|
|
`(exit
|
|
|
|
|
,(match exp
|
|
|
|
|
((_ ...)
|
|
|
|
|
(remove module-form? exp))
|
|
|
|
|
(_ `(,exp))))
|
|
|
|
|
port))))
|
2012-11-08 18:07:10 -05:00
|
|
|
|
|
|
|
|
|
;; The references don't really matter
|
|
|
|
|
;; since the builder is always used in
|
|
|
|
|
;; conjunction with the drv that needs
|
|
|
|
|
;; it. For clarity, we add references
|
|
|
|
|
;; to the subset of INPUTS that are
|
|
|
|
|
;; sources, avoiding references to other
|
|
|
|
|
;; .drv; otherwise, BUILDER's hash would
|
|
|
|
|
;; depend on those, even if they are
|
|
|
|
|
;; fixed-output.
|
|
|
|
|
(filter-map source-path inputs)))
|
|
|
|
|
|
2012-10-22 17:30:35 -04:00
|
|
|
|
(mod-drv (and (pair? modules)
|
2012-10-25 17:14:27 -04:00
|
|
|
|
(imported-modules store modules
|
|
|
|
|
#:guile guile-drv
|
|
|
|
|
#:system system)))
|
2012-06-11 18:18:14 -04:00
|
|
|
|
(mod-dir (and mod-drv
|
2012-10-22 17:30:35 -04:00
|
|
|
|
(derivation-path->output-path mod-drv)))
|
|
|
|
|
(go-drv (and (pair? modules)
|
2012-10-25 17:14:27 -04:00
|
|
|
|
(compiled-modules store modules
|
|
|
|
|
#:guile guile-drv
|
|
|
|
|
#:system system)))
|
2012-10-22 17:30:35 -04:00
|
|
|
|
(go-dir (and go-drv
|
|
|
|
|
(derivation-path->output-path go-drv))))
|
2013-08-26 16:11:04 -04:00
|
|
|
|
(derivation store name guile
|
2012-06-11 18:18:14 -04:00
|
|
|
|
`("--no-auto-compile"
|
|
|
|
|
,@(if mod-dir `("-L" ,mod-dir) '())
|
|
|
|
|
,builder)
|
2012-10-22 17:30:35 -04:00
|
|
|
|
|
2013-08-26 16:11:04 -04:00
|
|
|
|
#:system system
|
|
|
|
|
|
|
|
|
|
#:inputs `((,(or guile-for-build (%guile-for-build)))
|
|
|
|
|
(,builder)
|
|
|
|
|
,@(map cdr inputs)
|
|
|
|
|
,@(if mod-drv `((,mod-drv) (,go-drv)) '()))
|
|
|
|
|
|
2012-10-22 17:30:35 -04:00
|
|
|
|
;; When MODULES is non-empty, shamelessly clobber
|
|
|
|
|
;; $GUILE_LOAD_COMPILED_PATH.
|
2013-08-26 16:11:04 -04:00
|
|
|
|
#:env-vars (if go-dir
|
|
|
|
|
`(("GUILE_LOAD_COMPILED_PATH" . ,go-dir)
|
|
|
|
|
,@(alist-delete "GUILE_LOAD_COMPILED_PATH"
|
|
|
|
|
env-vars))
|
|
|
|
|
env-vars)
|
|
|
|
|
|
2012-06-09 17:16:55 -04:00
|
|
|
|
#:hash hash #:hash-algo hash-algo
|
2013-08-26 16:19:21 -04:00
|
|
|
|
#:outputs outputs
|
2013-08-27 12:34:49 -04:00
|
|
|
|
#:references-graphs references-graphs)))
|