gexp: Add 'lower-gexp' and express 'gexp->derivation' in terms of it.
* guix/gexp.scm (gexp-input-thing, gexp-input-output) (gexp-input-native?): Export. (lower-inputs): Return <gexp-input> records instead of tuples. (lower-reference-graphs): Adjust accordingly. (<lowered-gexp>): New record type. (lower-gexp, gexp-input->tuple): New procedure. (gexp->derivation)[%modules]: Remove. [requested-graft?]: New variable. [add-modules]: New procedure. Rewrite in terms of 'lower-gexp'. (gexp-inputs): Add TODO comment. * tests/gexp.scm ("lower-gexp"): New test.
This commit is contained in:
parent
fc3f14927f
commit
2ca41030d5
240
guix/gexp.scm
240
guix/gexp.scm
|
@ -39,6 +39,9 @@
|
||||||
|
|
||||||
gexp-input
|
gexp-input
|
||||||
gexp-input?
|
gexp-input?
|
||||||
|
gexp-input-thing
|
||||||
|
gexp-input-output
|
||||||
|
gexp-input-native?
|
||||||
|
|
||||||
local-file
|
local-file
|
||||||
local-file?
|
local-file?
|
||||||
|
@ -78,6 +81,14 @@
|
||||||
load-path-expression
|
load-path-expression
|
||||||
gexp-modules
|
gexp-modules
|
||||||
|
|
||||||
|
lower-gexp
|
||||||
|
lowered-gexp?
|
||||||
|
lowered-gexp-sexp
|
||||||
|
lowered-gexp-inputs
|
||||||
|
lowered-gexp-guile
|
||||||
|
lowered-gexp-load-path
|
||||||
|
lowered-gexp-load-compiled-path
|
||||||
|
|
||||||
gexp->derivation
|
gexp->derivation
|
||||||
gexp->file
|
gexp->file
|
||||||
gexp->script
|
gexp->script
|
||||||
|
@ -566,15 +577,20 @@ list."
|
||||||
"Turn any package from INPUTS into a derivation for SYSTEM; return the
|
"Turn any package from INPUTS into a derivation for SYSTEM; return the
|
||||||
corresponding input list as a monadic value. When TARGET is true, use it as
|
corresponding input list as a monadic value. When TARGET is true, use it as
|
||||||
the cross-compilation target triplet."
|
the cross-compilation target triplet."
|
||||||
|
(define (store-item? obj)
|
||||||
|
(and (string? obj) (store-path? obj)))
|
||||||
|
|
||||||
(with-monad %store-monad
|
(with-monad %store-monad
|
||||||
(mapm %store-monad
|
(mapm %store-monad
|
||||||
(match-lambda
|
(match-lambda
|
||||||
(((? struct? thing) sub-drv ...)
|
(((? struct? thing) sub-drv ...)
|
||||||
(mlet %store-monad ((drv (lower-object
|
(mlet %store-monad ((drv (lower-object
|
||||||
thing system #:target target)))
|
thing system #:target target)))
|
||||||
(return `(,drv ,@sub-drv))))
|
(return (apply gexp-input drv sub-drv))))
|
||||||
|
(((? store-item? item))
|
||||||
|
(return (gexp-input item)))
|
||||||
(input
|
(input
|
||||||
(return input)))
|
(return (gexp-input input))))
|
||||||
inputs)))
|
inputs)))
|
||||||
|
|
||||||
(define* (lower-reference-graphs graphs #:key system target)
|
(define* (lower-reference-graphs graphs #:key system target)
|
||||||
|
@ -586,7 +602,9 @@ corresponding derivation."
|
||||||
(mlet %store-monad ((inputs (lower-inputs inputs
|
(mlet %store-monad ((inputs (lower-inputs inputs
|
||||||
#:system system
|
#:system system
|
||||||
#:target target)))
|
#:target target)))
|
||||||
(return (map cons file-names inputs))))))
|
(return (map (lambda (file input)
|
||||||
|
(cons file (gexp-input->tuple input)))
|
||||||
|
file-names inputs))))))
|
||||||
|
|
||||||
(define* (lower-references lst #:key system target)
|
(define* (lower-references lst #:key system target)
|
||||||
"Based on LST, a list of output names and packages, return a list of output
|
"Based on LST, a list of output names and packages, return a list of output
|
||||||
|
@ -618,6 +636,130 @@ names and file names suitable for the #:allowed-references argument to
|
||||||
(lambda (system)
|
(lambda (system)
|
||||||
((force proc) system))))
|
((force proc) system))))
|
||||||
|
|
||||||
|
;; Representation of a gexp instantiated for a given target and system.
|
||||||
|
(define-record-type <lowered-gexp>
|
||||||
|
(lowered-gexp sexp inputs guile load-path load-compiled-path)
|
||||||
|
lowered-gexp?
|
||||||
|
(sexp lowered-gexp-sexp) ;sexp
|
||||||
|
(inputs lowered-gexp-inputs) ;list of <gexp-input>
|
||||||
|
(guile lowered-gexp-guile) ;<derivation> | #f
|
||||||
|
(load-path lowered-gexp-load-path) ;list of store items
|
||||||
|
(load-compiled-path lowered-gexp-load-compiled-path)) ;list of store items
|
||||||
|
|
||||||
|
(define* (lower-gexp exp
|
||||||
|
#:key
|
||||||
|
(module-path %load-path)
|
||||||
|
(system (%current-system))
|
||||||
|
(target 'current)
|
||||||
|
(graft? (%graft?))
|
||||||
|
(guile-for-build (%guile-for-build))
|
||||||
|
(effective-version "2.2")
|
||||||
|
|
||||||
|
deprecation-warnings
|
||||||
|
(pre-load-modules? #t)) ;transitional
|
||||||
|
"*Note: This API is subject to change; use at your own risk!*
|
||||||
|
|
||||||
|
Lower EXP, a gexp, instantiating it for SYSTEM and TARGET. Return a
|
||||||
|
<lowered-gexp> ready to be used.
|
||||||
|
|
||||||
|
Lowered gexps are an intermediate representation that's useful for
|
||||||
|
applications that deal with gexps outside in a way that is disconnected from
|
||||||
|
derivations--e.g., code evaluated for its side effects."
|
||||||
|
(define %modules
|
||||||
|
(delete-duplicates (gexp-modules exp)))
|
||||||
|
|
||||||
|
(define (search-path modules extensions suffix)
|
||||||
|
(append (match modules
|
||||||
|
((? derivation? drv)
|
||||||
|
(list (derivation->output-path drv)))
|
||||||
|
(#f
|
||||||
|
'())
|
||||||
|
((? store-path? item)
|
||||||
|
(list item)))
|
||||||
|
(map (lambda (extension)
|
||||||
|
(string-append (match extension
|
||||||
|
((? derivation? drv)
|
||||||
|
(derivation->output-path drv))
|
||||||
|
((? store-path? item)
|
||||||
|
item))
|
||||||
|
suffix))
|
||||||
|
extensions)))
|
||||||
|
|
||||||
|
(mlet* %store-monad ( ;; The following binding forces '%current-system' and
|
||||||
|
;; '%current-target-system' to be looked up at >>=
|
||||||
|
;; time.
|
||||||
|
(graft? (set-grafting graft?))
|
||||||
|
|
||||||
|
(system -> (or system (%current-system)))
|
||||||
|
(target -> (if (eq? target 'current)
|
||||||
|
(%current-target-system)
|
||||||
|
target))
|
||||||
|
(guile (if guile-for-build
|
||||||
|
(return guile-for-build)
|
||||||
|
(default-guile-derivation system)))
|
||||||
|
(normals (lower-inputs (gexp-inputs exp)
|
||||||
|
#:system system
|
||||||
|
#:target target))
|
||||||
|
(natives (lower-inputs (gexp-native-inputs exp)
|
||||||
|
#:system system
|
||||||
|
#:target #f))
|
||||||
|
(inputs -> (append normals natives))
|
||||||
|
(sexp (gexp->sexp exp
|
||||||
|
#:system system
|
||||||
|
#:target target))
|
||||||
|
(extensions -> (gexp-extensions exp))
|
||||||
|
(exts (mapm %store-monad
|
||||||
|
(lambda (obj)
|
||||||
|
(lower-object obj system))
|
||||||
|
extensions))
|
||||||
|
(modules (if (pair? %modules)
|
||||||
|
(imported-modules %modules
|
||||||
|
#:system system
|
||||||
|
#:module-path module-path)
|
||||||
|
(return #f)))
|
||||||
|
(compiled (if (pair? %modules)
|
||||||
|
(compiled-modules %modules
|
||||||
|
#:system system
|
||||||
|
#:module-path module-path
|
||||||
|
#:extensions extensions
|
||||||
|
#:guile guile
|
||||||
|
#:pre-load-modules?
|
||||||
|
pre-load-modules?
|
||||||
|
#:deprecation-warnings
|
||||||
|
deprecation-warnings)
|
||||||
|
(return #f))))
|
||||||
|
(define load-path
|
||||||
|
(search-path modules exts
|
||||||
|
(string-append "/share/guile/site/" effective-version)))
|
||||||
|
|
||||||
|
(define load-compiled-path
|
||||||
|
(search-path compiled exts
|
||||||
|
(string-append "/lib/guile/" effective-version
|
||||||
|
"/site-ccache")))
|
||||||
|
|
||||||
|
(mbegin %store-monad
|
||||||
|
(set-grafting graft?) ;restore the initial setting
|
||||||
|
(return (lowered-gexp sexp
|
||||||
|
`(,@(if modules
|
||||||
|
(list (gexp-input modules))
|
||||||
|
'())
|
||||||
|
,@(if compiled
|
||||||
|
(list (gexp-input compiled))
|
||||||
|
'())
|
||||||
|
,@(map gexp-input exts)
|
||||||
|
,@inputs)
|
||||||
|
guile
|
||||||
|
load-path
|
||||||
|
load-compiled-path)))))
|
||||||
|
|
||||||
|
(define (gexp-input->tuple input)
|
||||||
|
"Given INPUT, a <gexp-input> record, return the corresponding input tuple
|
||||||
|
suitable for the 'derivation' procedure."
|
||||||
|
(match (gexp-input-output input)
|
||||||
|
("out" `(,(gexp-input-thing input)))
|
||||||
|
(output `(,(gexp-input-thing input)
|
||||||
|
,(gexp-input-output input)))))
|
||||||
|
|
||||||
(define* (gexp->derivation name exp
|
(define* (gexp->derivation name exp
|
||||||
#:key
|
#:key
|
||||||
system (target 'current)
|
system (target 'current)
|
||||||
|
@ -682,10 +824,8 @@ DEPRECATION-WARNINGS determines whether to show deprecation warnings while
|
||||||
compiling modules. It can be #f, #t, or 'detailed.
|
compiling modules. It can be #f, #t, or 'detailed.
|
||||||
|
|
||||||
The other arguments are as for 'derivation'."
|
The other arguments are as for 'derivation'."
|
||||||
(define %modules
|
|
||||||
(delete-duplicates
|
|
||||||
(append modules (gexp-modules exp))))
|
|
||||||
(define outputs (gexp-outputs exp))
|
(define outputs (gexp-outputs exp))
|
||||||
|
(define requested-graft? graft?)
|
||||||
|
|
||||||
(define (graphs-file-names graphs)
|
(define (graphs-file-names graphs)
|
||||||
;; Return a list of (FILE-NAME . STORE-PATH) pairs made from GRAPHS.
|
;; Return a list of (FILE-NAME . STORE-PATH) pairs made from GRAPHS.
|
||||||
|
@ -699,11 +839,13 @@ The other arguments are as for 'derivation'."
|
||||||
(cons file-name thing)))
|
(cons file-name thing)))
|
||||||
graphs))
|
graphs))
|
||||||
|
|
||||||
(define (extension-flags extension)
|
(define (add-modules exp modules)
|
||||||
`("-L" ,(string-append (derivation->output-path extension)
|
(if (null? modules)
|
||||||
"/share/guile/site/" effective-version)
|
exp
|
||||||
"-C" ,(string-append (derivation->output-path extension)
|
(make-gexp (gexp-references exp)
|
||||||
"/lib/guile/" effective-version "/site-ccache")))
|
(append modules (gexp-self-modules exp))
|
||||||
|
(gexp-self-extensions exp)
|
||||||
|
(gexp-proc exp))))
|
||||||
|
|
||||||
(mlet* %store-monad ( ;; The following binding forces '%current-system' and
|
(mlet* %store-monad ( ;; The following binding forces '%current-system' and
|
||||||
;; '%current-target-system' to be looked up at >>=
|
;; '%current-target-system' to be looked up at >>=
|
||||||
|
@ -714,40 +856,21 @@ The other arguments are as for 'derivation'."
|
||||||
(target -> (if (eq? target 'current)
|
(target -> (if (eq? target 'current)
|
||||||
(%current-target-system)
|
(%current-target-system)
|
||||||
target))
|
target))
|
||||||
(normals (lower-inputs (gexp-inputs exp)
|
(exp -> (add-modules exp modules))
|
||||||
#:system system
|
(lowered (lower-gexp exp
|
||||||
#:target target))
|
#:module-path module-path
|
||||||
(natives (lower-inputs (gexp-native-inputs exp)
|
#:system system
|
||||||
#:system system
|
#:target target
|
||||||
#:target #f))
|
#:graft? requested-graft?
|
||||||
(inputs -> (append normals natives))
|
#:guile-for-build
|
||||||
(sexp (gexp->sexp exp
|
guile-for-build
|
||||||
#:system system
|
#:effective-version
|
||||||
#:target target))
|
effective-version
|
||||||
(builder (text-file script-name
|
#:deprecation-warnings
|
||||||
(object->string sexp)))
|
deprecation-warnings
|
||||||
(extensions -> (gexp-extensions exp))
|
#:pre-load-modules?
|
||||||
(exts (mapm %store-monad
|
pre-load-modules?))
|
||||||
(lambda (obj)
|
|
||||||
(lower-object obj system))
|
|
||||||
extensions))
|
|
||||||
(modules (if (pair? %modules)
|
|
||||||
(imported-modules %modules
|
|
||||||
#:system system
|
|
||||||
#:module-path module-path
|
|
||||||
#:guile guile-for-build)
|
|
||||||
(return #f)))
|
|
||||||
(compiled (if (pair? %modules)
|
|
||||||
(compiled-modules %modules
|
|
||||||
#:system system
|
|
||||||
#:module-path module-path
|
|
||||||
#:extensions extensions
|
|
||||||
#:guile guile-for-build
|
|
||||||
#:pre-load-modules?
|
|
||||||
pre-load-modules?
|
|
||||||
#:deprecation-warnings
|
|
||||||
deprecation-warnings)
|
|
||||||
(return #f)))
|
|
||||||
(graphs (if references-graphs
|
(graphs (if references-graphs
|
||||||
(lower-reference-graphs references-graphs
|
(lower-reference-graphs references-graphs
|
||||||
#:system system
|
#:system system
|
||||||
|
@ -763,32 +886,30 @@ The other arguments are as for 'derivation'."
|
||||||
#:system system
|
#:system system
|
||||||
#:target target)
|
#:target target)
|
||||||
(return #f)))
|
(return #f)))
|
||||||
(guile (if guile-for-build
|
(guile -> (lowered-gexp-guile lowered))
|
||||||
(return guile-for-build)
|
(builder (text-file script-name
|
||||||
(default-guile-derivation system))))
|
(object->string
|
||||||
|
(lowered-gexp-sexp lowered)))))
|
||||||
(mbegin %store-monad
|
(mbegin %store-monad
|
||||||
(set-grafting graft?) ;restore the initial setting
|
(set-grafting graft?) ;restore the initial setting
|
||||||
(raw-derivation name
|
(raw-derivation name
|
||||||
(string-append (derivation->output-path guile)
|
(string-append (derivation->output-path guile)
|
||||||
"/bin/guile")
|
"/bin/guile")
|
||||||
`("--no-auto-compile"
|
`("--no-auto-compile"
|
||||||
,@(if (pair? %modules)
|
,@(append-map (lambda (directory)
|
||||||
`("-L" ,(if (derivation? modules)
|
`("-L" ,directory))
|
||||||
(derivation->output-path modules)
|
(lowered-gexp-load-path lowered))
|
||||||
modules)
|
,@(append-map (lambda (directory)
|
||||||
"-C" ,(derivation->output-path compiled))
|
`("-C" ,directory))
|
||||||
'())
|
(lowered-gexp-load-compiled-path lowered))
|
||||||
,@(append-map extension-flags exts)
|
|
||||||
,builder)
|
,builder)
|
||||||
#:outputs outputs
|
#:outputs outputs
|
||||||
#:env-vars env-vars
|
#:env-vars env-vars
|
||||||
#:system system
|
#:system system
|
||||||
#:inputs `((,guile)
|
#:inputs `((,guile)
|
||||||
(,builder)
|
(,builder)
|
||||||
,@(if modules
|
,@(map gexp-input->tuple
|
||||||
`((,modules) (,compiled) ,@inputs)
|
(lowered-gexp-inputs lowered))
|
||||||
inputs)
|
|
||||||
,@(map list exts)
|
|
||||||
,@(match graphs
|
,@(match graphs
|
||||||
(((_ . inputs) ...) inputs)
|
(((_ . inputs) ...) inputs)
|
||||||
(_ '())))
|
(_ '())))
|
||||||
|
@ -804,6 +925,7 @@ The other arguments are as for 'derivation'."
|
||||||
(define* (gexp-inputs exp #:key native?)
|
(define* (gexp-inputs exp #:key native?)
|
||||||
"Return the input list for EXP. When NATIVE? is true, return only native
|
"Return the input list for EXP. When NATIVE? is true, return only native
|
||||||
references; otherwise, return only non-native references."
|
references; otherwise, return only non-native references."
|
||||||
|
;; TODO: Return <gexp-input> records instead of tuples.
|
||||||
(define (add-reference-inputs ref result)
|
(define (add-reference-inputs ref result)
|
||||||
(match ref
|
(match ref
|
||||||
(($ <gexp-input> (? gexp? exp) _ #t)
|
(($ <gexp-input> (? gexp? exp) _ #t)
|
||||||
|
|
|
@ -832,6 +832,43 @@
|
||||||
(built-derivations (list drv))
|
(built-derivations (list drv))
|
||||||
(return (equal? '(42 84) (call-with-input-file out read))))))
|
(return (equal? '(42 84) (call-with-input-file out read))))))
|
||||||
|
|
||||||
|
(test-assertm "lower-gexp"
|
||||||
|
(mlet* %store-monad
|
||||||
|
((extension -> %extension-package)
|
||||||
|
(extension-drv (package->derivation %extension-package))
|
||||||
|
(coreutils-drv (package->derivation coreutils))
|
||||||
|
(exp -> (with-extensions (list extension)
|
||||||
|
(with-imported-modules `((guix build utils))
|
||||||
|
#~(begin
|
||||||
|
(use-modules (guix build utils)
|
||||||
|
(hg2g))
|
||||||
|
#$coreutils:debug
|
||||||
|
mkdir-p
|
||||||
|
the-answer))))
|
||||||
|
(lexp (lower-gexp exp
|
||||||
|
#:effective-version "2.0")))
|
||||||
|
(define (matching-input drv output)
|
||||||
|
(lambda (input)
|
||||||
|
(and (eq? (gexp-input-thing input) drv)
|
||||||
|
(string=? (gexp-input-output input) output))))
|
||||||
|
|
||||||
|
(mbegin %store-monad
|
||||||
|
(return (and (find (matching-input extension-drv "out")
|
||||||
|
(lowered-gexp-inputs (pk 'lexp lexp)))
|
||||||
|
(find (matching-input coreutils-drv "debug")
|
||||||
|
(lowered-gexp-inputs lexp))
|
||||||
|
(member (string-append
|
||||||
|
(derivation->output-path extension-drv)
|
||||||
|
"/share/guile/site/2.0")
|
||||||
|
(lowered-gexp-load-path lexp))
|
||||||
|
(= 2 (length (lowered-gexp-load-path lexp)))
|
||||||
|
(member (string-append
|
||||||
|
(derivation->output-path extension-drv)
|
||||||
|
"/lib/guile/2.0/site-ccache")
|
||||||
|
(lowered-gexp-load-compiled-path lexp))
|
||||||
|
(= 2 (length (lowered-gexp-load-compiled-path lexp)))
|
||||||
|
(eq? (lowered-gexp-guile lexp) (%guile-for-build)))))))
|
||||||
|
|
||||||
(test-assertm "gexp->derivation #:references-graphs"
|
(test-assertm "gexp->derivation #:references-graphs"
|
||||||
(mlet* %store-monad
|
(mlet* %store-monad
|
||||||
((one (text-file "one" (random-text)))
|
((one (text-file "one" (random-text)))
|
||||||
|
|
Loading…
Reference in New Issue