summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--doc/guix.texi17
-rw-r--r--guix/gexp.scm33
-rw-r--r--tests/gexp.scm19
3 files changed, 66 insertions, 3 deletions
diff --git a/doc/guix.texi b/doc/guix.texi
index 39b76c7bf6..9c63230a4f 100644
--- a/doc/guix.texi
+++ b/doc/guix.texi
@@ -3345,9 +3345,10 @@ The other arguments are as for @code{derivation} (@pxref{Derivations}).
 @end deffn
 
 @cindex file-like objects
-The @code{local-file} and @code{plain-file} procedures below return
-@dfn{file-like objects}.  That is, when unquoted in a G-expression,
-these objects lead to a file in the store.  Consider this G-expression:
+The @code{local-file}, @code{plain-file}, and @code{computed-file}
+procedures below return @dfn{file-like objects}.  That is, when unquoted
+in a G-expression, these objects lead to a file in the store.  Consider
+this G-expression:
 
 @example
 #~(system* (string-append #$glibc "/sbin/nscd") "-f"
@@ -3383,6 +3384,16 @@ Return an object representing a text file called @var{name} with the given
 This is the declarative counterpart of @code{text-file}.
 @end deffn
 
+@deffn {Scheme Procedure} computed-file @var{name} @var{gexp} @
+          [#:modules '()] [#:options '(#:local-build? #t)]
+Return an object representing the store item @var{name}, a file or
+directory computed by @var{gexp}.  @var{modules} specifies the set of
+modules visible in the execution context of @var{gexp}.  @var{options}
+is a list of additional arguments to pass to @code{gexp->derivation}.
+
+This is the declarative counterpart of @code{gexp->derivation}.
+@end deffn
+
 @deffn {Monadic Procedure} gexp->script @var{name} @var{exp}
 Return an executable script @var{name} that runs @var{exp} using
 @var{guile} with @var{modules} in its search path.
diff --git a/guix/gexp.scm b/guix/gexp.scm
index de49fef088..ebb147d7db 100644
--- a/guix/gexp.scm
+++ b/guix/gexp.scm
@@ -43,6 +43,13 @@
             plain-file-name
             plain-file-content
 
+            computed-file
+            computed-file?
+            computed-file-name
+            computed-file-gexp
+            computed-file-modules
+            computed-file-options
+
             gexp->derivation
             gexp->file
             gexp->script
@@ -214,6 +221,32 @@ This is the declarative counterpart of 'text-file'."
     (($ <plain-file> name content references)
      (text-file name content references))))
 
+(define-record-type <computed-file>
+  (%computed-file name gexp modules options)
+  computed-file?
+  (name       computed-file-name)                 ;string
+  (gexp       computed-file-gexp)                 ;gexp
+  (modules    computed-file-modules)              ;list of module names
+  (options    computed-file-options))             ;list of arguments
+
+(define* (computed-file name gexp
+                        #:key (modules '()) (options '(#:local-build? #t)))
+  "Return an object representing the store item NAME, a file or directory
+computed by GEXP.  MODULES specifies the set of modules visible in the
+execution context of GEXP.  OPTIONS is a list of additional arguments to pass
+to 'gexp->derivation'.
+
+This is the declarative counterpart of 'gexp->derivation'."
+  (%computed-file name gexp modules options))
+
+(define-gexp-compiler (computed-file-compiler (file computed-file?)
+                                              system target)
+  ;; Compile FILE by returning a derivation whose build expression is its
+  ;; gexp.
+  (match file
+    (($ <computed-file> name gexp modules options)
+     (apply gexp->derivation name gexp #:modules modules options))))
+
 
 ;;;
 ;;; Inputs & outputs.
diff --git a/tests/gexp.scm b/tests/gexp.scm
index 492f3d6d89..ccbbbae7da 100644
--- a/tests/gexp.scm
+++ b/tests/gexp.scm
@@ -661,6 +661,25 @@
     (return (and (derivation? drv1) (derivation? drv2)
                  (store-path? item)))))
 
+(test-assertm "lower-object, computed-file"
+  (let* ((text     (plain-file "foo" "Hello!"))
+         (exp      #~(begin
+                       (mkdir #$output)
+                       (symlink #$%bootstrap-guile
+                                (string-append #$output "/guile"))
+                       (symlink #$text (string-append #$output "/text"))))
+         (computed (computed-file "computed" exp)))
+    (mlet* %store-monad ((text      (lower-object text))
+                         (guile-drv (lower-object %bootstrap-guile))
+                         (comp-drv  (lower-object computed))
+                         (comp ->   (derivation->output-path comp-drv)))
+      (mbegin %store-monad
+        (built-derivations (list comp-drv))
+        (return (and (string=? (readlink (string-append comp "/guile"))
+                               (derivation->output-path guile-drv))
+                     (string=? (readlink (string-append comp "/text"))
+                               text)))))))
+
 (test-assert "printer"
   (string-match "^#<gexp \\(string-append .*#<package coreutils.*\
  \"/bin/uname\"\\) [[:xdigit:]]+>$"