mirror of
https://git.in.rschanz.org/ryan77627/guix.git
synced 2024-12-24 21:38:07 -05:00
gexp: Add 'let-system'.
* guix/gexp.scm (<system-binding>): New record type. (let-system): New macro. (system-binding-compiler): New procedure. (default-expander): Add 'self-quoting?' case. (self-quoting?): New procedure. (lower-inputs): Add 'filterm'. Pass the result of 'mapm/accumulate-builds' through FILTERM. (gexp->sexp)[self-quoting?]: Remove. * tests/gexp.scm ("let-system", "let-system, target") ("let-system, ungexp-native, target") ("let-system, nested"): New tests. * doc/guix.texi (G-Expressions): Document it.
This commit is contained in:
parent
d03001a31a
commit
644cb40cd8
4 changed files with 165 additions and 26 deletions
|
@ -85,6 +85,7 @@
|
||||||
(eval . (put 'with-imported-modules 'scheme-indent-function 1))
|
(eval . (put 'with-imported-modules 'scheme-indent-function 1))
|
||||||
(eval . (put 'with-extensions 'scheme-indent-function 1))
|
(eval . (put 'with-extensions 'scheme-indent-function 1))
|
||||||
(eval . (put 'with-parameters 'scheme-indent-function 1))
|
(eval . (put 'with-parameters 'scheme-indent-function 1))
|
||||||
|
(eval . (put 'let-system 'scheme-indent-function 1))
|
||||||
|
|
||||||
(eval . (put 'with-database 'scheme-indent-function 2))
|
(eval . (put 'with-database 'scheme-indent-function 2))
|
||||||
(eval . (put 'call-with-transaction 'scheme-indent-function 2))
|
(eval . (put 'call-with-transaction 'scheme-indent-function 2))
|
||||||
|
|
|
@ -8123,6 +8123,32 @@ the second case, the resulting script contains a @code{(string-append
|
||||||
@dots{})} expression to construct the file name @emph{at run time}.
|
@dots{})} expression to construct the file name @emph{at run time}.
|
||||||
@end deffn
|
@end deffn
|
||||||
|
|
||||||
|
@deffn {Scheme Syntax} let-system @var{system} @var{body}@dots{}
|
||||||
|
@deffnx {Scheme Syntax} let-system (@var{system} @var{target}) @var{body}@dots{}
|
||||||
|
Bind @var{system} to the currently targeted system---e.g.,
|
||||||
|
@code{"x86_64-linux"}---within @var{body}.
|
||||||
|
|
||||||
|
In the second case, additionally bind @var{target} to the current
|
||||||
|
cross-compilation target---a GNU triplet such as
|
||||||
|
@code{"arm-linux-gnueabihf"}---or @code{#f} if we are not
|
||||||
|
cross-compiling.
|
||||||
|
|
||||||
|
@code{let-system} is useful in the occasional case where the object
|
||||||
|
spliced into the gexp depends on the target system, as in this example:
|
||||||
|
|
||||||
|
@example
|
||||||
|
#~(system*
|
||||||
|
#+(let-system system
|
||||||
|
(cond ((string-prefix? "armhf-" system)
|
||||||
|
(file-append qemu "/bin/qemu-system-arm"))
|
||||||
|
((string-prefix? "x86_64-" system)
|
||||||
|
(file-append qemu "/bin/qemu-system-x86_64"))
|
||||||
|
(else
|
||||||
|
(error "dunno!"))))
|
||||||
|
"-net" "user" #$image)
|
||||||
|
@end example
|
||||||
|
@end deffn
|
||||||
|
|
||||||
@deffn {Scheme Syntax} with-parameters ((@var{parameter} @var{value}) @dots{}) @var{exp}
|
@deffn {Scheme Syntax} with-parameters ((@var{parameter} @var{value}) @dots{}) @var{exp}
|
||||||
This macro is similar to the @code{parameterize} form for
|
This macro is similar to the @code{parameterize} form for
|
||||||
dynamically-bound @dfn{parameters} (@pxref{Parameters,,, guile, GNU
|
dynamically-bound @dfn{parameters} (@pxref{Parameters,,, guile, GNU
|
||||||
|
|
110
guix/gexp.scm
110
guix/gexp.scm
|
@ -37,6 +37,7 @@ (define-module (guix gexp)
|
||||||
gexp?
|
gexp?
|
||||||
with-imported-modules
|
with-imported-modules
|
||||||
with-extensions
|
with-extensions
|
||||||
|
let-system
|
||||||
|
|
||||||
gexp-input
|
gexp-input
|
||||||
gexp-input?
|
gexp-input?
|
||||||
|
@ -195,7 +196,9 @@ (define (default-expander thing obj output)
|
||||||
((? derivation? drv)
|
((? derivation? drv)
|
||||||
(derivation->output-path drv output))
|
(derivation->output-path drv output))
|
||||||
((? string? file)
|
((? string? file)
|
||||||
file)))
|
file)
|
||||||
|
((? self-quoting? obj)
|
||||||
|
obj)))
|
||||||
|
|
||||||
(define (register-compiler! compiler)
|
(define (register-compiler! compiler)
|
||||||
"Register COMPILER as a gexp compiler."
|
"Register COMPILER as a gexp compiler."
|
||||||
|
@ -327,6 +330,52 @@ (define-gexp-compiler raw-derivation-file-compiler <raw-derivation-file>
|
||||||
(derivation-file-name lowered)
|
(derivation-file-name lowered)
|
||||||
lowered)))
|
lowered)))
|
||||||
|
|
||||||
|
|
||||||
|
;;;
|
||||||
|
;;; System dependencies.
|
||||||
|
;;;
|
||||||
|
|
||||||
|
;; Binding form for the current system and cross-compilation target.
|
||||||
|
(define-record-type <system-binding>
|
||||||
|
(system-binding proc)
|
||||||
|
system-binding?
|
||||||
|
(proc system-binding-proc))
|
||||||
|
|
||||||
|
(define-syntax let-system
|
||||||
|
(syntax-rules ()
|
||||||
|
"Introduce a system binding in a gexp. The simplest form is:
|
||||||
|
|
||||||
|
(let-system system
|
||||||
|
(cond ((string=? system \"x86_64-linux\") ...)
|
||||||
|
(else ...)))
|
||||||
|
|
||||||
|
which binds SYSTEM to the currently targeted system. The second form is
|
||||||
|
similar, but it also shows the cross-compilation target:
|
||||||
|
|
||||||
|
(let-system (system target)
|
||||||
|
...)
|
||||||
|
|
||||||
|
Here TARGET is bound to the cross-compilation triplet or #f."
|
||||||
|
((_ (system target) exp0 exp ...)
|
||||||
|
(system-binding (lambda (system target)
|
||||||
|
exp0 exp ...)))
|
||||||
|
((_ system exp0 exp ...)
|
||||||
|
(system-binding (lambda (system target)
|
||||||
|
exp0 exp ...)))))
|
||||||
|
|
||||||
|
(define-gexp-compiler system-binding-compiler <system-binding>
|
||||||
|
compiler => (lambda (binding system target)
|
||||||
|
(match binding
|
||||||
|
(($ <system-binding> proc)
|
||||||
|
(with-monad %store-monad
|
||||||
|
;; PROC is expected to return a lowerable object.
|
||||||
|
;; 'lower-object' takes care of residualizing it to a
|
||||||
|
;; derivation or similar.
|
||||||
|
(return (proc system target))))))
|
||||||
|
|
||||||
|
;; Delegate to the expander of the object returned by PROC.
|
||||||
|
expander => #f)
|
||||||
|
|
||||||
|
|
||||||
;;;
|
;;;
|
||||||
;;; File declarations.
|
;;; File declarations.
|
||||||
|
@ -706,6 +755,15 @@ (define (gexp-extensions gexp)
|
||||||
list."
|
list."
|
||||||
(gexp-attribute gexp gexp-self-extensions))
|
(gexp-attribute gexp gexp-self-extensions))
|
||||||
|
|
||||||
|
(define (self-quoting? x)
|
||||||
|
(letrec-syntax ((one-of (syntax-rules ()
|
||||||
|
((_) #f)
|
||||||
|
((_ pred rest ...)
|
||||||
|
(or (pred x)
|
||||||
|
(one-of rest ...))))))
|
||||||
|
(one-of symbol? string? keyword? pair? null? array?
|
||||||
|
number? boolean? char?)))
|
||||||
|
|
||||||
(define* (lower-inputs inputs
|
(define* (lower-inputs inputs
|
||||||
#:key system target)
|
#:key system target)
|
||||||
"Turn any object from INPUTS into a derivation input for SYSTEM or a store
|
"Turn any object from INPUTS into a derivation input for SYSTEM or a store
|
||||||
|
@ -714,23 +772,32 @@ (define* (lower-inputs inputs
|
||||||
(define (store-item? obj)
|
(define (store-item? obj)
|
||||||
(and (string? obj) (store-path? obj)))
|
(and (string? obj) (store-path? obj)))
|
||||||
|
|
||||||
|
(define filterm
|
||||||
|
(lift1 (cut filter ->bool <>) %store-monad))
|
||||||
|
|
||||||
(with-monad %store-monad
|
(with-monad %store-monad
|
||||||
(mapm/accumulate-builds
|
(>>= (mapm/accumulate-builds
|
||||||
(match-lambda
|
(match-lambda
|
||||||
(((? struct? thing) sub-drv ...)
|
(((? struct? thing) sub-drv ...)
|
||||||
(mlet %store-monad ((obj (lower-object
|
(mlet %store-monad ((obj (lower-object
|
||||||
thing system #:target target)))
|
thing system #:target target)))
|
||||||
(return (match obj
|
(return (match obj
|
||||||
((? derivation? drv)
|
((? derivation? drv)
|
||||||
(let ((outputs (if (null? sub-drv)
|
(let ((outputs (if (null? sub-drv)
|
||||||
'("out")
|
'("out")
|
||||||
sub-drv)))
|
sub-drv)))
|
||||||
(derivation-input drv outputs)))
|
(derivation-input drv outputs)))
|
||||||
((? store-item? item)
|
((? store-item? item)
|
||||||
item)))))
|
item)
|
||||||
(((? store-item? item))
|
((? self-quoting?)
|
||||||
(return item)))
|
;; Some inputs such as <system-binding> can lower to
|
||||||
inputs)))
|
;; a self-quoting object that FILTERM will filter
|
||||||
|
;; out.
|
||||||
|
#f)))))
|
||||||
|
(((? store-item? item))
|
||||||
|
(return item)))
|
||||||
|
inputs)
|
||||||
|
filterm)))
|
||||||
|
|
||||||
(define* (lower-reference-graphs graphs #:key system target)
|
(define* (lower-reference-graphs graphs #:key system target)
|
||||||
"Given GRAPHS, a list of (FILE-NAME INPUT ...) lists for use as a
|
"Given GRAPHS, a list of (FILE-NAME INPUT ...) lists for use as a
|
||||||
|
@ -1146,15 +1213,6 @@ (define* (gexp->sexp exp #:key
|
||||||
(target (%current-target-system)))
|
(target (%current-target-system)))
|
||||||
"Return (monadically) the sexp corresponding to EXP for the given OUTPUT,
|
"Return (monadically) the sexp corresponding to EXP for the given OUTPUT,
|
||||||
and in the current monad setting (system type, etc.)"
|
and in the current monad setting (system type, etc.)"
|
||||||
(define (self-quoting? x)
|
|
||||||
(letrec-syntax ((one-of (syntax-rules ()
|
|
||||||
((_) #f)
|
|
||||||
((_ pred rest ...)
|
|
||||||
(or (pred x)
|
|
||||||
(one-of rest ...))))))
|
|
||||||
(one-of symbol? string? keyword? pair? null? array?
|
|
||||||
number? boolean? char?)))
|
|
||||||
|
|
||||||
(define* (reference->sexp ref #:optional native?)
|
(define* (reference->sexp ref #:optional native?)
|
||||||
(with-monad %store-monad
|
(with-monad %store-monad
|
||||||
(match ref
|
(match ref
|
||||||
|
|
|
@ -321,6 +321,60 @@ (define (match-input thing)
|
||||||
(string=? result
|
(string=? result
|
||||||
(string-append (derivation->output-path drv)
|
(string-append (derivation->output-path drv)
|
||||||
"/bin/touch"))))))
|
"/bin/touch"))))))
|
||||||
|
(test-equal "let-system"
|
||||||
|
(list `(begin ,(%current-system) #t) '(system-binding) '()
|
||||||
|
'low '() '())
|
||||||
|
(let* ((exp #~(begin
|
||||||
|
#$(let-system system system)
|
||||||
|
#t))
|
||||||
|
(low (run-with-store %store (lower-gexp exp))))
|
||||||
|
(list (lowered-gexp-sexp low)
|
||||||
|
(match (gexp-inputs exp)
|
||||||
|
(((($ (@@ (guix gexp) <system-binding>)) "out"))
|
||||||
|
'(system-binding))
|
||||||
|
(x x))
|
||||||
|
(gexp-native-inputs exp)
|
||||||
|
'low
|
||||||
|
(lowered-gexp-inputs low)
|
||||||
|
(lowered-gexp-sources low))))
|
||||||
|
|
||||||
|
(test-equal "let-system, target"
|
||||||
|
(list `(list ,(%current-system) #f)
|
||||||
|
`(list ,(%current-system) "aarch64-linux-gnu"))
|
||||||
|
(let ((exp #~(list #$@(let-system (system target)
|
||||||
|
(list system target)))))
|
||||||
|
(list (gexp->sexp* exp)
|
||||||
|
(gexp->sexp* exp "aarch64-linux-gnu"))))
|
||||||
|
|
||||||
|
(test-equal "let-system, ungexp-native, target"
|
||||||
|
`(here it is: ,(%current-system) #f)
|
||||||
|
(let ((exp #~(here it is: #+@(let-system (system target)
|
||||||
|
(list system target)))))
|
||||||
|
(gexp->sexp* exp "aarch64-linux-gnu")))
|
||||||
|
|
||||||
|
(test-equal "let-system, nested"
|
||||||
|
(list `(system* ,(string-append "qemu-system-" (%current-system))
|
||||||
|
"-m" "256")
|
||||||
|
'()
|
||||||
|
'(system-binding))
|
||||||
|
(let ((exp #~(system*
|
||||||
|
#+(let-system (system target)
|
||||||
|
(file-append (@@ (gnu packages virtualization)
|
||||||
|
qemu)
|
||||||
|
"/bin/qemu-system-"
|
||||||
|
system))
|
||||||
|
"-m" "256")))
|
||||||
|
(list (match (gexp->sexp* exp)
|
||||||
|
(('system* command rest ...)
|
||||||
|
`(system* ,(and (string-prefix? (%store-prefix) command)
|
||||||
|
(basename command))
|
||||||
|
,@rest))
|
||||||
|
(x x))
|
||||||
|
(gexp-inputs exp)
|
||||||
|
(match (gexp-native-inputs exp)
|
||||||
|
(((($ (@@ (guix gexp) <system-binding>)) "out"))
|
||||||
|
'(system-binding))
|
||||||
|
(x x)))))
|
||||||
|
|
||||||
(test-assert "ungexp + ungexp-native"
|
(test-assert "ungexp + ungexp-native"
|
||||||
(let* ((exp (gexp (list (ungexp-native %bootstrap-guile)
|
(let* ((exp (gexp (list (ungexp-native %bootstrap-guile)
|
||||||
|
|
Loading…
Reference in a new issue