2014-04-28 23:00:57 +02:00
|
|
|
|
;;; GNU Guix --- Functional package management for GNU
|
2020-01-03 12:39:48 +01:00
|
|
|
|
;;; Copyright © 2014, 2015, 2016, 2017, 2018, 2019, 2020 Ludovic Courtès <ludo@gnu.org>
|
services: messaging: Prosody config supports file-like objects.
* doc/guix.texi (Messaging Services): Update accordingly.
* gnu/services/configuration.scm (serialize-configuration,
serialize-maybe-stem, serialize-package): Return strings or string-valued
gexps (these procedures were only used for their side-effects).
* gnu/services/messaging.scm (serialize-field, serialize-field-list,
enclose-quotes, serialize-raw-content, serialize-ssl-configuration,
serialize-virtualhost-configuration-list,
serialize-int-component-configuration-list,
serialize-ext-component-configuration-list,
serialize-virtualhost-configuration, serialize-int-component-configuration,
serialize-ext-component-configuration, serialize-prosody-configuration):
Return strings or string-valued gexps and stop printing.
(prosody-activation): Use SERIALIZE-PROSODY-CONFIGURATION's return value with
MIXED-TEXT-FILE instead of using its output with PLAIN-FILE.
(serialize-non-negative-integer, serialize-non-negative-integer-list): Convert
numbers to strings.
(file-object?, serialize-file-object, file-object-list?,
serialize-file-object-list): New procedures.
(ssl-configuration)[capath, cafile], (prosody-configuration)[plugin-paths,
groups-file]: Replace FILE-NAME with FILE-OBJECT.
* guix/gexp.scm (file-like?): New exported procedure.
2018-02-26 01:12:24 +01:00
|
|
|
|
;;; Copyright © 2018 Clément Lassieur <clement@lassieur.org>
|
2018-07-10 19:06:32 +02:00
|
|
|
|
;;; Copyright © 2018 Jan Nieuwenhuizen <janneke@gnu.org>
|
2020-03-06 10:06:54 +01:00
|
|
|
|
;;; Copyright © 2019, 2020 Mathieu Othacehe <m.othacehe@gmail.com>
|
2014-04-28 23:00:57 +02:00
|
|
|
|
;;;
|
|
|
|
|
;;; This file is part of GNU Guix.
|
|
|
|
|
;;;
|
|
|
|
|
;;; GNU Guix is free software; you can redistribute it and/or modify it
|
|
|
|
|
;;; 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.
|
|
|
|
|
;;;
|
|
|
|
|
;;; GNU Guix is distributed in the hope that it will be useful, but
|
|
|
|
|
;;; 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
|
|
|
|
|
;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
|
|
|
|
|
(define-module (guix gexp)
|
monads: Move '%store-monad' and related procedures where they belong.
This turns (guix monads) into a generic module for monads, and moves the
store monad and related monadic procedures in their corresponding
module.
* guix/monads.scm (store-return, store-bind, %store-monad, store-lift,
text-file, interned-file, package-file, package->derivation,
package->cross-derivation, origin->derivation, imported-modules,
compiled, modules, built-derivations, run-with-store): Move to...
* guix/store.scm (store-return, store-bind, %store-monad, store-lift,
text-file, interned-file): ... here.
(%guile-for-build): New variable.
(run-with-store): Moved from monads.scm. Remove default value for
#:guile-for-build.
* guix/packages.scm (default-guile): Export.
(set-guile-for-build): New procedure.
(package-file, package->derivation, package->cross-derivation,
origin->derivation): Moved from monads.scm.
* guix/derivations.scm (%guile-for-build): Remove.
(imported-modules): Rename to...
(%imported-modules): ... this.
(compiled-modules): Rename to...
(%compiled-modules): ... this.
(built-derivations, imported-modules, compiled-modules): New
procedures.
* gnu/services/avahi.scm, gnu/services/base.scm, gnu/services/dbus.scm,
gnu/services/dmd.scm, gnu/services/networking.scm,
gnu/services/ssh.scm, gnu/services/xorg.scm, gnu/system/install.scm,
gnu/system/linux-initrd.scm, gnu/system/shadow.scm, guix/download.scm,
guix/gexp.scm, guix/git-download.scm, guix/profiles.scm,
guix/svn-download.scm, tests/monads.scm: Adjust imports accordingly.
* guix/monad-repl.scm (default-guile-derivation): New procedure.
(store-monad-language, run-in-store): Use it.
* build-aux/hydra/gnu-system.scm (qemu-jobs): Add explicit
'set-guile-for-build' call.
* guix/scripts/archive.scm (derivation-from-expression): Likewise.
* guix/scripts/build.scm (options/resolve-packages): Likewise.
* guix/scripts/environment.scm (guix-environment): Likewise.
* guix/scripts/system.scm (guix-system): Likewise.
* doc/guix.texi (The Store Monad): Adjust module names accordingly.
2015-01-14 13:34:52 +01:00
|
|
|
|
#:use-module (guix store)
|
2014-04-28 23:00:57 +02:00
|
|
|
|
#:use-module (guix monads)
|
monads: Move '%store-monad' and related procedures where they belong.
This turns (guix monads) into a generic module for monads, and moves the
store monad and related monadic procedures in their corresponding
module.
* guix/monads.scm (store-return, store-bind, %store-monad, store-lift,
text-file, interned-file, package-file, package->derivation,
package->cross-derivation, origin->derivation, imported-modules,
compiled, modules, built-derivations, run-with-store): Move to...
* guix/store.scm (store-return, store-bind, %store-monad, store-lift,
text-file, interned-file): ... here.
(%guile-for-build): New variable.
(run-with-store): Moved from monads.scm. Remove default value for
#:guile-for-build.
* guix/packages.scm (default-guile): Export.
(set-guile-for-build): New procedure.
(package-file, package->derivation, package->cross-derivation,
origin->derivation): Moved from monads.scm.
* guix/derivations.scm (%guile-for-build): Remove.
(imported-modules): Rename to...
(%imported-modules): ... this.
(compiled-modules): Rename to...
(%compiled-modules): ... this.
(built-derivations, imported-modules, compiled-modules): New
procedures.
* gnu/services/avahi.scm, gnu/services/base.scm, gnu/services/dbus.scm,
gnu/services/dmd.scm, gnu/services/networking.scm,
gnu/services/ssh.scm, gnu/services/xorg.scm, gnu/system/install.scm,
gnu/system/linux-initrd.scm, gnu/system/shadow.scm, guix/download.scm,
guix/gexp.scm, guix/git-download.scm, guix/profiles.scm,
guix/svn-download.scm, tests/monads.scm: Adjust imports accordingly.
* guix/monad-repl.scm (default-guile-derivation): New procedure.
(store-monad-language, run-in-store): Use it.
* build-aux/hydra/gnu-system.scm (qemu-jobs): Add explicit
'set-guile-for-build' call.
* guix/scripts/archive.scm (derivation-from-expression): Likewise.
* guix/scripts/build.scm (options/resolve-packages): Likewise.
* guix/scripts/environment.scm (guix-environment): Likewise.
* guix/scripts/system.scm (guix-system): Likewise.
* doc/guix.texi (The Store Monad): Adjust module names accordingly.
2015-01-14 13:34:52 +01:00
|
|
|
|
#:use-module (guix derivations)
|
2016-02-22 16:29:44 +01:00
|
|
|
|
#:use-module (guix grafts)
|
2015-02-13 17:23:17 +01:00
|
|
|
|
#:use-module (guix utils)
|
2018-07-10 19:06:32 +02:00
|
|
|
|
#:use-module (rnrs bytevectors)
|
2014-04-28 23:00:57 +02:00
|
|
|
|
#:use-module (srfi srfi-1)
|
|
|
|
|
#:use-module (srfi srfi-9)
|
2014-04-30 23:16:03 +02:00
|
|
|
|
#:use-module (srfi srfi-9 gnu)
|
2014-04-28 23:00:57 +02:00
|
|
|
|
#:use-module (srfi srfi-26)
|
2017-04-03 23:52:19 +02:00
|
|
|
|
#:use-module (srfi srfi-34)
|
|
|
|
|
#:use-module (srfi srfi-35)
|
2014-04-28 23:00:57 +02:00
|
|
|
|
#:use-module (ice-9 match)
|
|
|
|
|
#:export (gexp
|
|
|
|
|
gexp?
|
2016-07-03 22:26:19 +02:00
|
|
|
|
with-imported-modules
|
2018-05-28 18:14:37 +02:00
|
|
|
|
with-extensions
|
2017-11-14 10:16:22 +01:00
|
|
|
|
let-system
|
2015-03-15 21:45:37 +01:00
|
|
|
|
|
|
|
|
|
gexp-input
|
|
|
|
|
gexp-input?
|
2019-06-10 14:34:36 +02:00
|
|
|
|
gexp-input-thing
|
|
|
|
|
gexp-input-output
|
|
|
|
|
gexp-input-native?
|
2015-06-03 11:45:27 +02:00
|
|
|
|
|
2015-03-28 21:26:33 +01:00
|
|
|
|
local-file
|
|
|
|
|
local-file?
|
2015-06-03 11:21:15 +02:00
|
|
|
|
local-file-file
|
2015-12-14 19:52:47 +01:00
|
|
|
|
local-file-absolute-file-name
|
2015-06-03 11:21:15 +02:00
|
|
|
|
local-file-name
|
|
|
|
|
local-file-recursive?
|
2020-05-25 17:33:04 +02:00
|
|
|
|
local-file-select?
|
2015-03-15 21:45:37 +01:00
|
|
|
|
|
2015-06-03 11:45:27 +02:00
|
|
|
|
plain-file
|
|
|
|
|
plain-file?
|
|
|
|
|
plain-file-name
|
|
|
|
|
plain-file-content
|
|
|
|
|
|
2015-09-07 22:37:14 +02:00
|
|
|
|
computed-file
|
|
|
|
|
computed-file?
|
|
|
|
|
computed-file-name
|
|
|
|
|
computed-file-gexp
|
|
|
|
|
computed-file-options
|
|
|
|
|
|
2015-09-08 22:44:26 +02:00
|
|
|
|
program-file
|
|
|
|
|
program-file?
|
|
|
|
|
program-file-name
|
|
|
|
|
program-file-gexp
|
|
|
|
|
program-file-guile
|
2018-03-23 18:35:32 +01:00
|
|
|
|
program-file-module-path
|
2015-09-08 22:44:26 +02:00
|
|
|
|
|
2015-09-16 15:03:52 +02:00
|
|
|
|
scheme-file
|
|
|
|
|
scheme-file?
|
|
|
|
|
scheme-file-name
|
|
|
|
|
scheme-file-gexp
|
|
|
|
|
|
2016-09-09 22:46:36 +02:00
|
|
|
|
file-append
|
|
|
|
|
file-append?
|
|
|
|
|
file-append-base
|
|
|
|
|
file-append-suffix
|
|
|
|
|
|
2019-12-06 23:12:49 +01:00
|
|
|
|
raw-derivation-file
|
|
|
|
|
raw-derivation-file?
|
|
|
|
|
|
2020-03-06 11:25:43 +01:00
|
|
|
|
with-parameters
|
|
|
|
|
parameterized?
|
|
|
|
|
|
2017-03-09 12:37:21 +01:00
|
|
|
|
load-path-expression
|
|
|
|
|
gexp-modules
|
|
|
|
|
|
2019-06-10 14:34:36 +02:00
|
|
|
|
lower-gexp
|
|
|
|
|
lowered-gexp?
|
|
|
|
|
lowered-gexp-sexp
|
|
|
|
|
lowered-gexp-inputs
|
2019-07-09 23:05:01 +02:00
|
|
|
|
lowered-gexp-sources
|
2019-06-10 14:34:36 +02:00
|
|
|
|
lowered-gexp-guile
|
|
|
|
|
lowered-gexp-load-path
|
|
|
|
|
lowered-gexp-load-compiled-path
|
|
|
|
|
|
2014-04-28 23:00:57 +02:00
|
|
|
|
gexp->derivation
|
|
|
|
|
gexp->file
|
2015-01-12 23:26:52 +01:00
|
|
|
|
gexp->script
|
2015-02-13 17:23:17 +01:00
|
|
|
|
text-file*
|
2015-09-09 09:44:43 +02:00
|
|
|
|
mixed-text-file
|
2017-10-16 09:57:44 +02:00
|
|
|
|
file-union
|
2017-10-16 10:12:53 +02:00
|
|
|
|
directory-union
|
2015-02-13 17:23:17 +01:00
|
|
|
|
imported-files
|
|
|
|
|
imported-modules
|
2015-03-17 22:09:32 +01:00
|
|
|
|
compiled-modules
|
|
|
|
|
|
|
|
|
|
define-gexp-compiler
|
2015-06-30 23:23:06 +02:00
|
|
|
|
gexp-compiler?
|
services: messaging: Prosody config supports file-like objects.
* doc/guix.texi (Messaging Services): Update accordingly.
* gnu/services/configuration.scm (serialize-configuration,
serialize-maybe-stem, serialize-package): Return strings or string-valued
gexps (these procedures were only used for their side-effects).
* gnu/services/messaging.scm (serialize-field, serialize-field-list,
enclose-quotes, serialize-raw-content, serialize-ssl-configuration,
serialize-virtualhost-configuration-list,
serialize-int-component-configuration-list,
serialize-ext-component-configuration-list,
serialize-virtualhost-configuration, serialize-int-component-configuration,
serialize-ext-component-configuration, serialize-prosody-configuration):
Return strings or string-valued gexps and stop printing.
(prosody-activation): Use SERIALIZE-PROSODY-CONFIGURATION's return value with
MIXED-TEXT-FILE instead of using its output with PLAIN-FILE.
(serialize-non-negative-integer, serialize-non-negative-integer-list): Convert
numbers to strings.
(file-object?, serialize-file-object, file-object-list?,
serialize-file-object-list): New procedures.
(ssl-configuration)[capath, cafile], (prosody-configuration)[plugin-paths,
groups-file]: Replace FILE-NAME with FILE-OBJECT.
* guix/gexp.scm (file-like?): New exported procedure.
2018-02-26 01:12:24 +01:00
|
|
|
|
file-like?
|
2015-08-26 11:28:23 +02:00
|
|
|
|
lower-object
|
2015-06-30 23:23:06 +02:00
|
|
|
|
|
2017-04-03 23:52:19 +02:00
|
|
|
|
lower-inputs
|
|
|
|
|
|
|
|
|
|
&gexp-error
|
|
|
|
|
gexp-error?
|
|
|
|
|
&gexp-input-error
|
|
|
|
|
gexp-input-error?
|
|
|
|
|
gexp-error-invalid-input))
|
2014-04-28 23:00:57 +02:00
|
|
|
|
|
|
|
|
|
;;; Commentary:
|
|
|
|
|
;;;
|
|
|
|
|
;;; This module implements "G-expressions", or "gexps". Gexps are like
|
|
|
|
|
;;; S-expressions (sexps), with two differences:
|
|
|
|
|
;;;
|
|
|
|
|
;;; 1. References (un-quotations) to derivations or packages in a gexp are
|
gexp: Add 'ungexp-native' and 'ungexp-native-splicing'.
* guix/gexp.scm (<gexp>)[natives]: New field.
(write-gexp): Use both 'gexp-references' and
'gexp-native-references'.
(gexp->derivation): Use both 'gexp-inputs' and 'gexp-native-inputs',
and append them.
(gexp-inputs): Add 'references' parameter and honor it.
(gexp-native-inputs): New procedure.
(gexp->sexp)[reference->sexp]: Add 'native?' parameter and honor it.
Use it, and use 'gexp-native-references'.
(gexp)[collect-native-escapes]: New procedure.
[escape->ref]: Handle 'ungexp-native' and 'ungexp-native-splicing'.
[substitute-ungexp, substitute-ungexp-splicing]: New procedures.
[substitute-references]: Use them, and handle 'ungexp-native' and
'ungexp-native-splicing'.
Adjust generated 'make-gexp' call to provide both normal references
and native references.
[read-ungexp]: Support 'ungexp-native' and
'ungexp-native-splicing'.
Add reader extension for #+.
* tests/gexp.scm (gexp-native-inputs): New procedure.
(gexp->sexp*): Add 'target' parameter.
("ungexp + ungexp-native",
"input list + ungexp-native",
"input list splicing + ungexp-native-splicing",
"gexp->derivation, ungexp-native",
"gexp->derivation, ungexp + ungexp-native"): New tests.
("sugar"): Add tests for #+ and #+@.
* doc/guix.texi (G-Expressions): Document 'ungexp-native' et al.
2014-08-18 14:53:10 +02:00
|
|
|
|
;;; replaced by the corresponding output file name; in addition, the
|
|
|
|
|
;;; 'ungexp-native' unquote-like form allows code to explicitly refer to
|
|
|
|
|
;;; the native code of a given package, in case of cross-compilation;
|
2014-04-28 23:00:57 +02:00
|
|
|
|
;;;
|
|
|
|
|
;;; 2. Gexps embed information about the derivations they refer to.
|
|
|
|
|
;;;
|
|
|
|
|
;;; Gexps make it easy to write to files Scheme code that refers to store
|
|
|
|
|
;;; items, or to write Scheme code to build derivations.
|
|
|
|
|
;;;
|
|
|
|
|
;;; Code:
|
|
|
|
|
|
|
|
|
|
;; "G expressions".
|
|
|
|
|
(define-record-type <gexp>
|
2018-05-28 18:14:37 +02:00
|
|
|
|
(make-gexp references modules extensions proc)
|
2014-04-28 23:00:57 +02:00
|
|
|
|
gexp?
|
2016-07-02 23:19:40 +02:00
|
|
|
|
(references gexp-references) ;list of <gexp-input>
|
2016-07-03 22:26:19 +02:00
|
|
|
|
(modules gexp-self-modules) ;list of module names
|
2018-05-28 18:14:37 +02:00
|
|
|
|
(extensions gexp-self-extensions) ;list of lowerable things
|
2016-07-02 23:19:40 +02:00
|
|
|
|
(proc gexp-proc)) ;procedure
|
2014-04-28 23:00:57 +02:00
|
|
|
|
|
2014-04-30 23:16:03 +02:00
|
|
|
|
(define (write-gexp gexp port)
|
|
|
|
|
"Write GEXP on PORT."
|
|
|
|
|
(display "#<gexp " port)
|
2014-07-17 15:40:06 +02:00
|
|
|
|
|
|
|
|
|
;; Try to write the underlying sexp. Now, this trick doesn't work when
|
|
|
|
|
;; doing things like (ungexp-splicing (gexp ())) because GEXP's procedure
|
|
|
|
|
;; tries to use 'append' on that, which fails with wrong-type-arg.
|
|
|
|
|
(false-if-exception
|
gexp: Add 'ungexp-native' and 'ungexp-native-splicing'.
* guix/gexp.scm (<gexp>)[natives]: New field.
(write-gexp): Use both 'gexp-references' and
'gexp-native-references'.
(gexp->derivation): Use both 'gexp-inputs' and 'gexp-native-inputs',
and append them.
(gexp-inputs): Add 'references' parameter and honor it.
(gexp-native-inputs): New procedure.
(gexp->sexp)[reference->sexp]: Add 'native?' parameter and honor it.
Use it, and use 'gexp-native-references'.
(gexp)[collect-native-escapes]: New procedure.
[escape->ref]: Handle 'ungexp-native' and 'ungexp-native-splicing'.
[substitute-ungexp, substitute-ungexp-splicing]: New procedures.
[substitute-references]: Use them, and handle 'ungexp-native' and
'ungexp-native-splicing'.
Adjust generated 'make-gexp' call to provide both normal references
and native references.
[read-ungexp]: Support 'ungexp-native' and
'ungexp-native-splicing'.
Add reader extension for #+.
* tests/gexp.scm (gexp-native-inputs): New procedure.
(gexp->sexp*): Add 'target' parameter.
("ungexp + ungexp-native",
"input list + ungexp-native",
"input list splicing + ungexp-native-splicing",
"gexp->derivation, ungexp-native",
"gexp->derivation, ungexp + ungexp-native"): New tests.
("sugar"): Add tests for #+ and #+@.
* doc/guix.texi (G-Expressions): Document 'ungexp-native' et al.
2014-08-18 14:53:10 +02:00
|
|
|
|
(write (apply (gexp-proc gexp)
|
2016-07-02 23:19:40 +02:00
|
|
|
|
(gexp-references gexp))
|
gexp: Add 'ungexp-native' and 'ungexp-native-splicing'.
* guix/gexp.scm (<gexp>)[natives]: New field.
(write-gexp): Use both 'gexp-references' and
'gexp-native-references'.
(gexp->derivation): Use both 'gexp-inputs' and 'gexp-native-inputs',
and append them.
(gexp-inputs): Add 'references' parameter and honor it.
(gexp-native-inputs): New procedure.
(gexp->sexp)[reference->sexp]: Add 'native?' parameter and honor it.
Use it, and use 'gexp-native-references'.
(gexp)[collect-native-escapes]: New procedure.
[escape->ref]: Handle 'ungexp-native' and 'ungexp-native-splicing'.
[substitute-ungexp, substitute-ungexp-splicing]: New procedures.
[substitute-references]: Use them, and handle 'ungexp-native' and
'ungexp-native-splicing'.
Adjust generated 'make-gexp' call to provide both normal references
and native references.
[read-ungexp]: Support 'ungexp-native' and
'ungexp-native-splicing'.
Add reader extension for #+.
* tests/gexp.scm (gexp-native-inputs): New procedure.
(gexp->sexp*): Add 'target' parameter.
("ungexp + ungexp-native",
"input list + ungexp-native",
"input list splicing + ungexp-native-splicing",
"gexp->derivation, ungexp-native",
"gexp->derivation, ungexp + ungexp-native"): New tests.
("sugar"): Add tests for #+ and #+@.
* doc/guix.texi (G-Expressions): Document 'ungexp-native' et al.
2014-08-18 14:53:10 +02:00
|
|
|
|
port))
|
2014-04-30 23:16:03 +02:00
|
|
|
|
(format port " ~a>"
|
|
|
|
|
(number->string (object-address gexp) 16)))
|
|
|
|
|
|
|
|
|
|
(set-record-type-printer! <gexp> write-gexp)
|
|
|
|
|
|
2015-03-15 23:27:34 +01:00
|
|
|
|
|
|
|
|
|
;;;
|
|
|
|
|
;;; Methods.
|
|
|
|
|
;;;
|
|
|
|
|
|
|
|
|
|
;; Compiler for a type of objects that may be introduced in a gexp.
|
|
|
|
|
(define-record-type <gexp-compiler>
|
2016-09-10 11:57:37 +02:00
|
|
|
|
(gexp-compiler type lower expand)
|
2015-03-15 23:27:34 +01:00
|
|
|
|
gexp-compiler?
|
2016-09-10 11:57:37 +02:00
|
|
|
|
(type gexp-compiler-type) ;record type descriptor
|
2016-09-09 22:43:41 +02:00
|
|
|
|
(lower gexp-compiler-lower)
|
2016-09-10 11:57:37 +02:00
|
|
|
|
(expand gexp-compiler-expand)) ;#f | DRV -> sexp
|
2015-03-15 23:27:34 +01:00
|
|
|
|
|
2017-04-03 23:52:19 +02:00
|
|
|
|
(define-condition-type &gexp-error &error
|
|
|
|
|
gexp-error?)
|
|
|
|
|
|
|
|
|
|
(define-condition-type &gexp-input-error &gexp-error
|
|
|
|
|
gexp-input-error?
|
|
|
|
|
(input gexp-error-invalid-input))
|
|
|
|
|
|
|
|
|
|
|
2015-03-15 23:27:34 +01:00
|
|
|
|
(define %gexp-compilers
|
2016-09-10 11:57:37 +02:00
|
|
|
|
;; 'eq?' mapping of record type descriptor to <gexp-compiler>.
|
|
|
|
|
(make-hash-table 20))
|
2015-03-15 23:27:34 +01:00
|
|
|
|
|
2016-09-09 22:43:41 +02:00
|
|
|
|
(define (default-expander thing obj output)
|
|
|
|
|
"This is the default expander for \"things\" that appear in gexps. It
|
|
|
|
|
returns its output file name of OBJ's OUTPUT."
|
|
|
|
|
(match obj
|
|
|
|
|
((? derivation? drv)
|
|
|
|
|
(derivation->output-path drv output))
|
|
|
|
|
((? string? file)
|
2017-11-14 10:16:22 +01:00
|
|
|
|
file)
|
|
|
|
|
((? self-quoting? obj)
|
|
|
|
|
obj)))
|
2016-09-09 22:43:41 +02:00
|
|
|
|
|
2015-03-15 23:27:34 +01:00
|
|
|
|
(define (register-compiler! compiler)
|
|
|
|
|
"Register COMPILER as a gexp compiler."
|
2016-09-10 11:57:37 +02:00
|
|
|
|
(hashq-set! %gexp-compilers
|
|
|
|
|
(gexp-compiler-type compiler) compiler))
|
2015-03-15 23:27:34 +01:00
|
|
|
|
|
|
|
|
|
(define (lookup-compiler object)
|
2016-09-09 22:43:41 +02:00
|
|
|
|
"Search for a compiler for OBJECT. Upon success, return the three argument
|
2015-03-15 23:27:34 +01:00
|
|
|
|
procedure to lower it; otherwise return #f."
|
2016-09-10 11:57:37 +02:00
|
|
|
|
(and=> (hashq-ref %gexp-compilers (struct-vtable object))
|
|
|
|
|
gexp-compiler-lower))
|
2015-03-15 23:27:34 +01:00
|
|
|
|
|
services: messaging: Prosody config supports file-like objects.
* doc/guix.texi (Messaging Services): Update accordingly.
* gnu/services/configuration.scm (serialize-configuration,
serialize-maybe-stem, serialize-package): Return strings or string-valued
gexps (these procedures were only used for their side-effects).
* gnu/services/messaging.scm (serialize-field, serialize-field-list,
enclose-quotes, serialize-raw-content, serialize-ssl-configuration,
serialize-virtualhost-configuration-list,
serialize-int-component-configuration-list,
serialize-ext-component-configuration-list,
serialize-virtualhost-configuration, serialize-int-component-configuration,
serialize-ext-component-configuration, serialize-prosody-configuration):
Return strings or string-valued gexps and stop printing.
(prosody-activation): Use SERIALIZE-PROSODY-CONFIGURATION's return value with
MIXED-TEXT-FILE instead of using its output with PLAIN-FILE.
(serialize-non-negative-integer, serialize-non-negative-integer-list): Convert
numbers to strings.
(file-object?, serialize-file-object, file-object-list?,
serialize-file-object-list): New procedures.
(ssl-configuration)[capath, cafile], (prosody-configuration)[plugin-paths,
groups-file]: Replace FILE-NAME with FILE-OBJECT.
* guix/gexp.scm (file-like?): New exported procedure.
2018-02-26 01:12:24 +01:00
|
|
|
|
(define (file-like? object)
|
|
|
|
|
"Return #t if OBJECT leads to a file in the store once unquoted in a
|
|
|
|
|
G-expression; otherwise return #f."
|
|
|
|
|
(and (struct? object) (->bool (lookup-compiler object))))
|
|
|
|
|
|
2016-09-09 22:43:41 +02:00
|
|
|
|
(define (lookup-expander object)
|
|
|
|
|
"Search for an expander for OBJECT. Upon success, return the three argument
|
|
|
|
|
procedure to expand it; otherwise return #f."
|
2016-09-10 11:57:37 +02:00
|
|
|
|
(and=> (hashq-ref %gexp-compilers (struct-vtable object))
|
|
|
|
|
gexp-compiler-expand))
|
2016-09-09 22:43:41 +02:00
|
|
|
|
|
2015-08-26 11:28:23 +02:00
|
|
|
|
(define* (lower-object obj
|
|
|
|
|
#:optional (system (%current-system))
|
2020-03-06 10:06:54 +01:00
|
|
|
|
#:key (target 'current))
|
2015-08-26 11:28:23 +02:00
|
|
|
|
"Return as a value in %STORE-MONAD the derivation or store item
|
|
|
|
|
corresponding to OBJ for SYSTEM, cross-compiling for TARGET if TARGET is true.
|
|
|
|
|
OBJ must be an object that has an associated gexp compiler, such as a
|
|
|
|
|
<package>."
|
2017-11-14 17:10:17 +01:00
|
|
|
|
(mlet %store-monad ((target (if (eq? target 'current)
|
|
|
|
|
(current-target-system)
|
|
|
|
|
(return target)))
|
|
|
|
|
(graft? (grafting?)))
|
|
|
|
|
(let loop ((obj obj))
|
|
|
|
|
(match (lookup-compiler obj)
|
|
|
|
|
(#f
|
|
|
|
|
(raise (condition (&gexp-input-error (input obj)))))
|
|
|
|
|
(lower
|
|
|
|
|
;; Cache in STORE the result of lowering OBJ.
|
|
|
|
|
(mcached (mlet %store-monad ((lowered (lower obj system target)))
|
|
|
|
|
(if (and (struct? lowered)
|
|
|
|
|
(not (derivation? lowered)))
|
|
|
|
|
(loop lowered)
|
|
|
|
|
(return lowered)))
|
|
|
|
|
obj
|
|
|
|
|
system target graft?))))))
|
|
|
|
|
|
|
|
|
|
(define* (lower+expand-object obj
|
|
|
|
|
#:optional (system (%current-system))
|
|
|
|
|
#:key target (output "out"))
|
|
|
|
|
"Return as a value in %STORE-MONAD the output of object OBJ expands to for
|
|
|
|
|
SYSTEM and TARGET. Object such as <package>, <file-append>, or <plain-file>
|
|
|
|
|
expand to file names, but it's possible to expand to a plain data type."
|
|
|
|
|
(let loop ((obj obj)
|
|
|
|
|
(expand (and (struct? obj) (lookup-expander obj))))
|
|
|
|
|
(match (lookup-compiler obj)
|
|
|
|
|
(#f
|
|
|
|
|
(raise (condition (&gexp-input-error (input obj)))))
|
|
|
|
|
(lower
|
|
|
|
|
(mlet* %store-monad ((graft? (grafting?))
|
|
|
|
|
(lowered (mcached (lower obj system target)
|
|
|
|
|
obj
|
|
|
|
|
system target graft?)))
|
|
|
|
|
;; LOWER might return something that needs to be further
|
|
|
|
|
;; lowered.
|
|
|
|
|
(if (struct? lowered)
|
|
|
|
|
;; If we lack an expander, delegate to that of LOWERED.
|
|
|
|
|
(if (not expand)
|
|
|
|
|
(loop lowered (lookup-expander lowered))
|
|
|
|
|
(return (expand obj lowered output)))
|
2020-05-25 16:06:03 +02:00
|
|
|
|
(if (not expand) ;self-quoting
|
|
|
|
|
(return lowered)
|
|
|
|
|
(return (expand obj lowered output)))))))))
|
2015-08-26 11:28:23 +02:00
|
|
|
|
|
2016-09-09 22:43:41 +02:00
|
|
|
|
(define-syntax define-gexp-compiler
|
|
|
|
|
(syntax-rules (=> compiler expander)
|
|
|
|
|
"Define NAME as a compiler for objects matching PREDICATE encountered in
|
|
|
|
|
gexps.
|
|
|
|
|
|
2017-11-14 17:10:17 +01:00
|
|
|
|
In the simplest form of the macro, BODY must return (1) a derivation for
|
|
|
|
|
a record of the specified type, for SYSTEM and TARGET (the latter of which is
|
|
|
|
|
#f except when cross-compiling), (2) another record that can itself be
|
|
|
|
|
compiled down to a derivation, or (3) an object of a primitive data type.
|
2016-09-09 22:43:41 +02:00
|
|
|
|
|
|
|
|
|
The more elaborate form allows you to specify an expander:
|
|
|
|
|
|
2017-11-14 17:10:17 +01:00
|
|
|
|
(define-gexp-compiler something-compiler <something>
|
2016-09-09 22:43:41 +02:00
|
|
|
|
compiler => (lambda (param system target) ...)
|
|
|
|
|
expander => (lambda (param drv output) ...))
|
|
|
|
|
|
|
|
|
|
The expander specifies how an object is converted to its sexp representation."
|
2016-09-10 11:57:37 +02:00
|
|
|
|
((_ (name (param record-type) system target) body ...)
|
|
|
|
|
(define-gexp-compiler name record-type
|
2016-09-09 22:43:41 +02:00
|
|
|
|
compiler => (lambda (param system target) body ...)
|
|
|
|
|
expander => default-expander))
|
2016-09-10 11:57:37 +02:00
|
|
|
|
((_ name record-type
|
2016-09-09 22:43:41 +02:00
|
|
|
|
compiler => compile
|
|
|
|
|
expander => expand)
|
|
|
|
|
(begin
|
|
|
|
|
(define name
|
2016-09-10 11:57:37 +02:00
|
|
|
|
(gexp-compiler record-type compile expand))
|
2016-09-09 22:43:41 +02:00
|
|
|
|
(register-compiler! name)))))
|
2015-03-15 23:27:34 +01:00
|
|
|
|
|
2016-09-10 11:57:37 +02:00
|
|
|
|
(define-gexp-compiler (derivation-compiler (drv <derivation>) system target)
|
2015-03-21 23:13:02 +01:00
|
|
|
|
;; Derivations are the lowest-level representation, so this is the identity
|
|
|
|
|
;; compiler.
|
|
|
|
|
(with-monad %store-monad
|
|
|
|
|
(return drv)))
|
|
|
|
|
|
2019-12-06 23:12:49 +01:00
|
|
|
|
;; Expand to a raw ".drv" file for the lowerable object it wraps. In other
|
|
|
|
|
;; words, this gives the raw ".drv" file instead of its build result.
|
|
|
|
|
(define-record-type <raw-derivation-file>
|
|
|
|
|
(raw-derivation-file obj)
|
|
|
|
|
raw-derivation-file?
|
|
|
|
|
(obj raw-derivation-file-object)) ;lowerable object
|
|
|
|
|
|
|
|
|
|
(define-gexp-compiler raw-derivation-file-compiler <raw-derivation-file>
|
|
|
|
|
compiler => (lambda (obj system target)
|
|
|
|
|
(mlet %store-monad ((obj (lower-object
|
|
|
|
|
(raw-derivation-file-object obj)
|
|
|
|
|
system #:target target)))
|
|
|
|
|
;; Returning the .drv file name instead of the <derivation>
|
|
|
|
|
;; record ensures that 'lower-gexp' will classify it as a
|
|
|
|
|
;; "source" and not as an "input".
|
|
|
|
|
(return (if (derivation? obj)
|
|
|
|
|
(derivation-file-name obj)
|
|
|
|
|
obj))))
|
|
|
|
|
expander => (lambda (obj lowered output)
|
|
|
|
|
(if (derivation? lowered)
|
|
|
|
|
(derivation-file-name lowered)
|
|
|
|
|
lowered)))
|
|
|
|
|
|
2017-11-14 10:16:22 +01:00
|
|
|
|
|
|
|
|
|
;;;
|
|
|
|
|
;;; 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)
|
|
|
|
|
|
2015-03-28 21:26:33 +01:00
|
|
|
|
|
|
|
|
|
;;;
|
2015-06-03 11:45:27 +02:00
|
|
|
|
;;; File declarations.
|
2015-03-28 21:26:33 +01:00
|
|
|
|
;;;
|
|
|
|
|
|
2015-12-14 19:52:47 +01:00
|
|
|
|
;; A local file name. FILE is the file name the user entered, which can be a
|
|
|
|
|
;; relative file name, and ABSOLUTE is a promise that computes its canonical
|
|
|
|
|
;; absolute file name. We keep it in a promise to compute it lazily and avoid
|
|
|
|
|
;; repeated 'stat' calls.
|
2015-03-28 21:26:33 +01:00
|
|
|
|
(define-record-type <local-file>
|
2016-06-16 00:06:27 +02:00
|
|
|
|
(%%local-file file absolute name recursive? select?)
|
2015-03-28 21:26:33 +01:00
|
|
|
|
local-file?
|
|
|
|
|
(file local-file-file) ;string
|
2015-12-14 19:52:47 +01:00
|
|
|
|
(absolute %local-file-absolute-file-name) ;promise string
|
2015-03-28 21:26:33 +01:00
|
|
|
|
(name local-file-name) ;string
|
2016-06-16 00:06:27 +02:00
|
|
|
|
(recursive? local-file-recursive?) ;Boolean
|
|
|
|
|
(select? local-file-select?)) ;string stat -> Boolean
|
|
|
|
|
|
|
|
|
|
(define (true file stat) #t)
|
2015-03-28 21:26:33 +01:00
|
|
|
|
|
2015-12-14 19:52:47 +01:00
|
|
|
|
(define* (%local-file file promise #:optional (name (basename file))
|
2016-06-16 00:06:27 +02:00
|
|
|
|
#:key recursive? (select? true))
|
2015-12-14 19:52:47 +01:00
|
|
|
|
;; This intermediate procedure is part of our ABI, but the underlying
|
|
|
|
|
;; %%LOCAL-FILE is not.
|
2016-06-16 00:06:27 +02:00
|
|
|
|
(%%local-file file promise name recursive? select?))
|
2015-12-14 19:52:47 +01:00
|
|
|
|
|
|
|
|
|
(define (absolute-file-name file directory)
|
|
|
|
|
"Return the canonical absolute file name for FILE, which lives in the
|
|
|
|
|
vicinity of DIRECTORY."
|
|
|
|
|
(canonicalize-path
|
|
|
|
|
(cond ((string-prefix? "/" file) file)
|
|
|
|
|
((not directory) file)
|
|
|
|
|
((string-prefix? "/" directory)
|
|
|
|
|
(string-append directory "/" file))
|
|
|
|
|
(else file))))
|
|
|
|
|
|
2017-07-20 15:48:09 +02:00
|
|
|
|
(define-syntax local-file
|
|
|
|
|
(lambda (s)
|
|
|
|
|
"Return an object representing local file FILE to add to the store; this
|
2015-12-14 19:52:47 +01:00
|
|
|
|
object can be used in a gexp. If FILE is a relative file name, it is looked
|
|
|
|
|
up relative to the source file where this form appears. FILE will be added to
|
|
|
|
|
the store under NAME--by default the base name of FILE.
|
2015-03-28 21:26:33 +01:00
|
|
|
|
|
|
|
|
|
When RECURSIVE? is true, the contents of FILE are added recursively; if FILE
|
|
|
|
|
designates a flat file and RECURSIVE? is true, its contents are added, and its
|
|
|
|
|
permission bits are kept.
|
|
|
|
|
|
2016-06-16 00:06:27 +02:00
|
|
|
|
When RECURSIVE? is true, call (SELECT? FILE STAT) for each directory entry,
|
|
|
|
|
where FILE is the entry's absolute file name and STAT is the result of
|
|
|
|
|
'lstat'; exclude entries for which SELECT? does not return true.
|
|
|
|
|
|
2017-07-20 15:48:09 +02:00
|
|
|
|
This is the declarative counterpart of the 'interned-file' monadic procedure.
|
|
|
|
|
It is implemented as a macro to capture the current source directory where it
|
|
|
|
|
appears."
|
|
|
|
|
(syntax-case s ()
|
|
|
|
|
((_ file rest ...)
|
2019-11-30 17:17:00 +01:00
|
|
|
|
(string? (syntax->datum #'file))
|
|
|
|
|
;; FILE is a literal, so resolve it relative to the source directory.
|
2017-07-20 15:48:09 +02:00
|
|
|
|
#'(%local-file file
|
|
|
|
|
(delay (absolute-file-name file (current-source-directory)))
|
|
|
|
|
rest ...))
|
2019-11-30 17:17:00 +01:00
|
|
|
|
((_ file rest ...)
|
|
|
|
|
;; Resolve FILE relative to the current directory.
|
|
|
|
|
#'(%local-file file
|
|
|
|
|
(delay (absolute-file-name file (getcwd)))
|
|
|
|
|
rest ...))
|
2017-07-20 15:48:09 +02:00
|
|
|
|
((_)
|
|
|
|
|
#'(syntax-error "missing file name"))
|
|
|
|
|
(id
|
|
|
|
|
(identifier? #'id)
|
|
|
|
|
;; XXX: We could return #'(lambda (file . rest) ...). However,
|
|
|
|
|
;; (syntax-source #'id) is #f so (current-source-directory) would not
|
|
|
|
|
;; work. Thus, simply forbid this form.
|
|
|
|
|
#'(syntax-error
|
|
|
|
|
"'local-file' is a macro and cannot be used like this")))))
|
2015-12-14 19:52:47 +01:00
|
|
|
|
|
|
|
|
|
(define (local-file-absolute-file-name file)
|
|
|
|
|
"Return the absolute file name for FILE, a <local-file> instance. A
|
|
|
|
|
'system-error' exception is raised if FILE could not be found."
|
|
|
|
|
(force (%local-file-absolute-file-name file)))
|
2015-03-28 21:26:33 +01:00
|
|
|
|
|
2016-09-10 11:57:37 +02:00
|
|
|
|
(define-gexp-compiler (local-file-compiler (file <local-file>) system target)
|
2015-03-28 21:26:33 +01:00
|
|
|
|
;; "Compile" FILE by adding it to the store.
|
|
|
|
|
(match file
|
2016-06-16 00:06:27 +02:00
|
|
|
|
(($ <local-file> file (= force absolute) name recursive? select?)
|
2015-12-14 19:52:47 +01:00
|
|
|
|
;; Canonicalize FILE so that if it's a symlink, it is resolved. Failing
|
|
|
|
|
;; to do that, when RECURSIVE? is #t, we could end up creating a dangling
|
|
|
|
|
;; symlink in the store, and when RECURSIVE? is #f 'add-to-store' would
|
|
|
|
|
;; just throw an error, both of which are inconvenient.
|
2016-06-16 00:06:27 +02:00
|
|
|
|
(interned-file absolute name
|
|
|
|
|
#:recursive? recursive? #:select? select?))))
|
2015-03-28 21:26:33 +01:00
|
|
|
|
|
2015-06-03 11:45:27 +02:00
|
|
|
|
(define-record-type <plain-file>
|
|
|
|
|
(%plain-file name content references)
|
|
|
|
|
plain-file?
|
|
|
|
|
(name plain-file-name) ;string
|
2018-07-10 19:06:32 +02:00
|
|
|
|
(content plain-file-content) ;string or bytevector
|
2015-06-03 11:45:27 +02:00
|
|
|
|
(references plain-file-references)) ;list (currently unused)
|
|
|
|
|
|
|
|
|
|
(define (plain-file name content)
|
|
|
|
|
"Return an object representing a text file called NAME with the given
|
|
|
|
|
CONTENT (a string) to be added to the store.
|
|
|
|
|
|
|
|
|
|
This is the declarative counterpart of 'text-file'."
|
|
|
|
|
;; XXX: For now just ignore 'references' because it's not clear how to use
|
|
|
|
|
;; them in a declarative context.
|
|
|
|
|
(%plain-file name content '()))
|
|
|
|
|
|
2016-09-10 11:57:37 +02:00
|
|
|
|
(define-gexp-compiler (plain-file-compiler (file <plain-file>) system target)
|
2015-06-03 11:45:27 +02:00
|
|
|
|
;; "Compile" FILE by adding it to the store.
|
|
|
|
|
(match file
|
2018-07-10 19:06:32 +02:00
|
|
|
|
(($ <plain-file> name (and (? string?) content) references)
|
|
|
|
|
(text-file name content references))
|
|
|
|
|
(($ <plain-file> name (and (? bytevector?) content) references)
|
|
|
|
|
(binary-file name content references))))
|
2015-06-03 11:45:27 +02:00
|
|
|
|
|
2015-09-07 22:37:14 +02:00
|
|
|
|
(define-record-type <computed-file>
|
2017-12-10 16:35:41 +01:00
|
|
|
|
(%computed-file name gexp guile options)
|
2015-09-07 22:37:14 +02:00
|
|
|
|
computed-file?
|
|
|
|
|
(name computed-file-name) ;string
|
|
|
|
|
(gexp computed-file-gexp) ;gexp
|
2017-12-10 16:35:41 +01:00
|
|
|
|
(guile computed-file-guile) ;<package>
|
2015-09-07 22:37:14 +02:00
|
|
|
|
(options computed-file-options)) ;list of arguments
|
|
|
|
|
|
|
|
|
|
(define* (computed-file name gexp
|
2017-12-10 16:35:41 +01:00
|
|
|
|
#:key guile (options '(#:local-build? #t)))
|
2015-09-07 22:37:14 +02:00
|
|
|
|
"Return an object representing the store item NAME, a file or directory
|
2016-07-12 17:43:19 +02:00
|
|
|
|
computed by GEXP. OPTIONS is a list of additional arguments to pass
|
2015-09-07 22:37:14 +02:00
|
|
|
|
to 'gexp->derivation'.
|
|
|
|
|
|
|
|
|
|
This is the declarative counterpart of 'gexp->derivation'."
|
2017-12-10 16:35:41 +01:00
|
|
|
|
(%computed-file name gexp guile options))
|
2015-09-07 22:37:14 +02:00
|
|
|
|
|
2016-09-10 11:57:37 +02:00
|
|
|
|
(define-gexp-compiler (computed-file-compiler (file <computed-file>)
|
2015-09-07 22:37:14 +02:00
|
|
|
|
system target)
|
|
|
|
|
;; Compile FILE by returning a derivation whose build expression is its
|
|
|
|
|
;; gexp.
|
|
|
|
|
(match file
|
2017-12-10 16:35:41 +01:00
|
|
|
|
(($ <computed-file> name gexp guile options)
|
|
|
|
|
(if guile
|
|
|
|
|
(mlet %store-monad ((guile (lower-object guile system
|
|
|
|
|
#:target target)))
|
|
|
|
|
(apply gexp->derivation name gexp #:guile-for-build guile
|
2019-01-05 00:01:18 +01:00
|
|
|
|
#:system system #:target target options))
|
|
|
|
|
(apply gexp->derivation name gexp
|
|
|
|
|
#:system system #:target target options)))))
|
2015-09-07 22:37:14 +02:00
|
|
|
|
|
2015-09-08 22:44:26 +02:00
|
|
|
|
(define-record-type <program-file>
|
2018-03-23 18:35:32 +01:00
|
|
|
|
(%program-file name gexp guile path)
|
2015-09-08 22:44:26 +02:00
|
|
|
|
program-file?
|
|
|
|
|
(name program-file-name) ;string
|
|
|
|
|
(gexp program-file-gexp) ;gexp
|
2018-03-23 18:35:32 +01:00
|
|
|
|
(guile program-file-guile) ;package
|
|
|
|
|
(path program-file-module-path)) ;list of strings
|
2015-09-08 22:44:26 +02:00
|
|
|
|
|
2018-03-23 18:35:32 +01:00
|
|
|
|
(define* (program-file name gexp #:key (guile #f) (module-path %load-path))
|
2015-09-08 22:44:26 +02:00
|
|
|
|
"Return an object representing the executable store item NAME that runs
|
2018-03-23 18:35:32 +01:00
|
|
|
|
GEXP. GUILE is the Guile package used to execute that script. Imported
|
|
|
|
|
modules of GEXP are looked up in MODULE-PATH.
|
2015-09-08 22:44:26 +02:00
|
|
|
|
|
|
|
|
|
This is the declarative counterpart of 'gexp->script'."
|
2018-03-23 18:35:32 +01:00
|
|
|
|
(%program-file name gexp guile module-path))
|
2015-09-08 22:44:26 +02:00
|
|
|
|
|
2016-09-10 11:57:37 +02:00
|
|
|
|
(define-gexp-compiler (program-file-compiler (file <program-file>)
|
2015-09-08 22:44:26 +02:00
|
|
|
|
system target)
|
|
|
|
|
;; Compile FILE by returning a derivation that builds the script.
|
|
|
|
|
(match file
|
2018-03-23 18:35:32 +01:00
|
|
|
|
(($ <program-file> name gexp guile module-path)
|
2015-09-08 22:44:26 +02:00
|
|
|
|
(gexp->script name gexp
|
2018-03-23 18:35:32 +01:00
|
|
|
|
#:module-path module-path
|
2019-07-26 23:48:03 +02:00
|
|
|
|
#:guile (or guile (default-guile))
|
|
|
|
|
#:system system
|
|
|
|
|
#:target target))))
|
2015-09-08 22:44:26 +02:00
|
|
|
|
|
2015-09-16 15:03:52 +02:00
|
|
|
|
(define-record-type <scheme-file>
|
2020-04-22 15:24:47 +02:00
|
|
|
|
(%scheme-file name gexp splice? load-path?)
|
2015-09-16 15:03:52 +02:00
|
|
|
|
scheme-file?
|
|
|
|
|
(name scheme-file-name) ;string
|
2018-04-11 00:52:40 +02:00
|
|
|
|
(gexp scheme-file-gexp) ;gexp
|
2020-04-22 15:24:47 +02:00
|
|
|
|
(splice? scheme-file-splice?) ;Boolean
|
|
|
|
|
(load-path? scheme-file-set-load-path?)) ;Boolean
|
2015-09-16 15:03:52 +02:00
|
|
|
|
|
2020-04-22 15:24:47 +02:00
|
|
|
|
(define* (scheme-file name gexp #:key splice? (set-load-path? #t))
|
2015-09-16 15:03:52 +02:00
|
|
|
|
"Return an object representing the Scheme file NAME that contains GEXP.
|
|
|
|
|
|
|
|
|
|
This is the declarative counterpart of 'gexp->file'."
|
2020-04-22 15:24:47 +02:00
|
|
|
|
(%scheme-file name gexp splice? set-load-path?))
|
2015-09-16 15:03:52 +02:00
|
|
|
|
|
2016-09-10 11:57:37 +02:00
|
|
|
|
(define-gexp-compiler (scheme-file-compiler (file <scheme-file>)
|
2015-09-16 15:03:52 +02:00
|
|
|
|
system target)
|
|
|
|
|
;; Compile FILE by returning a derivation that builds the file.
|
|
|
|
|
(match file
|
2020-04-22 15:24:47 +02:00
|
|
|
|
(($ <scheme-file> name gexp splice? set-load-path?)
|
2019-12-14 17:52:53 +01:00
|
|
|
|
(gexp->file name gexp
|
2020-04-22 15:24:47 +02:00
|
|
|
|
#:set-load-path? set-load-path?
|
2019-12-14 17:52:53 +01:00
|
|
|
|
#:splice? splice?
|
|
|
|
|
#:system system
|
|
|
|
|
#:target target))))
|
2015-09-16 15:03:52 +02:00
|
|
|
|
|
2016-09-09 22:46:36 +02:00
|
|
|
|
;; Appending SUFFIX to BASE's output file name.
|
|
|
|
|
(define-record-type <file-append>
|
|
|
|
|
(%file-append base suffix)
|
|
|
|
|
file-append?
|
|
|
|
|
(base file-append-base) ;<package> | <derivation> | ...
|
|
|
|
|
(suffix file-append-suffix)) ;list of strings
|
|
|
|
|
|
2018-10-18 00:45:05 +02:00
|
|
|
|
(define (write-file-append file port)
|
|
|
|
|
(match file
|
|
|
|
|
(($ <file-append> base suffix)
|
|
|
|
|
(format port "#<file-append ~s ~s>" base
|
|
|
|
|
(string-join suffix)))))
|
|
|
|
|
|
|
|
|
|
(set-record-type-printer! <file-append> write-file-append)
|
|
|
|
|
|
2016-09-09 22:46:36 +02:00
|
|
|
|
(define (file-append base . suffix)
|
|
|
|
|
"Return a <file-append> object that expands to the concatenation of BASE and
|
|
|
|
|
SUFFIX."
|
|
|
|
|
(%file-append base suffix))
|
|
|
|
|
|
2016-09-10 11:57:37 +02:00
|
|
|
|
(define-gexp-compiler file-append-compiler <file-append>
|
2016-09-09 22:46:36 +02:00
|
|
|
|
compiler => (lambda (obj system target)
|
|
|
|
|
(match obj
|
|
|
|
|
(($ <file-append> base _)
|
|
|
|
|
(lower-object base system #:target target))))
|
|
|
|
|
expander => (lambda (obj lowered output)
|
|
|
|
|
(match obj
|
|
|
|
|
(($ <file-append> base suffix)
|
|
|
|
|
(let* ((expand (lookup-expander base))
|
|
|
|
|
(base (expand base lowered output)))
|
|
|
|
|
(string-append base (string-concatenate suffix)))))))
|
|
|
|
|
|
2020-03-06 11:25:43 +01:00
|
|
|
|
;; Representation of SRFI-39 parameter settings in the dynamic scope of an
|
|
|
|
|
;; object lowering.
|
|
|
|
|
(define-record-type <parameterized>
|
|
|
|
|
(parameterized bindings thunk)
|
|
|
|
|
parameterized?
|
|
|
|
|
(bindings parameterized-bindings) ;list of parameter/value pairs
|
|
|
|
|
(thunk parameterized-thunk)) ;thunk
|
|
|
|
|
|
|
|
|
|
(define-syntax-rule (with-parameters ((param value) ...) body ...)
|
|
|
|
|
"Bind each PARAM to the corresponding VALUE for the extent during which BODY
|
|
|
|
|
is lowered. Consider this example:
|
|
|
|
|
|
|
|
|
|
(with-parameters ((%current-system \"x86_64-linux\"))
|
|
|
|
|
coreutils)
|
|
|
|
|
|
|
|
|
|
It returns a <parameterized> object that ensures %CURRENT-SYSTEM is set to
|
|
|
|
|
x86_64-linux when COREUTILS is lowered."
|
|
|
|
|
(parameterized (list (list param (lambda () value)) ...)
|
|
|
|
|
(lambda ()
|
|
|
|
|
body ...)))
|
|
|
|
|
|
|
|
|
|
(define-gexp-compiler compile-parameterized <parameterized>
|
|
|
|
|
compiler =>
|
|
|
|
|
(lambda (parameterized system target)
|
|
|
|
|
(match (parameterized-bindings parameterized)
|
|
|
|
|
(((parameters values) ...)
|
|
|
|
|
(let ((fluids (map parameter-fluid parameters))
|
|
|
|
|
(thunk (parameterized-thunk parameterized)))
|
|
|
|
|
;; Install the PARAMETERS for the dynamic extent of THUNK.
|
|
|
|
|
(with-fluids* fluids
|
|
|
|
|
(map (lambda (thunk) (thunk)) values)
|
|
|
|
|
(lambda ()
|
|
|
|
|
;; Special-case '%current-system' and '%current-target-system' to
|
|
|
|
|
;; make sure we get the desired effect.
|
|
|
|
|
(let ((system (if (memq %current-system parameters)
|
|
|
|
|
(%current-system)
|
|
|
|
|
system))
|
|
|
|
|
(target (if (memq %current-target-system parameters)
|
|
|
|
|
(%current-target-system)
|
|
|
|
|
target)))
|
|
|
|
|
(lower-object (thunk) system #:target target))))))))
|
|
|
|
|
|
|
|
|
|
expander => (lambda (parameterized lowered output)
|
|
|
|
|
(match (parameterized-bindings parameterized)
|
|
|
|
|
(((parameters values) ...)
|
|
|
|
|
(let ((fluids (map parameter-fluid parameters))
|
|
|
|
|
(thunk (parameterized-thunk parameterized)))
|
|
|
|
|
;; Install the PARAMETERS for the dynamic extent of THUNK.
|
|
|
|
|
(with-fluids* fluids
|
|
|
|
|
(map (lambda (thunk) (thunk)) values)
|
|
|
|
|
(lambda ()
|
|
|
|
|
;; Delegate to the expander of the wrapped object.
|
|
|
|
|
(let* ((base (thunk))
|
|
|
|
|
(expand (lookup-expander base)))
|
|
|
|
|
(expand base lowered output)))))))))
|
2016-09-09 22:46:36 +02:00
|
|
|
|
|
2015-03-15 23:27:34 +01:00
|
|
|
|
|
|
|
|
|
;;;
|
|
|
|
|
;;; Inputs & outputs.
|
|
|
|
|
;;;
|
|
|
|
|
|
2015-03-11 23:20:50 +01:00
|
|
|
|
;; The input of a gexp.
|
|
|
|
|
(define-record-type <gexp-input>
|
2015-03-15 21:45:37 +01:00
|
|
|
|
(%gexp-input thing output native?)
|
2015-03-11 23:20:50 +01:00
|
|
|
|
gexp-input?
|
|
|
|
|
(thing gexp-input-thing) ;<package> | <origin> | <derivation> | ...
|
|
|
|
|
(output gexp-input-output) ;string
|
|
|
|
|
(native? gexp-input-native?)) ;Boolean
|
|
|
|
|
|
2015-03-30 22:59:24 +02:00
|
|
|
|
(define (write-gexp-input input port)
|
|
|
|
|
(match input
|
|
|
|
|
(($ <gexp-input> thing output #f)
|
|
|
|
|
(format port "#<gexp-input ~s:~a>" thing output))
|
|
|
|
|
(($ <gexp-input> thing output #t)
|
|
|
|
|
(format port "#<gexp-input native ~s:~a>" thing output))))
|
|
|
|
|
|
|
|
|
|
(set-record-type-printer! <gexp-input> write-gexp-input)
|
|
|
|
|
|
2015-03-15 21:45:37 +01:00
|
|
|
|
(define* (gexp-input thing ;convenience procedure
|
|
|
|
|
#:optional (output "out")
|
|
|
|
|
#:key native?)
|
|
|
|
|
"Return a new <gexp-input> for the OUTPUT of THING; NATIVE? determines
|
|
|
|
|
whether this should be considered a \"native\" input or not."
|
|
|
|
|
(%gexp-input thing output native?))
|
|
|
|
|
|
2014-04-28 23:00:57 +02:00
|
|
|
|
;; Reference to one of the derivation's outputs, for gexps used in
|
|
|
|
|
;; derivations.
|
2015-03-16 22:31:14 +01:00
|
|
|
|
(define-record-type <gexp-output>
|
|
|
|
|
(gexp-output name)
|
|
|
|
|
gexp-output?
|
|
|
|
|
(name gexp-output-name))
|
2014-04-28 23:00:57 +02:00
|
|
|
|
|
2015-03-30 22:59:24 +02:00
|
|
|
|
(define (write-gexp-output output port)
|
|
|
|
|
(match output
|
|
|
|
|
(($ <gexp-output> name)
|
|
|
|
|
(format port "#<gexp-output ~a>" name))))
|
|
|
|
|
|
|
|
|
|
(set-record-type-printer! <gexp-output> write-gexp-output)
|
|
|
|
|
|
2018-10-27 15:45:45 +02:00
|
|
|
|
(define* (gexp-attribute gexp self-attribute #:optional (equal? equal?))
|
2018-05-28 18:14:37 +02:00
|
|
|
|
"Recurse on GEXP and the expressions it refers to, summing the items
|
2018-10-27 15:45:45 +02:00
|
|
|
|
returned by SELF-ATTRIBUTE, a procedure that takes a gexp. Use EQUAL? as the
|
|
|
|
|
second argument to 'delete-duplicates'."
|
2017-04-19 16:11:25 +02:00
|
|
|
|
(if (gexp? gexp)
|
|
|
|
|
(delete-duplicates
|
2018-05-28 18:14:37 +02:00
|
|
|
|
(append (self-attribute gexp)
|
2017-04-19 16:11:25 +02:00
|
|
|
|
(append-map (match-lambda
|
|
|
|
|
(($ <gexp-input> (? gexp? exp))
|
2018-05-28 18:14:37 +02:00
|
|
|
|
(gexp-attribute exp self-attribute))
|
2017-04-19 16:11:25 +02:00
|
|
|
|
(($ <gexp-input> (lst ...))
|
|
|
|
|
(append-map (lambda (item)
|
|
|
|
|
(if (gexp? item)
|
2018-05-28 18:14:37 +02:00
|
|
|
|
(gexp-attribute item
|
|
|
|
|
self-attribute)
|
2017-04-19 16:11:25 +02:00
|
|
|
|
'()))
|
|
|
|
|
lst))
|
|
|
|
|
(_
|
|
|
|
|
'()))
|
2018-10-27 15:45:45 +02:00
|
|
|
|
(gexp-references gexp)))
|
|
|
|
|
equal?)
|
2017-04-19 16:11:25 +02:00
|
|
|
|
'())) ;plain Scheme data type
|
2016-07-03 22:26:19 +02:00
|
|
|
|
|
2018-05-28 18:14:37 +02:00
|
|
|
|
(define (gexp-modules gexp)
|
|
|
|
|
"Return the list of Guile module names GEXP relies on. If (gexp? GEXP) is
|
|
|
|
|
false, meaning that GEXP is a plain Scheme object, return the empty list."
|
2018-10-27 15:45:45 +02:00
|
|
|
|
(define (module=? m1 m2)
|
|
|
|
|
;; Return #t when M1 equals M2. Special-case '=>' specs because their
|
|
|
|
|
;; right-hand side may not be comparable with 'equal?': it's typically a
|
|
|
|
|
;; file-like object that embeds a gexp, which in turn embeds closure;
|
|
|
|
|
;; those closures may be 'eq?' when running compiled code but are unlikely
|
|
|
|
|
;; to be 'eq?' when running on 'eval'. Ignore the right-hand side to
|
|
|
|
|
;; avoid this discrepancy.
|
|
|
|
|
(match m1
|
|
|
|
|
(((name1 ...) '=> _)
|
|
|
|
|
(match m2
|
|
|
|
|
(((name2 ...) '=> _) (equal? name1 name2))
|
|
|
|
|
(_ #f)))
|
|
|
|
|
(_
|
|
|
|
|
(equal? m1 m2))))
|
|
|
|
|
|
|
|
|
|
(gexp-attribute gexp gexp-self-modules module=?))
|
2018-05-28 18:14:37 +02:00
|
|
|
|
|
|
|
|
|
(define (gexp-extensions gexp)
|
|
|
|
|
"Return the list of Guile extensions (packages) GEXP relies on. If (gexp?
|
|
|
|
|
GEXP) is false, meaning that GEXP is a plain Scheme object, return the empty
|
|
|
|
|
list."
|
|
|
|
|
(gexp-attribute gexp gexp-self-extensions))
|
|
|
|
|
|
2017-11-14 10:16:22 +01:00
|
|
|
|
(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?)))
|
|
|
|
|
|
2014-08-17 21:20:11 +02:00
|
|
|
|
(define* (lower-inputs inputs
|
|
|
|
|
#:key system target)
|
2019-07-09 23:05:01 +02:00
|
|
|
|
"Turn any object from INPUTS into a derivation input for SYSTEM or a store
|
|
|
|
|
item (a \"source\"); return the corresponding input list as a monadic value.
|
|
|
|
|
When TARGET is true, use it as the cross-compilation target triplet."
|
2019-06-10 14:34:36 +02:00
|
|
|
|
(define (store-item? obj)
|
|
|
|
|
(and (string? obj) (store-path? obj)))
|
|
|
|
|
|
2017-11-14 10:16:22 +01:00
|
|
|
|
(define filterm
|
|
|
|
|
(lift1 (cut filter ->bool <>) %store-monad))
|
|
|
|
|
|
2014-04-28 23:00:57 +02:00
|
|
|
|
(with-monad %store-monad
|
2017-11-14 10:16:22 +01:00
|
|
|
|
(>>= (mapm/accumulate-builds
|
|
|
|
|
(match-lambda
|
|
|
|
|
(((? struct? thing) sub-drv ...)
|
|
|
|
|
(mlet %store-monad ((obj (lower-object
|
|
|
|
|
thing system #:target target)))
|
|
|
|
|
(return (match obj
|
|
|
|
|
((? derivation? drv)
|
|
|
|
|
(let ((outputs (if (null? sub-drv)
|
|
|
|
|
'("out")
|
|
|
|
|
sub-drv)))
|
|
|
|
|
(derivation-input drv outputs)))
|
|
|
|
|
((? store-item? item)
|
|
|
|
|
item)
|
|
|
|
|
((? self-quoting?)
|
|
|
|
|
;; Some inputs such as <system-binding> can lower to
|
|
|
|
|
;; a self-quoting object that FILTERM will filter
|
|
|
|
|
;; out.
|
|
|
|
|
#f)))))
|
|
|
|
|
(((? store-item? item))
|
|
|
|
|
(return item)))
|
|
|
|
|
inputs)
|
|
|
|
|
filterm)))
|
2014-04-28 23:00:57 +02:00
|
|
|
|
|
2014-09-06 15:45:32 +02:00
|
|
|
|
(define* (lower-reference-graphs graphs #:key system target)
|
|
|
|
|
"Given GRAPHS, a list of (FILE-NAME INPUT ...) lists for use as a
|
|
|
|
|
#:reference-graphs argument, lower it such that each INPUT is replaced by the
|
2019-07-09 23:05:01 +02:00
|
|
|
|
corresponding <derivation-input> or store item."
|
2014-09-06 15:45:32 +02:00
|
|
|
|
(match graphs
|
|
|
|
|
(((file-names . inputs) ...)
|
|
|
|
|
(mlet %store-monad ((inputs (lower-inputs inputs
|
|
|
|
|
#:system system
|
|
|
|
|
#:target target)))
|
2019-07-09 23:05:01 +02:00
|
|
|
|
(return (map cons file-names inputs))))))
|
2014-09-06 15:45:32 +02:00
|
|
|
|
|
2015-02-11 22:10:14 +01:00
|
|
|
|
(define* (lower-references lst #:key system target)
|
|
|
|
|
"Based on LST, a list of output names and packages, return a list of output
|
|
|
|
|
names and file names suitable for the #:allowed-references argument to
|
|
|
|
|
'derivation'."
|
|
|
|
|
(with-monad %store-monad
|
|
|
|
|
(define lower
|
|
|
|
|
(match-lambda
|
|
|
|
|
((? string? output)
|
|
|
|
|
(return output))
|
2015-03-21 23:21:53 +01:00
|
|
|
|
(($ <gexp-input> thing output native?)
|
2015-08-26 11:28:23 +02:00
|
|
|
|
(mlet %store-monad ((drv (lower-object thing system
|
|
|
|
|
#:target (if native?
|
|
|
|
|
#f target))))
|
2015-03-21 23:21:53 +01:00
|
|
|
|
(return (derivation->output-path drv output))))
|
2015-03-15 23:27:34 +01:00
|
|
|
|
(thing
|
2015-08-26 11:28:23 +02:00
|
|
|
|
(mlet %store-monad ((drv (lower-object thing system
|
|
|
|
|
#:target target)))
|
2015-02-11 22:10:14 +01:00
|
|
|
|
(return (derivation->output-path drv))))))
|
|
|
|
|
|
2020-04-02 10:59:15 +02:00
|
|
|
|
(mapm/accumulate-builds lower lst)))
|
2015-02-11 22:10:14 +01:00
|
|
|
|
|
2015-03-17 22:09:32 +01:00
|
|
|
|
(define default-guile-derivation
|
|
|
|
|
;; Here we break the abstraction by talking to the higher-level layer.
|
|
|
|
|
;; Thus, do the resolution lazily to hide the circular dependency.
|
|
|
|
|
(let ((proc (delay
|
|
|
|
|
(let ((iface (resolve-interface '(guix packages))))
|
|
|
|
|
(module-ref iface 'default-guile-derivation)))))
|
|
|
|
|
(lambda (system)
|
|
|
|
|
((force proc) system))))
|
|
|
|
|
|
2019-06-10 14:34:36 +02:00
|
|
|
|
;; Representation of a gexp instantiated for a given target and system.
|
2019-07-09 23:05:01 +02:00
|
|
|
|
;; It's an intermediate representation between <gexp> and <derivation>.
|
2019-06-10 14:34:36 +02:00
|
|
|
|
(define-record-type <lowered-gexp>
|
2019-07-09 23:05:01 +02:00
|
|
|
|
(lowered-gexp sexp inputs sources guile load-path load-compiled-path)
|
2019-06-10 14:34:36 +02:00
|
|
|
|
lowered-gexp?
|
|
|
|
|
(sexp lowered-gexp-sexp) ;sexp
|
2019-07-09 23:05:01 +02:00
|
|
|
|
(inputs lowered-gexp-inputs) ;list of <derivation-input>
|
|
|
|
|
(sources lowered-gexp-sources) ;list of store items
|
2019-07-10 18:39:25 +02:00
|
|
|
|
(guile lowered-gexp-guile) ;<derivation-input> | #f
|
2019-06-10 14:34:36 +02:00
|
|
|
|
(load-path lowered-gexp-load-path) ;list of store items
|
|
|
|
|
(load-compiled-path lowered-gexp-load-compiled-path)) ;list of store items
|
|
|
|
|
|
2019-10-27 18:55:44 +01:00
|
|
|
|
(define* (imported+compiled-modules modules system
|
|
|
|
|
#:key (extensions '())
|
|
|
|
|
deprecation-warnings guile
|
|
|
|
|
(module-path %load-path))
|
|
|
|
|
"Return a pair where the first element is the imported MODULES and the
|
|
|
|
|
second element is the derivation to compile them."
|
2019-10-27 19:12:11 +01:00
|
|
|
|
(mcached equal?
|
|
|
|
|
(mlet %store-monad ((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
|
|
|
|
|
#:deprecation-warnings
|
|
|
|
|
deprecation-warnings)
|
|
|
|
|
(return #f))))
|
|
|
|
|
(return (cons modules compiled)))
|
|
|
|
|
modules
|
|
|
|
|
system extensions guile deprecation-warnings module-path))
|
2019-10-27 18:55:44 +01:00
|
|
|
|
|
2019-06-10 14:34:36 +02:00
|
|
|
|
(define* (lower-gexp exp
|
|
|
|
|
#:key
|
|
|
|
|
(module-path %load-path)
|
|
|
|
|
(system (%current-system))
|
|
|
|
|
(target 'current)
|
|
|
|
|
(graft? (%graft?))
|
|
|
|
|
(guile-for-build (%guile-for-build))
|
2020-03-17 15:32:36 +01:00
|
|
|
|
(effective-version "3.0")
|
2019-06-10 14:34:36 +02:00
|
|
|
|
|
2019-07-12 01:03:53 +02:00
|
|
|
|
deprecation-warnings)
|
2019-06-10 14:34:36 +02:00
|
|
|
|
"*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)
|
2020-03-06 10:06:54 +01:00
|
|
|
|
(lower-object obj system
|
|
|
|
|
#:target #f))
|
2019-06-10 14:34:36 +02:00
|
|
|
|
extensions))
|
2019-10-27 18:55:44 +01:00
|
|
|
|
(modules+compiled (imported+compiled-modules
|
|
|
|
|
%modules system
|
|
|
|
|
#:extensions extensions
|
|
|
|
|
#:deprecation-warnings
|
|
|
|
|
deprecation-warnings
|
|
|
|
|
#:guile guile
|
|
|
|
|
#:module-path module-path))
|
|
|
|
|
(modules -> (car modules+compiled))
|
|
|
|
|
(compiled -> (cdr modules+compiled)))
|
2019-06-10 14:34:36 +02:00
|
|
|
|
(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
|
2019-07-09 23:05:01 +02:00
|
|
|
|
`(,@(if (derivation? modules)
|
|
|
|
|
(list (derivation-input modules))
|
2019-06-10 14:34:36 +02:00
|
|
|
|
'())
|
|
|
|
|
,@(if compiled
|
2019-07-09 23:05:01 +02:00
|
|
|
|
(list (derivation-input compiled))
|
2019-06-10 14:34:36 +02:00
|
|
|
|
'())
|
2019-07-09 23:05:01 +02:00
|
|
|
|
,@(map derivation-input exts)
|
|
|
|
|
,@(filter derivation-input? inputs))
|
|
|
|
|
(filter string? (cons modules inputs))
|
2019-07-10 18:39:25 +02:00
|
|
|
|
(derivation-input guile '("out"))
|
2019-06-10 14:34:36 +02:00
|
|
|
|
load-path
|
|
|
|
|
load-compiled-path)))))
|
|
|
|
|
|
2014-04-28 23:00:57 +02:00
|
|
|
|
(define* (gexp->derivation name exp
|
|
|
|
|
#:key
|
2014-08-17 21:20:11 +02:00
|
|
|
|
system (target 'current)
|
2014-04-28 23:00:57 +02:00
|
|
|
|
hash hash-algo recursive?
|
|
|
|
|
(env-vars '())
|
|
|
|
|
(modules '())
|
2014-11-09 22:19:17 +01:00
|
|
|
|
(module-path %load-path)
|
2014-04-28 23:00:57 +02:00
|
|
|
|
(guile-for-build (%guile-for-build))
|
2020-03-17 15:32:36 +01:00
|
|
|
|
(effective-version "3.0")
|
2015-02-13 23:14:05 +01:00
|
|
|
|
(graft? (%graft?))
|
2014-04-28 23:00:57 +02:00
|
|
|
|
references-graphs
|
2016-03-20 22:44:03 +01:00
|
|
|
|
allowed-references disallowed-references
|
2015-04-30 23:51:44 +02:00
|
|
|
|
leaked-env-vars
|
2015-08-29 00:32:31 +02:00
|
|
|
|
local-build? (substitutable? #t)
|
2018-11-26 22:14:11 +01:00
|
|
|
|
(properties '())
|
2017-11-29 16:38:13 +01:00
|
|
|
|
deprecation-warnings
|
2015-08-29 00:32:31 +02:00
|
|
|
|
(script-name (string-append name "-builder")))
|
2014-04-28 23:00:57 +02:00
|
|
|
|
"Return a derivation NAME that runs EXP (a gexp) with GUILE-FOR-BUILD (a
|
2015-08-29 00:32:31 +02:00
|
|
|
|
derivation) on SYSTEM; EXP is stored in a file called SCRIPT-NAME. When
|
|
|
|
|
TARGET is true, it is used as the cross-compilation target triplet for
|
|
|
|
|
packages referred to by EXP.
|
2014-04-28 23:00:57 +02:00
|
|
|
|
|
2016-07-03 22:26:19 +02:00
|
|
|
|
MODULES is deprecated in favor of 'with-imported-modules'. Its meaning is to
|
|
|
|
|
make MODULES available in the evaluation context of EXP; MODULES is a list of
|
2014-11-09 22:19:17 +01:00
|
|
|
|
names of Guile modules searched in MODULE-PATH to be copied in the store,
|
2014-04-28 23:00:57 +02:00
|
|
|
|
compiled, and made available in the load path during the execution of
|
|
|
|
|
EXP---e.g., '((guix build utils) (guix build gnu-build-system)).
|
|
|
|
|
|
2018-05-28 18:14:37 +02:00
|
|
|
|
EFFECTIVE-VERSION determines the string to use when adding extensions of
|
|
|
|
|
EXP (see 'with-extensions') to the search path---e.g., \"2.2\".
|
|
|
|
|
|
2015-02-13 23:14:05 +01:00
|
|
|
|
GRAFT? determines whether packages referred to by EXP should be grafted when
|
|
|
|
|
applicable.
|
|
|
|
|
|
2014-09-06 15:45:32 +02:00
|
|
|
|
When REFERENCES-GRAPHS is true, it must be a list of tuples of one of the
|
|
|
|
|
following forms:
|
|
|
|
|
|
|
|
|
|
(FILE-NAME PACKAGE)
|
|
|
|
|
(FILE-NAME PACKAGE OUTPUT)
|
|
|
|
|
(FILE-NAME DERIVATION)
|
|
|
|
|
(FILE-NAME DERIVATION OUTPUT)
|
|
|
|
|
(FILE-NAME STORE-ITEM)
|
|
|
|
|
|
|
|
|
|
The right-hand-side of each element of REFERENCES-GRAPHS is automatically made
|
|
|
|
|
an input of the build process of EXP. In the build environment, each
|
|
|
|
|
FILE-NAME contains the reference graph of the corresponding item, in a simple
|
|
|
|
|
text format.
|
|
|
|
|
|
2015-02-11 22:10:14 +01:00
|
|
|
|
ALLOWED-REFERENCES must be either #f or a list of output names and packages.
|
|
|
|
|
In the latter case, the list denotes store items that the result is allowed to
|
|
|
|
|
refer to. Any reference to another store item will lead to a build error.
|
2016-03-20 22:44:03 +01:00
|
|
|
|
Similarly for DISALLOWED-REFERENCES, which can list items that must not be
|
|
|
|
|
referenced by the outputs.
|
2014-09-06 15:45:32 +02:00
|
|
|
|
|
2017-11-29 16:38:13 +01:00
|
|
|
|
DEPRECATION-WARNINGS determines whether to show deprecation warnings while
|
|
|
|
|
compiling modules. It can be #f, #t, or 'detailed.
|
|
|
|
|
|
2014-04-28 23:00:57 +02:00
|
|
|
|
The other arguments are as for 'derivation'."
|
|
|
|
|
(define outputs (gexp-outputs exp))
|
2019-06-10 14:34:36 +02:00
|
|
|
|
(define requested-graft? graft?)
|
2014-04-28 23:00:57 +02:00
|
|
|
|
|
2014-09-06 15:45:32 +02:00
|
|
|
|
(define (graphs-file-names graphs)
|
|
|
|
|
;; Return a list of (FILE-NAME . STORE-PATH) pairs made from GRAPHS.
|
|
|
|
|
(map (match-lambda
|
2019-07-09 23:05:01 +02:00
|
|
|
|
((file-name . (? derivation-input? input))
|
|
|
|
|
(cons file-name (first (derivation-input-output-paths input))))
|
|
|
|
|
((file-name . (? string? item))
|
|
|
|
|
(cons file-name item)))
|
2014-09-06 15:45:32 +02:00
|
|
|
|
graphs))
|
|
|
|
|
|
2019-06-10 14:34:36 +02:00
|
|
|
|
(define (add-modules exp modules)
|
|
|
|
|
(if (null? modules)
|
|
|
|
|
exp
|
|
|
|
|
(make-gexp (gexp-references exp)
|
|
|
|
|
(append modules (gexp-self-modules exp))
|
|
|
|
|
(gexp-self-extensions exp)
|
|
|
|
|
(gexp-proc exp))))
|
2018-05-28 18:14:37 +02:00
|
|
|
|
|
|
|
|
|
(mlet* %store-monad ( ;; The following binding forces '%current-system' and
|
2015-02-13 23:14:05 +01:00
|
|
|
|
;; '%current-target-system' to be looked up at >>=
|
|
|
|
|
;; time.
|
|
|
|
|
(graft? (set-grafting graft?))
|
2014-08-17 21:20:11 +02:00
|
|
|
|
|
2014-07-12 22:11:12 +02:00
|
|
|
|
(system -> (or system (%current-system)))
|
2014-08-17 21:20:11 +02:00
|
|
|
|
(target -> (if (eq? target 'current)
|
|
|
|
|
(%current-target-system)
|
|
|
|
|
target))
|
2019-06-10 14:34:36 +02:00
|
|
|
|
(exp -> (add-modules exp modules))
|
|
|
|
|
(lowered (lower-gexp exp
|
|
|
|
|
#:module-path module-path
|
|
|
|
|
#:system system
|
|
|
|
|
#:target target
|
|
|
|
|
#:graft? requested-graft?
|
|
|
|
|
#:guile-for-build
|
|
|
|
|
guile-for-build
|
|
|
|
|
#:effective-version
|
|
|
|
|
effective-version
|
|
|
|
|
#:deprecation-warnings
|
2019-07-12 01:03:53 +02:00
|
|
|
|
deprecation-warnings))
|
2019-06-10 14:34:36 +02:00
|
|
|
|
|
2014-09-06 15:45:32 +02:00
|
|
|
|
(graphs (if references-graphs
|
|
|
|
|
(lower-reference-graphs references-graphs
|
|
|
|
|
#:system system
|
|
|
|
|
#:target target)
|
|
|
|
|
(return #f)))
|
2015-02-11 22:10:14 +01:00
|
|
|
|
(allowed (if allowed-references
|
|
|
|
|
(lower-references allowed-references
|
|
|
|
|
#:system system
|
|
|
|
|
#:target target)
|
|
|
|
|
(return #f)))
|
2016-03-20 22:44:03 +01:00
|
|
|
|
(disallowed (if disallowed-references
|
|
|
|
|
(lower-references disallowed-references
|
|
|
|
|
#:system system
|
|
|
|
|
#:target target)
|
|
|
|
|
(return #f)))
|
2019-06-10 14:34:36 +02:00
|
|
|
|
(guile -> (lowered-gexp-guile lowered))
|
|
|
|
|
(builder (text-file script-name
|
|
|
|
|
(object->string
|
|
|
|
|
(lowered-gexp-sexp lowered)))))
|
2015-02-13 23:14:05 +01:00
|
|
|
|
(mbegin %store-monad
|
|
|
|
|
(set-grafting graft?) ;restore the initial setting
|
|
|
|
|
(raw-derivation name
|
2019-07-10 18:39:25 +02:00
|
|
|
|
(string-append (derivation-input-output-path guile)
|
2015-02-13 23:14:05 +01:00
|
|
|
|
"/bin/guile")
|
|
|
|
|
`("--no-auto-compile"
|
2019-06-10 14:34:36 +02:00
|
|
|
|
,@(append-map (lambda (directory)
|
|
|
|
|
`("-L" ,directory))
|
|
|
|
|
(lowered-gexp-load-path lowered))
|
|
|
|
|
,@(append-map (lambda (directory)
|
|
|
|
|
`("-C" ,directory))
|
|
|
|
|
(lowered-gexp-load-compiled-path lowered))
|
2015-02-13 23:14:05 +01:00
|
|
|
|
,builder)
|
|
|
|
|
#:outputs outputs
|
|
|
|
|
#:env-vars env-vars
|
|
|
|
|
#:system system
|
2019-07-10 18:39:25 +02:00
|
|
|
|
#:inputs `(,guile
|
2019-07-09 23:05:01 +02:00
|
|
|
|
,@(lowered-gexp-inputs lowered)
|
2015-02-13 23:14:05 +01:00
|
|
|
|
,@(match graphs
|
2019-07-09 23:05:01 +02:00
|
|
|
|
(((_ . inputs) ...)
|
|
|
|
|
(filter derivation-input? inputs))
|
|
|
|
|
(#f '())))
|
|
|
|
|
#:sources `(,builder
|
|
|
|
|
,@(if (and (string? modules)
|
|
|
|
|
(store-path? modules))
|
|
|
|
|
(list modules)
|
|
|
|
|
'())
|
|
|
|
|
,@(lowered-gexp-sources lowered)
|
|
|
|
|
,@(match graphs
|
|
|
|
|
(((_ . inputs) ...)
|
|
|
|
|
(filter string? inputs))
|
|
|
|
|
(#f '())))
|
|
|
|
|
|
2015-02-13 23:14:05 +01:00
|
|
|
|
#:hash hash #:hash-algo hash-algo #:recursive? recursive?
|
|
|
|
|
#:references-graphs (and=> graphs graphs-file-names)
|
|
|
|
|
#:allowed-references allowed
|
2016-03-20 22:44:03 +01:00
|
|
|
|
#:disallowed-references disallowed
|
2015-04-30 23:51:44 +02:00
|
|
|
|
#:leaked-env-vars leaked-env-vars
|
2015-07-03 00:05:16 +02:00
|
|
|
|
#:local-build? local-build?
|
2018-11-26 22:14:11 +01:00
|
|
|
|
#:substitutable? substitutable?
|
|
|
|
|
#:properties properties))))
|
2014-04-28 23:00:57 +02:00
|
|
|
|
|
2015-03-22 23:17:37 +01:00
|
|
|
|
(define* (gexp-inputs exp #:key native?)
|
|
|
|
|
"Return the input list for EXP. When NATIVE? is true, return only native
|
|
|
|
|
references; otherwise, return only non-native references."
|
2019-06-10 14:34:36 +02:00
|
|
|
|
;; TODO: Return <gexp-input> records instead of tuples.
|
2014-04-28 23:00:57 +02:00
|
|
|
|
(define (add-reference-inputs ref result)
|
|
|
|
|
(match ref
|
2015-03-22 23:17:37 +01:00
|
|
|
|
(($ <gexp-input> (? gexp? exp) _ #t)
|
|
|
|
|
(if native?
|
|
|
|
|
(append (gexp-inputs exp)
|
|
|
|
|
(gexp-inputs exp #:native? #t)
|
|
|
|
|
result)
|
|
|
|
|
result))
|
|
|
|
|
(($ <gexp-input> (? gexp? exp) _ #f)
|
2016-12-19 17:13:21 +01:00
|
|
|
|
(append (gexp-inputs exp #:native? native?)
|
|
|
|
|
result))
|
2015-03-11 23:20:50 +01:00
|
|
|
|
(($ <gexp-input> (? string? str))
|
|
|
|
|
(if (direct-store-path? str)
|
|
|
|
|
(cons `(,str) result)
|
2014-04-28 23:00:57 +02:00
|
|
|
|
result))
|
2016-12-19 17:06:12 +01:00
|
|
|
|
(($ <gexp-input> (? struct? thing) output n?)
|
|
|
|
|
(if (and (eqv? n? native?) (lookup-compiler thing))
|
2015-03-15 23:27:34 +01:00
|
|
|
|
;; THING is a derivation, or a package, or an origin, etc.
|
|
|
|
|
(cons `(,thing ,output) result)
|
|
|
|
|
result))
|
2015-03-22 23:17:37 +01:00
|
|
|
|
(($ <gexp-input> (lst ...) output n?)
|
2017-07-17 23:21:55 +02:00
|
|
|
|
(fold-right add-reference-inputs result
|
|
|
|
|
;; XXX: For now, automatically convert LST to a list of
|
|
|
|
|
;; gexp-inputs. Inherit N?.
|
|
|
|
|
(map (match-lambda
|
|
|
|
|
((? gexp-input? x)
|
|
|
|
|
(%gexp-input (gexp-input-thing x)
|
|
|
|
|
(gexp-input-output x)
|
|
|
|
|
n?))
|
|
|
|
|
(x
|
|
|
|
|
(%gexp-input x "out" n?)))
|
|
|
|
|
lst)))
|
2014-04-28 23:00:57 +02:00
|
|
|
|
(_
|
|
|
|
|
;; Ignore references to other kinds of objects.
|
|
|
|
|
result)))
|
|
|
|
|
|
|
|
|
|
(fold-right add-reference-inputs
|
|
|
|
|
'()
|
2016-12-19 17:06:12 +01:00
|
|
|
|
(gexp-references exp)))
|
gexp: Add 'ungexp-native' and 'ungexp-native-splicing'.
* guix/gexp.scm (<gexp>)[natives]: New field.
(write-gexp): Use both 'gexp-references' and
'gexp-native-references'.
(gexp->derivation): Use both 'gexp-inputs' and 'gexp-native-inputs',
and append them.
(gexp-inputs): Add 'references' parameter and honor it.
(gexp-native-inputs): New procedure.
(gexp->sexp)[reference->sexp]: Add 'native?' parameter and honor it.
Use it, and use 'gexp-native-references'.
(gexp)[collect-native-escapes]: New procedure.
[escape->ref]: Handle 'ungexp-native' and 'ungexp-native-splicing'.
[substitute-ungexp, substitute-ungexp-splicing]: New procedures.
[substitute-references]: Use them, and handle 'ungexp-native' and
'ungexp-native-splicing'.
Adjust generated 'make-gexp' call to provide both normal references
and native references.
[read-ungexp]: Support 'ungexp-native' and
'ungexp-native-splicing'.
Add reader extension for #+.
* tests/gexp.scm (gexp-native-inputs): New procedure.
(gexp->sexp*): Add 'target' parameter.
("ungexp + ungexp-native",
"input list + ungexp-native",
"input list splicing + ungexp-native-splicing",
"gexp->derivation, ungexp-native",
"gexp->derivation, ungexp + ungexp-native"): New tests.
("sugar"): Add tests for #+ and #+@.
* doc/guix.texi (G-Expressions): Document 'ungexp-native' et al.
2014-08-18 14:53:10 +02:00
|
|
|
|
|
|
|
|
|
(define gexp-native-inputs
|
2015-03-22 23:17:37 +01:00
|
|
|
|
(cut gexp-inputs <> #:native? #t))
|
2014-04-28 23:00:57 +02:00
|
|
|
|
|
|
|
|
|
(define (gexp-outputs exp)
|
|
|
|
|
"Return the outputs referred to by EXP as a list of strings."
|
|
|
|
|
(define (add-reference-output ref result)
|
|
|
|
|
(match ref
|
2015-03-16 22:31:14 +01:00
|
|
|
|
(($ <gexp-output> name)
|
2014-04-28 23:00:57 +02:00
|
|
|
|
(cons name result))
|
2015-03-11 23:20:50 +01:00
|
|
|
|
(($ <gexp-input> (? gexp? exp))
|
2014-04-28 23:00:57 +02:00
|
|
|
|
(append (gexp-outputs exp) result))
|
2015-03-11 23:20:50 +01:00
|
|
|
|
(($ <gexp-input> (lst ...) output native?)
|
|
|
|
|
;; XXX: Automatically convert LST.
|
2015-03-15 21:45:37 +01:00
|
|
|
|
(add-reference-output (map (match-lambda
|
|
|
|
|
((? gexp-input? x) x)
|
|
|
|
|
(x (%gexp-input x "out" native?)))
|
|
|
|
|
lst)
|
2015-03-11 23:20:50 +01:00
|
|
|
|
result))
|
2015-02-27 22:05:40 +01:00
|
|
|
|
((lst ...)
|
|
|
|
|
(fold-right add-reference-output result lst))
|
2014-04-28 23:00:57 +02:00
|
|
|
|
(_
|
|
|
|
|
result)))
|
|
|
|
|
|
2015-03-02 16:26:13 +01:00
|
|
|
|
(delete-duplicates
|
|
|
|
|
(add-reference-output (gexp-references exp) '())))
|
2014-04-28 23:00:57 +02:00
|
|
|
|
|
2014-08-17 21:20:11 +02:00
|
|
|
|
(define* (gexp->sexp exp #:key
|
|
|
|
|
(system (%current-system))
|
|
|
|
|
(target (%current-target-system)))
|
2014-04-28 23:00:57 +02:00
|
|
|
|
"Return (monadically) the sexp corresponding to EXP for the given OUTPUT,
|
|
|
|
|
and in the current monad setting (system type, etc.)"
|
gexp: Add 'ungexp-native' and 'ungexp-native-splicing'.
* guix/gexp.scm (<gexp>)[natives]: New field.
(write-gexp): Use both 'gexp-references' and
'gexp-native-references'.
(gexp->derivation): Use both 'gexp-inputs' and 'gexp-native-inputs',
and append them.
(gexp-inputs): Add 'references' parameter and honor it.
(gexp-native-inputs): New procedure.
(gexp->sexp)[reference->sexp]: Add 'native?' parameter and honor it.
Use it, and use 'gexp-native-references'.
(gexp)[collect-native-escapes]: New procedure.
[escape->ref]: Handle 'ungexp-native' and 'ungexp-native-splicing'.
[substitute-ungexp, substitute-ungexp-splicing]: New procedures.
[substitute-references]: Use them, and handle 'ungexp-native' and
'ungexp-native-splicing'.
Adjust generated 'make-gexp' call to provide both normal references
and native references.
[read-ungexp]: Support 'ungexp-native' and
'ungexp-native-splicing'.
Add reader extension for #+.
* tests/gexp.scm (gexp-native-inputs): New procedure.
(gexp->sexp*): Add 'target' parameter.
("ungexp + ungexp-native",
"input list + ungexp-native",
"input list splicing + ungexp-native-splicing",
"gexp->derivation, ungexp-native",
"gexp->derivation, ungexp + ungexp-native"): New tests.
("sugar"): Add tests for #+ and #+@.
* doc/guix.texi (G-Expressions): Document 'ungexp-native' et al.
2014-08-18 14:53:10 +02:00
|
|
|
|
(define* (reference->sexp ref #:optional native?)
|
2014-04-28 23:00:57 +02:00
|
|
|
|
(with-monad %store-monad
|
|
|
|
|
(match ref
|
2015-03-16 22:31:14 +01:00
|
|
|
|
(($ <gexp-output> output)
|
2014-04-29 17:58:34 +02:00
|
|
|
|
;; Output file names are not known in advance but the daemon defines
|
|
|
|
|
;; an environment variable for each of them at build time, so use
|
|
|
|
|
;; that trick.
|
|
|
|
|
(return `((@ (guile) getenv) ,output)))
|
2015-03-11 23:20:50 +01:00
|
|
|
|
(($ <gexp-input> (? gexp? exp) output n?)
|
gexp: Add 'ungexp-native' and 'ungexp-native-splicing'.
* guix/gexp.scm (<gexp>)[natives]: New field.
(write-gexp): Use both 'gexp-references' and
'gexp-native-references'.
(gexp->derivation): Use both 'gexp-inputs' and 'gexp-native-inputs',
and append them.
(gexp-inputs): Add 'references' parameter and honor it.
(gexp-native-inputs): New procedure.
(gexp->sexp)[reference->sexp]: Add 'native?' parameter and honor it.
Use it, and use 'gexp-native-references'.
(gexp)[collect-native-escapes]: New procedure.
[escape->ref]: Handle 'ungexp-native' and 'ungexp-native-splicing'.
[substitute-ungexp, substitute-ungexp-splicing]: New procedures.
[substitute-references]: Use them, and handle 'ungexp-native' and
'ungexp-native-splicing'.
Adjust generated 'make-gexp' call to provide both normal references
and native references.
[read-ungexp]: Support 'ungexp-native' and
'ungexp-native-splicing'.
Add reader extension for #+.
* tests/gexp.scm (gexp-native-inputs): New procedure.
(gexp->sexp*): Add 'target' parameter.
("ungexp + ungexp-native",
"input list + ungexp-native",
"input list splicing + ungexp-native-splicing",
"gexp->derivation, ungexp-native",
"gexp->derivation, ungexp + ungexp-native"): New tests.
("sugar"): Add tests for #+ and #+@.
* doc/guix.texi (G-Expressions): Document 'ungexp-native' et al.
2014-08-18 14:53:10 +02:00
|
|
|
|
(gexp->sexp exp
|
|
|
|
|
#:system system
|
2015-03-11 23:20:50 +01:00
|
|
|
|
#:target (if (or n? native?) #f target)))
|
|
|
|
|
(($ <gexp-input> (refs ...) output n?)
|
2017-06-25 15:33:58 +02:00
|
|
|
|
(mapm %store-monad
|
|
|
|
|
(lambda (ref)
|
|
|
|
|
;; XXX: Automatically convert REF to an gexp-input.
|
|
|
|
|
(reference->sexp
|
|
|
|
|
(if (gexp-input? ref)
|
|
|
|
|
ref
|
|
|
|
|
(%gexp-input ref "out" n?))
|
|
|
|
|
(or n? native?)))
|
|
|
|
|
refs))
|
2015-03-15 23:27:34 +01:00
|
|
|
|
(($ <gexp-input> (? struct? thing) output n?)
|
2017-11-14 17:10:17 +01:00
|
|
|
|
(let ((target (if (or n? native?) #f target)))
|
|
|
|
|
(lower+expand-object thing system
|
|
|
|
|
#:target target
|
|
|
|
|
#:output output)))
|
2019-09-23 22:17:39 +02:00
|
|
|
|
(($ <gexp-input> (? self-quoting? x))
|
2015-03-11 23:20:50 +01:00
|
|
|
|
(return x))
|
2019-09-23 22:17:39 +02:00
|
|
|
|
(($ <gexp-input> x)
|
|
|
|
|
(raise (condition (&gexp-input-error (input x)))))
|
2014-04-28 23:00:57 +02:00
|
|
|
|
(x
|
|
|
|
|
(return x)))))
|
|
|
|
|
|
|
|
|
|
(mlet %store-monad
|
2017-06-25 15:33:58 +02:00
|
|
|
|
((args (mapm %store-monad
|
|
|
|
|
reference->sexp (gexp-references exp))))
|
2014-04-28 23:00:57 +02:00
|
|
|
|
(return (apply (gexp-proc exp) args))))
|
|
|
|
|
|
2019-02-06 21:58:43 +01:00
|
|
|
|
(define-syntax-rule (define-syntax-parameter-once name proc)
|
|
|
|
|
;; Like 'define-syntax-parameter' but ensure the top-level binding for NAME
|
|
|
|
|
;; does not get redefined. This works around a race condition in a
|
|
|
|
|
;; multi-threaded context with Guile <= 2.2.4: <https://bugs.gnu.org/27476>.
|
|
|
|
|
(eval-when (load eval expand compile)
|
|
|
|
|
(define name
|
|
|
|
|
(if (module-locally-bound? (current-module) 'name)
|
|
|
|
|
(module-ref (current-module) 'name)
|
|
|
|
|
(make-syntax-transformer 'name 'syntax-parameter
|
|
|
|
|
(list proc))))))
|
|
|
|
|
|
|
|
|
|
(define-syntax-parameter-once current-imported-modules
|
2016-07-03 22:26:19 +02:00
|
|
|
|
;; Current list of imported modules.
|
|
|
|
|
(identifier-syntax '()))
|
|
|
|
|
|
|
|
|
|
(define-syntax-rule (with-imported-modules modules body ...)
|
|
|
|
|
"Mark the gexps defined in BODY... as requiring MODULES in their execution
|
|
|
|
|
environment."
|
|
|
|
|
(syntax-parameterize ((current-imported-modules
|
|
|
|
|
(identifier-syntax modules)))
|
|
|
|
|
body ...))
|
|
|
|
|
|
2019-02-06 21:58:43 +01:00
|
|
|
|
(define-syntax-parameter-once current-imported-extensions
|
2018-05-28 18:14:37 +02:00
|
|
|
|
;; Current list of extensions.
|
|
|
|
|
(identifier-syntax '()))
|
|
|
|
|
|
|
|
|
|
(define-syntax-rule (with-extensions extensions body ...)
|
|
|
|
|
"Mark the gexps defined in BODY... as requiring EXTENSIONS in their
|
|
|
|
|
execution environment."
|
|
|
|
|
(syntax-parameterize ((current-imported-extensions
|
|
|
|
|
(identifier-syntax extensions)))
|
|
|
|
|
body ...))
|
|
|
|
|
|
2014-04-28 23:00:57 +02:00
|
|
|
|
(define-syntax gexp
|
|
|
|
|
(lambda (s)
|
|
|
|
|
(define (collect-escapes exp)
|
|
|
|
|
;; Return all the 'ungexp' present in EXP.
|
|
|
|
|
(let loop ((exp exp)
|
|
|
|
|
(result '()))
|
2015-03-22 23:09:43 +01:00
|
|
|
|
(syntax-case exp (ungexp
|
|
|
|
|
ungexp-splicing
|
|
|
|
|
ungexp-native
|
|
|
|
|
ungexp-native-splicing)
|
2014-04-28 23:00:57 +02:00
|
|
|
|
((ungexp _)
|
|
|
|
|
(cons exp result))
|
|
|
|
|
((ungexp _ _)
|
|
|
|
|
(cons exp result))
|
|
|
|
|
((ungexp-splicing _ ...)
|
|
|
|
|
(cons exp result))
|
2015-03-22 23:09:43 +01:00
|
|
|
|
((ungexp-native _ ...)
|
gexp: Add 'ungexp-native' and 'ungexp-native-splicing'.
* guix/gexp.scm (<gexp>)[natives]: New field.
(write-gexp): Use both 'gexp-references' and
'gexp-native-references'.
(gexp->derivation): Use both 'gexp-inputs' and 'gexp-native-inputs',
and append them.
(gexp-inputs): Add 'references' parameter and honor it.
(gexp-native-inputs): New procedure.
(gexp->sexp)[reference->sexp]: Add 'native?' parameter and honor it.
Use it, and use 'gexp-native-references'.
(gexp)[collect-native-escapes]: New procedure.
[escape->ref]: Handle 'ungexp-native' and 'ungexp-native-splicing'.
[substitute-ungexp, substitute-ungexp-splicing]: New procedures.
[substitute-references]: Use them, and handle 'ungexp-native' and
'ungexp-native-splicing'.
Adjust generated 'make-gexp' call to provide both normal references
and native references.
[read-ungexp]: Support 'ungexp-native' and
'ungexp-native-splicing'.
Add reader extension for #+.
* tests/gexp.scm (gexp-native-inputs): New procedure.
(gexp->sexp*): Add 'target' parameter.
("ungexp + ungexp-native",
"input list + ungexp-native",
"input list splicing + ungexp-native-splicing",
"gexp->derivation, ungexp-native",
"gexp->derivation, ungexp + ungexp-native"): New tests.
("sugar"): Add tests for #+ and #+@.
* doc/guix.texi (G-Expressions): Document 'ungexp-native' et al.
2014-08-18 14:53:10 +02:00
|
|
|
|
(cons exp result))
|
|
|
|
|
((ungexp-native-splicing _ ...)
|
|
|
|
|
(cons exp result))
|
2017-01-01 22:22:14 +01:00
|
|
|
|
((exp0 . exp)
|
gexp: Add 'ungexp-native' and 'ungexp-native-splicing'.
* guix/gexp.scm (<gexp>)[natives]: New field.
(write-gexp): Use both 'gexp-references' and
'gexp-native-references'.
(gexp->derivation): Use both 'gexp-inputs' and 'gexp-native-inputs',
and append them.
(gexp-inputs): Add 'references' parameter and honor it.
(gexp-native-inputs): New procedure.
(gexp->sexp)[reference->sexp]: Add 'native?' parameter and honor it.
Use it, and use 'gexp-native-references'.
(gexp)[collect-native-escapes]: New procedure.
[escape->ref]: Handle 'ungexp-native' and 'ungexp-native-splicing'.
[substitute-ungexp, substitute-ungexp-splicing]: New procedures.
[substitute-references]: Use them, and handle 'ungexp-native' and
'ungexp-native-splicing'.
Adjust generated 'make-gexp' call to provide both normal references
and native references.
[read-ungexp]: Support 'ungexp-native' and
'ungexp-native-splicing'.
Add reader extension for #+.
* tests/gexp.scm (gexp-native-inputs): New procedure.
(gexp->sexp*): Add 'target' parameter.
("ungexp + ungexp-native",
"input list + ungexp-native",
"input list splicing + ungexp-native-splicing",
"gexp->derivation, ungexp-native",
"gexp->derivation, ungexp + ungexp-native"): New tests.
("sugar"): Add tests for #+ and #+@.
* doc/guix.texi (G-Expressions): Document 'ungexp-native' et al.
2014-08-18 14:53:10 +02:00
|
|
|
|
(let ((result (loop #'exp0 result)))
|
2017-01-01 22:22:14 +01:00
|
|
|
|
(loop #'exp result)))
|
gexp: Add 'ungexp-native' and 'ungexp-native-splicing'.
* guix/gexp.scm (<gexp>)[natives]: New field.
(write-gexp): Use both 'gexp-references' and
'gexp-native-references'.
(gexp->derivation): Use both 'gexp-inputs' and 'gexp-native-inputs',
and append them.
(gexp-inputs): Add 'references' parameter and honor it.
(gexp-native-inputs): New procedure.
(gexp->sexp)[reference->sexp]: Add 'native?' parameter and honor it.
Use it, and use 'gexp-native-references'.
(gexp)[collect-native-escapes]: New procedure.
[escape->ref]: Handle 'ungexp-native' and 'ungexp-native-splicing'.
[substitute-ungexp, substitute-ungexp-splicing]: New procedures.
[substitute-references]: Use them, and handle 'ungexp-native' and
'ungexp-native-splicing'.
Adjust generated 'make-gexp' call to provide both normal references
and native references.
[read-ungexp]: Support 'ungexp-native' and
'ungexp-native-splicing'.
Add reader extension for #+.
* tests/gexp.scm (gexp-native-inputs): New procedure.
(gexp->sexp*): Add 'target' parameter.
("ungexp + ungexp-native",
"input list + ungexp-native",
"input list splicing + ungexp-native-splicing",
"gexp->derivation, ungexp-native",
"gexp->derivation, ungexp + ungexp-native"): New tests.
("sugar"): Add tests for #+ and #+@.
* doc/guix.texi (G-Expressions): Document 'ungexp-native' et al.
2014-08-18 14:53:10 +02:00
|
|
|
|
(_
|
|
|
|
|
result))))
|
|
|
|
|
|
2014-04-28 23:00:57 +02:00
|
|
|
|
(define (escape->ref exp)
|
|
|
|
|
;; Turn 'ungexp' form EXP into a "reference".
|
gexp: Add 'ungexp-native' and 'ungexp-native-splicing'.
* guix/gexp.scm (<gexp>)[natives]: New field.
(write-gexp): Use both 'gexp-references' and
'gexp-native-references'.
(gexp->derivation): Use both 'gexp-inputs' and 'gexp-native-inputs',
and append them.
(gexp-inputs): Add 'references' parameter and honor it.
(gexp-native-inputs): New procedure.
(gexp->sexp)[reference->sexp]: Add 'native?' parameter and honor it.
Use it, and use 'gexp-native-references'.
(gexp)[collect-native-escapes]: New procedure.
[escape->ref]: Handle 'ungexp-native' and 'ungexp-native-splicing'.
[substitute-ungexp, substitute-ungexp-splicing]: New procedures.
[substitute-references]: Use them, and handle 'ungexp-native' and
'ungexp-native-splicing'.
Adjust generated 'make-gexp' call to provide both normal references
and native references.
[read-ungexp]: Support 'ungexp-native' and
'ungexp-native-splicing'.
Add reader extension for #+.
* tests/gexp.scm (gexp-native-inputs): New procedure.
(gexp->sexp*): Add 'target' parameter.
("ungexp + ungexp-native",
"input list + ungexp-native",
"input list splicing + ungexp-native-splicing",
"gexp->derivation, ungexp-native",
"gexp->derivation, ungexp + ungexp-native"): New tests.
("sugar"): Add tests for #+ and #+@.
* doc/guix.texi (G-Expressions): Document 'ungexp-native' et al.
2014-08-18 14:53:10 +02:00
|
|
|
|
(syntax-case exp (ungexp ungexp-splicing
|
|
|
|
|
ungexp-native ungexp-native-splicing
|
|
|
|
|
output)
|
2014-04-28 23:00:57 +02:00
|
|
|
|
((ungexp output)
|
2015-03-16 22:31:14 +01:00
|
|
|
|
#'(gexp-output "out"))
|
2014-04-28 23:00:57 +02:00
|
|
|
|
((ungexp output name)
|
2015-03-16 22:31:14 +01:00
|
|
|
|
#'(gexp-output name))
|
2014-04-28 23:00:57 +02:00
|
|
|
|
((ungexp thing)
|
2015-03-15 21:45:37 +01:00
|
|
|
|
#'(%gexp-input thing "out" #f))
|
2014-04-28 23:00:57 +02:00
|
|
|
|
((ungexp drv-or-pkg out)
|
2015-03-15 21:45:37 +01:00
|
|
|
|
#'(%gexp-input drv-or-pkg out #f))
|
2014-04-28 23:00:57 +02:00
|
|
|
|
((ungexp-splicing lst)
|
2015-03-15 21:45:37 +01:00
|
|
|
|
#'(%gexp-input lst "out" #f))
|
gexp: Add 'ungexp-native' and 'ungexp-native-splicing'.
* guix/gexp.scm (<gexp>)[natives]: New field.
(write-gexp): Use both 'gexp-references' and
'gexp-native-references'.
(gexp->derivation): Use both 'gexp-inputs' and 'gexp-native-inputs',
and append them.
(gexp-inputs): Add 'references' parameter and honor it.
(gexp-native-inputs): New procedure.
(gexp->sexp)[reference->sexp]: Add 'native?' parameter and honor it.
Use it, and use 'gexp-native-references'.
(gexp)[collect-native-escapes]: New procedure.
[escape->ref]: Handle 'ungexp-native' and 'ungexp-native-splicing'.
[substitute-ungexp, substitute-ungexp-splicing]: New procedures.
[substitute-references]: Use them, and handle 'ungexp-native' and
'ungexp-native-splicing'.
Adjust generated 'make-gexp' call to provide both normal references
and native references.
[read-ungexp]: Support 'ungexp-native' and
'ungexp-native-splicing'.
Add reader extension for #+.
* tests/gexp.scm (gexp-native-inputs): New procedure.
(gexp->sexp*): Add 'target' parameter.
("ungexp + ungexp-native",
"input list + ungexp-native",
"input list splicing + ungexp-native-splicing",
"gexp->derivation, ungexp-native",
"gexp->derivation, ungexp + ungexp-native"): New tests.
("sugar"): Add tests for #+ and #+@.
* doc/guix.texi (G-Expressions): Document 'ungexp-native' et al.
2014-08-18 14:53:10 +02:00
|
|
|
|
((ungexp-native thing)
|
2015-03-15 21:45:37 +01:00
|
|
|
|
#'(%gexp-input thing "out" #t))
|
gexp: Add 'ungexp-native' and 'ungexp-native-splicing'.
* guix/gexp.scm (<gexp>)[natives]: New field.
(write-gexp): Use both 'gexp-references' and
'gexp-native-references'.
(gexp->derivation): Use both 'gexp-inputs' and 'gexp-native-inputs',
and append them.
(gexp-inputs): Add 'references' parameter and honor it.
(gexp-native-inputs): New procedure.
(gexp->sexp)[reference->sexp]: Add 'native?' parameter and honor it.
Use it, and use 'gexp-native-references'.
(gexp)[collect-native-escapes]: New procedure.
[escape->ref]: Handle 'ungexp-native' and 'ungexp-native-splicing'.
[substitute-ungexp, substitute-ungexp-splicing]: New procedures.
[substitute-references]: Use them, and handle 'ungexp-native' and
'ungexp-native-splicing'.
Adjust generated 'make-gexp' call to provide both normal references
and native references.
[read-ungexp]: Support 'ungexp-native' and
'ungexp-native-splicing'.
Add reader extension for #+.
* tests/gexp.scm (gexp-native-inputs): New procedure.
(gexp->sexp*): Add 'target' parameter.
("ungexp + ungexp-native",
"input list + ungexp-native",
"input list splicing + ungexp-native-splicing",
"gexp->derivation, ungexp-native",
"gexp->derivation, ungexp + ungexp-native"): New tests.
("sugar"): Add tests for #+ and #+@.
* doc/guix.texi (G-Expressions): Document 'ungexp-native' et al.
2014-08-18 14:53:10 +02:00
|
|
|
|
((ungexp-native drv-or-pkg out)
|
2015-03-15 21:45:37 +01:00
|
|
|
|
#'(%gexp-input drv-or-pkg out #t))
|
gexp: Add 'ungexp-native' and 'ungexp-native-splicing'.
* guix/gexp.scm (<gexp>)[natives]: New field.
(write-gexp): Use both 'gexp-references' and
'gexp-native-references'.
(gexp->derivation): Use both 'gexp-inputs' and 'gexp-native-inputs',
and append them.
(gexp-inputs): Add 'references' parameter and honor it.
(gexp-native-inputs): New procedure.
(gexp->sexp)[reference->sexp]: Add 'native?' parameter and honor it.
Use it, and use 'gexp-native-references'.
(gexp)[collect-native-escapes]: New procedure.
[escape->ref]: Handle 'ungexp-native' and 'ungexp-native-splicing'.
[substitute-ungexp, substitute-ungexp-splicing]: New procedures.
[substitute-references]: Use them, and handle 'ungexp-native' and
'ungexp-native-splicing'.
Adjust generated 'make-gexp' call to provide both normal references
and native references.
[read-ungexp]: Support 'ungexp-native' and
'ungexp-native-splicing'.
Add reader extension for #+.
* tests/gexp.scm (gexp-native-inputs): New procedure.
(gexp->sexp*): Add 'target' parameter.
("ungexp + ungexp-native",
"input list + ungexp-native",
"input list splicing + ungexp-native-splicing",
"gexp->derivation, ungexp-native",
"gexp->derivation, ungexp + ungexp-native"): New tests.
("sugar"): Add tests for #+ and #+@.
* doc/guix.texi (G-Expressions): Document 'ungexp-native' et al.
2014-08-18 14:53:10 +02:00
|
|
|
|
((ungexp-native-splicing lst)
|
2015-03-15 21:45:37 +01:00
|
|
|
|
#'(%gexp-input lst "out" #t))))
|
2014-04-28 23:00:57 +02:00
|
|
|
|
|
gexp: Add 'ungexp-native' and 'ungexp-native-splicing'.
* guix/gexp.scm (<gexp>)[natives]: New field.
(write-gexp): Use both 'gexp-references' and
'gexp-native-references'.
(gexp->derivation): Use both 'gexp-inputs' and 'gexp-native-inputs',
and append them.
(gexp-inputs): Add 'references' parameter and honor it.
(gexp-native-inputs): New procedure.
(gexp->sexp)[reference->sexp]: Add 'native?' parameter and honor it.
Use it, and use 'gexp-native-references'.
(gexp)[collect-native-escapes]: New procedure.
[escape->ref]: Handle 'ungexp-native' and 'ungexp-native-splicing'.
[substitute-ungexp, substitute-ungexp-splicing]: New procedures.
[substitute-references]: Use them, and handle 'ungexp-native' and
'ungexp-native-splicing'.
Adjust generated 'make-gexp' call to provide both normal references
and native references.
[read-ungexp]: Support 'ungexp-native' and
'ungexp-native-splicing'.
Add reader extension for #+.
* tests/gexp.scm (gexp-native-inputs): New procedure.
(gexp->sexp*): Add 'target' parameter.
("ungexp + ungexp-native",
"input list + ungexp-native",
"input list splicing + ungexp-native-splicing",
"gexp->derivation, ungexp-native",
"gexp->derivation, ungexp + ungexp-native"): New tests.
("sugar"): Add tests for #+ and #+@.
* doc/guix.texi (G-Expressions): Document 'ungexp-native' et al.
2014-08-18 14:53:10 +02:00
|
|
|
|
(define (substitute-ungexp exp substs)
|
|
|
|
|
;; Given EXP, an 'ungexp' or 'ungexp-native' form, substitute it with
|
|
|
|
|
;; the corresponding form in SUBSTS.
|
|
|
|
|
(match (assoc exp substs)
|
|
|
|
|
((_ id)
|
|
|
|
|
id)
|
2017-01-01 18:17:29 +01:00
|
|
|
|
(_ ;internal error
|
|
|
|
|
(with-syntax ((exp exp))
|
|
|
|
|
#'(syntax-error "error: no 'ungexp' substitution" exp)))))
|
gexp: Add 'ungexp-native' and 'ungexp-native-splicing'.
* guix/gexp.scm (<gexp>)[natives]: New field.
(write-gexp): Use both 'gexp-references' and
'gexp-native-references'.
(gexp->derivation): Use both 'gexp-inputs' and 'gexp-native-inputs',
and append them.
(gexp-inputs): Add 'references' parameter and honor it.
(gexp-native-inputs): New procedure.
(gexp->sexp)[reference->sexp]: Add 'native?' parameter and honor it.
Use it, and use 'gexp-native-references'.
(gexp)[collect-native-escapes]: New procedure.
[escape->ref]: Handle 'ungexp-native' and 'ungexp-native-splicing'.
[substitute-ungexp, substitute-ungexp-splicing]: New procedures.
[substitute-references]: Use them, and handle 'ungexp-native' and
'ungexp-native-splicing'.
Adjust generated 'make-gexp' call to provide both normal references
and native references.
[read-ungexp]: Support 'ungexp-native' and
'ungexp-native-splicing'.
Add reader extension for #+.
* tests/gexp.scm (gexp-native-inputs): New procedure.
(gexp->sexp*): Add 'target' parameter.
("ungexp + ungexp-native",
"input list + ungexp-native",
"input list splicing + ungexp-native-splicing",
"gexp->derivation, ungexp-native",
"gexp->derivation, ungexp + ungexp-native"): New tests.
("sugar"): Add tests for #+ and #+@.
* doc/guix.texi (G-Expressions): Document 'ungexp-native' et al.
2014-08-18 14:53:10 +02:00
|
|
|
|
|
|
|
|
|
(define (substitute-ungexp-splicing exp substs)
|
|
|
|
|
(syntax-case exp ()
|
|
|
|
|
((exp rest ...)
|
|
|
|
|
(match (assoc #'exp substs)
|
|
|
|
|
((_ id)
|
|
|
|
|
(with-syntax ((id id))
|
|
|
|
|
#`(append id
|
|
|
|
|
#,(substitute-references #'(rest ...) substs))))
|
|
|
|
|
(_
|
|
|
|
|
#'(syntax-error "error: no 'ungexp-splicing' substitution"
|
2017-01-01 18:17:29 +01:00
|
|
|
|
exp))))))
|
gexp: Add 'ungexp-native' and 'ungexp-native-splicing'.
* guix/gexp.scm (<gexp>)[natives]: New field.
(write-gexp): Use both 'gexp-references' and
'gexp-native-references'.
(gexp->derivation): Use both 'gexp-inputs' and 'gexp-native-inputs',
and append them.
(gexp-inputs): Add 'references' parameter and honor it.
(gexp-native-inputs): New procedure.
(gexp->sexp)[reference->sexp]: Add 'native?' parameter and honor it.
Use it, and use 'gexp-native-references'.
(gexp)[collect-native-escapes]: New procedure.
[escape->ref]: Handle 'ungexp-native' and 'ungexp-native-splicing'.
[substitute-ungexp, substitute-ungexp-splicing]: New procedures.
[substitute-references]: Use them, and handle 'ungexp-native' and
'ungexp-native-splicing'.
Adjust generated 'make-gexp' call to provide both normal references
and native references.
[read-ungexp]: Support 'ungexp-native' and
'ungexp-native-splicing'.
Add reader extension for #+.
* tests/gexp.scm (gexp-native-inputs): New procedure.
(gexp->sexp*): Add 'target' parameter.
("ungexp + ungexp-native",
"input list + ungexp-native",
"input list splicing + ungexp-native-splicing",
"gexp->derivation, ungexp-native",
"gexp->derivation, ungexp + ungexp-native"): New tests.
("sugar"): Add tests for #+ and #+@.
* doc/guix.texi (G-Expressions): Document 'ungexp-native' et al.
2014-08-18 14:53:10 +02:00
|
|
|
|
|
2014-04-28 23:00:57 +02:00
|
|
|
|
(define (substitute-references exp substs)
|
|
|
|
|
;; Return a variant of EXP where all the cars of SUBSTS have been
|
|
|
|
|
;; replaced by the corresponding cdr.
|
gexp: Add 'ungexp-native' and 'ungexp-native-splicing'.
* guix/gexp.scm (<gexp>)[natives]: New field.
(write-gexp): Use both 'gexp-references' and
'gexp-native-references'.
(gexp->derivation): Use both 'gexp-inputs' and 'gexp-native-inputs',
and append them.
(gexp-inputs): Add 'references' parameter and honor it.
(gexp-native-inputs): New procedure.
(gexp->sexp)[reference->sexp]: Add 'native?' parameter and honor it.
Use it, and use 'gexp-native-references'.
(gexp)[collect-native-escapes]: New procedure.
[escape->ref]: Handle 'ungexp-native' and 'ungexp-native-splicing'.
[substitute-ungexp, substitute-ungexp-splicing]: New procedures.
[substitute-references]: Use them, and handle 'ungexp-native' and
'ungexp-native-splicing'.
Adjust generated 'make-gexp' call to provide both normal references
and native references.
[read-ungexp]: Support 'ungexp-native' and
'ungexp-native-splicing'.
Add reader extension for #+.
* tests/gexp.scm (gexp-native-inputs): New procedure.
(gexp->sexp*): Add 'target' parameter.
("ungexp + ungexp-native",
"input list + ungexp-native",
"input list splicing + ungexp-native-splicing",
"gexp->derivation, ungexp-native",
"gexp->derivation, ungexp + ungexp-native"): New tests.
("sugar"): Add tests for #+ and #+@.
* doc/guix.texi (G-Expressions): Document 'ungexp-native' et al.
2014-08-18 14:53:10 +02:00
|
|
|
|
(syntax-case exp (ungexp ungexp-native
|
|
|
|
|
ungexp-splicing ungexp-native-splicing)
|
2014-04-28 23:00:57 +02:00
|
|
|
|
((ungexp _ ...)
|
gexp: Add 'ungexp-native' and 'ungexp-native-splicing'.
* guix/gexp.scm (<gexp>)[natives]: New field.
(write-gexp): Use both 'gexp-references' and
'gexp-native-references'.
(gexp->derivation): Use both 'gexp-inputs' and 'gexp-native-inputs',
and append them.
(gexp-inputs): Add 'references' parameter and honor it.
(gexp-native-inputs): New procedure.
(gexp->sexp)[reference->sexp]: Add 'native?' parameter and honor it.
Use it, and use 'gexp-native-references'.
(gexp)[collect-native-escapes]: New procedure.
[escape->ref]: Handle 'ungexp-native' and 'ungexp-native-splicing'.
[substitute-ungexp, substitute-ungexp-splicing]: New procedures.
[substitute-references]: Use them, and handle 'ungexp-native' and
'ungexp-native-splicing'.
Adjust generated 'make-gexp' call to provide both normal references
and native references.
[read-ungexp]: Support 'ungexp-native' and
'ungexp-native-splicing'.
Add reader extension for #+.
* tests/gexp.scm (gexp-native-inputs): New procedure.
(gexp->sexp*): Add 'target' parameter.
("ungexp + ungexp-native",
"input list + ungexp-native",
"input list splicing + ungexp-native-splicing",
"gexp->derivation, ungexp-native",
"gexp->derivation, ungexp + ungexp-native"): New tests.
("sugar"): Add tests for #+ and #+@.
* doc/guix.texi (G-Expressions): Document 'ungexp-native' et al.
2014-08-18 14:53:10 +02:00
|
|
|
|
(substitute-ungexp exp substs))
|
|
|
|
|
((ungexp-native _ ...)
|
|
|
|
|
(substitute-ungexp exp substs))
|
2014-04-28 23:00:57 +02:00
|
|
|
|
(((ungexp-splicing _ ...) rest ...)
|
gexp: Add 'ungexp-native' and 'ungexp-native-splicing'.
* guix/gexp.scm (<gexp>)[natives]: New field.
(write-gexp): Use both 'gexp-references' and
'gexp-native-references'.
(gexp->derivation): Use both 'gexp-inputs' and 'gexp-native-inputs',
and append them.
(gexp-inputs): Add 'references' parameter and honor it.
(gexp-native-inputs): New procedure.
(gexp->sexp)[reference->sexp]: Add 'native?' parameter and honor it.
Use it, and use 'gexp-native-references'.
(gexp)[collect-native-escapes]: New procedure.
[escape->ref]: Handle 'ungexp-native' and 'ungexp-native-splicing'.
[substitute-ungexp, substitute-ungexp-splicing]: New procedures.
[substitute-references]: Use them, and handle 'ungexp-native' and
'ungexp-native-splicing'.
Adjust generated 'make-gexp' call to provide both normal references
and native references.
[read-ungexp]: Support 'ungexp-native' and
'ungexp-native-splicing'.
Add reader extension for #+.
* tests/gexp.scm (gexp-native-inputs): New procedure.
(gexp->sexp*): Add 'target' parameter.
("ungexp + ungexp-native",
"input list + ungexp-native",
"input list splicing + ungexp-native-splicing",
"gexp->derivation, ungexp-native",
"gexp->derivation, ungexp + ungexp-native"): New tests.
("sugar"): Add tests for #+ and #+@.
* doc/guix.texi (G-Expressions): Document 'ungexp-native' et al.
2014-08-18 14:53:10 +02:00
|
|
|
|
(substitute-ungexp-splicing exp substs))
|
|
|
|
|
(((ungexp-native-splicing _ ...) rest ...)
|
|
|
|
|
(substitute-ungexp-splicing exp substs))
|
2017-01-01 22:22:14 +01:00
|
|
|
|
((exp0 . exp)
|
2014-04-28 23:00:57 +02:00
|
|
|
|
#`(cons #,(substitute-references #'exp0 substs)
|
2017-01-01 22:22:14 +01:00
|
|
|
|
#,(substitute-references #'exp substs)))
|
2014-04-28 23:00:57 +02:00
|
|
|
|
(x #''x)))
|
|
|
|
|
|
|
|
|
|
(syntax-case s (ungexp output)
|
|
|
|
|
((_ exp)
|
2016-07-02 23:19:40 +02:00
|
|
|
|
(let* ((escapes (delete-duplicates (collect-escapes #'exp)))
|
2014-04-28 23:00:57 +02:00
|
|
|
|
(formals (generate-temporaries escapes))
|
|
|
|
|
(sexp (substitute-references #'exp (zip escapes formals)))
|
2016-07-02 23:19:40 +02:00
|
|
|
|
(refs (map escape->ref escapes)))
|
|
|
|
|
#`(make-gexp (list #,@refs)
|
2016-07-03 22:26:19 +02:00
|
|
|
|
current-imported-modules
|
2018-05-28 18:14:37 +02:00
|
|
|
|
current-imported-extensions
|
2014-04-28 23:00:57 +02:00
|
|
|
|
(lambda #,formals
|
|
|
|
|
#,sexp)))))))
|
|
|
|
|
|
2015-02-13 17:23:17 +01:00
|
|
|
|
|
|
|
|
|
;;;
|
|
|
|
|
;;; Module handling.
|
|
|
|
|
;;;
|
|
|
|
|
|
2015-08-30 22:52:49 +02:00
|
|
|
|
(define %utils-module
|
|
|
|
|
;; This file provides 'mkdir-p', needed to implement 'imported-files' and
|
2016-06-20 23:46:32 +02:00
|
|
|
|
;; other primitives below. Note: We give the file name relative to this
|
|
|
|
|
;; file you are currently reading; 'search-path' could return a file name
|
|
|
|
|
;; relative to the current working directory.
|
|
|
|
|
(local-file "build/utils.scm"
|
2015-08-30 22:52:49 +02:00
|
|
|
|
"build-utils.scm"))
|
2015-02-13 17:23:17 +01:00
|
|
|
|
|
2018-07-16 11:17:55 +02:00
|
|
|
|
(define* (imported-files/derivation files
|
|
|
|
|
#:key (name "file-import")
|
2018-07-16 11:40:34 +02:00
|
|
|
|
(symlink? #f)
|
2018-07-16 11:17:55 +02:00
|
|
|
|
(system (%current-system))
|
2018-07-27 00:09:52 +02:00
|
|
|
|
(guile (%guile-for-build)))
|
2015-02-13 17:23:17 +01:00
|
|
|
|
"Return a derivation that imports FILES into STORE. FILES must be a list
|
2017-03-15 22:14:36 +01:00
|
|
|
|
of (FINAL-PATH . FILE) pairs. Each FILE is mapped to FINAL-PATH in the
|
|
|
|
|
resulting store path. FILE can be either a file name, or a file-like object,
|
2018-07-16 11:40:34 +02:00
|
|
|
|
as returned by 'local-file' for example. If SYMLINK? is true, create symlinks
|
|
|
|
|
to the source files instead of copying them."
|
2015-02-13 17:23:17 +01:00
|
|
|
|
(define file-pair
|
|
|
|
|
(match-lambda
|
2017-03-15 22:14:36 +01:00
|
|
|
|
((final-path . (? string? file-name))
|
2015-02-13 17:23:17 +01:00
|
|
|
|
(mlet %store-monad ((file (interned-file file-name
|
|
|
|
|
(basename final-path))))
|
2017-03-15 22:14:36 +01:00
|
|
|
|
(return (list final-path file))))
|
|
|
|
|
((final-path . file-like)
|
|
|
|
|
(mlet %store-monad ((file (lower-object file-like system)))
|
2015-02-13 17:23:17 +01:00
|
|
|
|
(return (list final-path file))))))
|
|
|
|
|
|
2017-06-25 15:33:58 +02:00
|
|
|
|
(mlet %store-monad ((files (mapm %store-monad file-pair files)))
|
2015-02-13 17:23:17 +01:00
|
|
|
|
(define build
|
|
|
|
|
(gexp
|
|
|
|
|
(begin
|
2015-08-30 22:52:49 +02:00
|
|
|
|
(primitive-load (ungexp %utils-module)) ;for 'mkdir-p'
|
2015-02-13 17:23:17 +01:00
|
|
|
|
(use-modules (ice-9 match))
|
|
|
|
|
|
|
|
|
|
(mkdir (ungexp output)) (chdir (ungexp output))
|
|
|
|
|
(for-each (match-lambda
|
|
|
|
|
((final-path store-path)
|
|
|
|
|
(mkdir-p (dirname final-path))
|
2018-07-16 11:40:34 +02:00
|
|
|
|
((ungexp (if symlink? 'symlink 'copy-file))
|
|
|
|
|
store-path final-path)))
|
2015-02-13 17:23:17 +01:00
|
|
|
|
'(ungexp files)))))
|
|
|
|
|
|
|
|
|
|
;; TODO: Pass FILES as an environment variable so that BUILD remains
|
|
|
|
|
;; exactly the same regardless of FILES: less disk space, and fewer
|
|
|
|
|
;; 'add-to-store' RPCs.
|
|
|
|
|
(gexp->derivation name build
|
|
|
|
|
#:system system
|
|
|
|
|
#:guile-for-build guile
|
2018-05-15 10:34:45 +02:00
|
|
|
|
#:local-build? #t
|
2020-05-25 22:58:31 +02:00
|
|
|
|
#:substitutable? #f
|
2018-05-15 10:34:45 +02:00
|
|
|
|
|
2018-07-27 00:09:52 +02:00
|
|
|
|
;; Avoid deprecation warnings about the use of the _IO*
|
|
|
|
|
;; constants in (guix build utils).
|
2018-05-15 10:34:45 +02:00
|
|
|
|
#:env-vars
|
2018-07-27 00:09:52 +02:00
|
|
|
|
'(("GUILE_WARN_DEPRECATED" . "no")))))
|
2015-02-13 17:23:17 +01:00
|
|
|
|
|
2018-07-16 11:17:55 +02:00
|
|
|
|
(define* (imported-files files
|
|
|
|
|
#:key (name "file-import")
|
|
|
|
|
;; The following parameters make sense when creating
|
|
|
|
|
;; an actual derivation.
|
|
|
|
|
(system (%current-system))
|
2018-07-27 00:09:52 +02:00
|
|
|
|
(guile (%guile-for-build)))
|
2018-07-16 11:17:55 +02:00
|
|
|
|
"Import FILES into the store and return the resulting derivation or store
|
|
|
|
|
file name (a derivation is created if and only if some elements of FILES are
|
|
|
|
|
file-like objects and not local file names.) FILES must be a list
|
|
|
|
|
of (FINAL-PATH . FILE) pairs. Each FILE is mapped to FINAL-PATH in the
|
|
|
|
|
resulting store path. FILE can be either a file name, or a file-like object,
|
|
|
|
|
as returned by 'local-file' for example."
|
2018-07-26 22:59:49 +02:00
|
|
|
|
(if (any (match-lambda
|
|
|
|
|
((_ . (? struct? source)) #t)
|
|
|
|
|
(_ #f))
|
|
|
|
|
files)
|
2018-07-16 11:17:55 +02:00
|
|
|
|
(imported-files/derivation files #:name name
|
2018-07-16 11:40:34 +02:00
|
|
|
|
#:symlink? derivation?
|
2018-07-27 00:09:52 +02:00
|
|
|
|
#:system system #:guile guile)
|
2018-07-16 11:17:55 +02:00
|
|
|
|
(interned-file-tree `(,name directory
|
|
|
|
|
,@(file-mapping->tree files)))))
|
|
|
|
|
|
2015-02-13 17:23:17 +01:00
|
|
|
|
(define* (imported-modules modules
|
|
|
|
|
#:key (name "module-import")
|
|
|
|
|
(system (%current-system))
|
|
|
|
|
(guile (%guile-for-build))
|
2018-07-27 00:09:52 +02:00
|
|
|
|
(module-path %load-path))
|
2015-02-13 17:23:17 +01:00
|
|
|
|
"Return a derivation that contains the source files of MODULES, a list of
|
2017-03-15 22:14:36 +01:00
|
|
|
|
module names such as `(ice-9 q)'. All of MODULES must be either names of
|
|
|
|
|
modules to be found in the MODULE-PATH search path, or a module name followed
|
|
|
|
|
by an arrow followed by a file-like object. For example:
|
|
|
|
|
|
|
|
|
|
(imported-modules `((guix build utils)
|
|
|
|
|
(guix gcrypt)
|
|
|
|
|
((guix config) => ,(scheme-file …))))
|
|
|
|
|
|
|
|
|
|
In this example, the first two modules are taken from MODULE-PATH, and the
|
|
|
|
|
last one is created from the given <scheme-file> object."
|
2018-07-16 10:14:00 +02:00
|
|
|
|
(let ((files (map (match-lambda
|
|
|
|
|
(((module ...) '=> file)
|
|
|
|
|
(cons (module->source-file-name module)
|
|
|
|
|
file))
|
|
|
|
|
((module ...)
|
|
|
|
|
(let ((f (module->source-file-name module)))
|
|
|
|
|
(cons f (search-path* module-path f)))))
|
|
|
|
|
modules)))
|
2018-07-16 11:17:55 +02:00
|
|
|
|
(imported-files files #:name name
|
|
|
|
|
#:system system
|
2018-07-27 00:09:52 +02:00
|
|
|
|
#:guile guile)))
|
2015-02-13 17:23:17 +01:00
|
|
|
|
|
|
|
|
|
(define* (compiled-modules modules
|
|
|
|
|
#:key (name "module-import-compiled")
|
|
|
|
|
(system (%current-system))
|
2019-07-26 23:22:28 +02:00
|
|
|
|
target
|
2015-02-13 17:23:17 +01:00
|
|
|
|
(guile (%guile-for-build))
|
2017-11-29 16:38:13 +01:00
|
|
|
|
(module-path %load-path)
|
2018-05-28 18:14:37 +02:00
|
|
|
|
(extensions '())
|
2019-06-17 15:54:17 +02:00
|
|
|
|
(deprecation-warnings #f))
|
2015-02-13 17:23:17 +01:00
|
|
|
|
"Return a derivation that builds a tree containing the `.go' files
|
|
|
|
|
corresponding to MODULES. All the MODULES are built in a context where
|
2019-07-26 23:22:28 +02:00
|
|
|
|
they can refer to each other. When TARGET is true, cross-compile MODULES for
|
|
|
|
|
TARGET, a GNU triplet."
|
2018-04-01 12:33:28 +02:00
|
|
|
|
(define total (length modules))
|
|
|
|
|
|
2015-02-13 17:23:17 +01:00
|
|
|
|
(mlet %store-monad ((modules (imported-modules modules
|
|
|
|
|
#:system system
|
|
|
|
|
#:guile guile
|
|
|
|
|
#:module-path
|
2018-07-27 00:09:52 +02:00
|
|
|
|
module-path)))
|
2015-02-13 17:23:17 +01:00
|
|
|
|
(define build
|
|
|
|
|
(gexp
|
|
|
|
|
(begin
|
2015-08-30 22:52:49 +02:00
|
|
|
|
(primitive-load (ungexp %utils-module)) ;for 'mkdir-p'
|
|
|
|
|
|
2015-02-13 17:23:17 +01:00
|
|
|
|
(use-modules (ice-9 ftw)
|
2018-04-01 12:33:28 +02:00
|
|
|
|
(ice-9 format)
|
|
|
|
|
(srfi srfi-1)
|
2015-02-13 17:23:17 +01:00
|
|
|
|
(srfi srfi-26)
|
2019-12-03 14:56:29 +01:00
|
|
|
|
(system base target)
|
2015-02-13 17:23:17 +01:00
|
|
|
|
(system base compile))
|
|
|
|
|
|
|
|
|
|
(define (regular? file)
|
|
|
|
|
(not (member file '("." ".."))))
|
|
|
|
|
|
2018-04-01 12:33:28 +02:00
|
|
|
|
(define (process-entry entry output processed)
|
2018-04-01 12:10:30 +02:00
|
|
|
|
(if (file-is-directory? entry)
|
|
|
|
|
(let ((output (string-append output "/" (basename entry))))
|
|
|
|
|
(mkdir-p output)
|
2018-04-01 12:33:28 +02:00
|
|
|
|
(process-directory entry output processed))
|
2018-04-01 12:10:30 +02:00
|
|
|
|
(let* ((base (basename entry ".scm"))
|
|
|
|
|
(output (string-append output "/" base ".go")))
|
2018-04-01 12:33:28 +02:00
|
|
|
|
(format #t "[~2@a/~2@a] Compiling '~a'...~%"
|
2019-06-17 15:54:17 +02:00
|
|
|
|
(+ 1 processed (ungexp total))
|
|
|
|
|
(ungexp (* total 2))
|
2019-04-04 17:18:06 +02:00
|
|
|
|
entry)
|
2019-07-26 23:22:28 +02:00
|
|
|
|
|
|
|
|
|
(ungexp-splicing
|
|
|
|
|
(if target
|
|
|
|
|
(gexp ((with-target (ungexp target)
|
|
|
|
|
(lambda ()
|
|
|
|
|
(compile-file entry
|
|
|
|
|
#:output-file output
|
|
|
|
|
#:opts
|
|
|
|
|
%auto-compilation-options)))))
|
|
|
|
|
(gexp ((compile-file entry
|
|
|
|
|
#:output-file output
|
|
|
|
|
#:opts %auto-compilation-options)))))
|
|
|
|
|
|
2018-04-01 12:33:28 +02:00
|
|
|
|
(+ 1 processed))))
|
2018-04-01 12:10:30 +02:00
|
|
|
|
|
2018-04-01 12:33:28 +02:00
|
|
|
|
(define (process-directory directory output processed)
|
2015-02-13 17:23:17 +01:00
|
|
|
|
(let ((entries (map (cut string-append directory "/" <>)
|
|
|
|
|
(scandir directory regular?))))
|
2018-04-01 12:33:28 +02:00
|
|
|
|
(fold (cut process-entry <> output <>)
|
|
|
|
|
processed
|
|
|
|
|
entries)))
|
|
|
|
|
|
2019-06-17 15:54:17 +02:00
|
|
|
|
(define* (load-from-directory directory
|
|
|
|
|
#:optional (loaded 0))
|
|
|
|
|
"Load all the source files found in DIRECTORY."
|
|
|
|
|
;; XXX: This works around <https://bugs.gnu.org/15602>.
|
|
|
|
|
(let ((entries (map (cut string-append directory "/" <>)
|
|
|
|
|
(scandir directory regular?))))
|
|
|
|
|
(fold (lambda (file loaded)
|
|
|
|
|
(if (file-is-directory? file)
|
|
|
|
|
(load-from-directory file loaded)
|
|
|
|
|
(begin
|
|
|
|
|
(format #t "[~2@a/~2@a] Loading '~a'...~%"
|
|
|
|
|
(+ 1 loaded) (ungexp (* 2 total))
|
|
|
|
|
file)
|
|
|
|
|
(save-module-excursion
|
|
|
|
|
(lambda ()
|
|
|
|
|
(primitive-load file)))
|
|
|
|
|
(+ 1 loaded))))
|
|
|
|
|
loaded
|
|
|
|
|
entries)))
|
|
|
|
|
|
2018-04-01 12:33:28 +02:00
|
|
|
|
(setvbuf (current-output-port)
|
|
|
|
|
(cond-expand (guile-2.2 'line) (else _IOLBF)))
|
2015-02-13 17:23:17 +01:00
|
|
|
|
|
2018-07-27 00:02:00 +02:00
|
|
|
|
(define mkdir-p
|
|
|
|
|
;; Capture 'mkdir-p'.
|
|
|
|
|
(@ (guix build utils) mkdir-p))
|
2018-06-01 13:45:36 +02:00
|
|
|
|
|
2018-05-28 18:14:37 +02:00
|
|
|
|
;; Add EXTENSIONS to the search path.
|
2018-07-27 00:02:00 +02:00
|
|
|
|
(set! %load-path
|
|
|
|
|
(append (map (lambda (extension)
|
|
|
|
|
(string-append extension
|
|
|
|
|
"/share/guile/site/"
|
|
|
|
|
(effective-version)))
|
|
|
|
|
'((ungexp-native-splicing extensions)))
|
|
|
|
|
%load-path))
|
|
|
|
|
(set! %load-compiled-path
|
|
|
|
|
(append (map (lambda (extension)
|
|
|
|
|
(string-append extension "/lib/guile/"
|
|
|
|
|
(effective-version)
|
|
|
|
|
"/site-ccache"))
|
|
|
|
|
'((ungexp-native-splicing extensions)))
|
|
|
|
|
%load-compiled-path))
|
2018-05-28 18:14:37 +02:00
|
|
|
|
|
2015-02-13 17:23:17 +01:00
|
|
|
|
(set! %load-path (cons (ungexp modules) %load-path))
|
2018-06-01 13:45:36 +02:00
|
|
|
|
|
2018-07-27 00:02:00 +02:00
|
|
|
|
;; Above we loaded our own (guix build utils) but now we may need to
|
|
|
|
|
;; load a compile a different one. Thus, force a reload.
|
|
|
|
|
(let ((utils (string-append (ungexp modules)
|
|
|
|
|
"/guix/build/utils.scm")))
|
|
|
|
|
(when (file-exists? utils)
|
|
|
|
|
(load utils)))
|
2018-06-01 13:45:36 +02:00
|
|
|
|
|
2015-02-13 17:23:17 +01:00
|
|
|
|
(mkdir (ungexp output))
|
|
|
|
|
(chdir (ungexp modules))
|
2019-04-04 17:18:06 +02:00
|
|
|
|
|
2019-06-17 15:54:17 +02:00
|
|
|
|
(load-from-directory ".")
|
2018-04-01 12:33:28 +02:00
|
|
|
|
(process-directory "." (ungexp output) 0))))
|
2015-02-13 17:23:17 +01:00
|
|
|
|
|
|
|
|
|
;; TODO: Pass MODULES as an environment variable.
|
|
|
|
|
(gexp->derivation name build
|
|
|
|
|
#:system system
|
|
|
|
|
#:guile-for-build guile
|
2017-11-29 16:38:13 +01:00
|
|
|
|
#:local-build? #t
|
|
|
|
|
#:env-vars
|
|
|
|
|
(case deprecation-warnings
|
|
|
|
|
((#f)
|
|
|
|
|
'(("GUILE_WARN_DEPRECATED" . "no")))
|
|
|
|
|
((detailed)
|
|
|
|
|
'(("GUILE_WARN_DEPRECATED" . "detailed")))
|
|
|
|
|
(else
|
|
|
|
|
'())))))
|
2015-02-13 17:23:17 +01:00
|
|
|
|
|
2014-04-28 23:00:57 +02:00
|
|
|
|
|
|
|
|
|
;;;
|
|
|
|
|
;;; Convenience procedures.
|
|
|
|
|
;;;
|
|
|
|
|
|
2014-05-01 18:53:16 +02:00
|
|
|
|
(define (default-guile)
|
2020-02-23 00:20:30 +01:00
|
|
|
|
;; Lazily resolve 'guile-3.0' (not 'guile-final' because this is for
|
2017-11-29 22:29:26 +01:00
|
|
|
|
;; programs returned by 'program-file' and we don't want to keep references
|
|
|
|
|
;; to several Guile packages). This module must not refer to (gnu …)
|
2014-05-01 18:53:16 +02:00
|
|
|
|
;; modules directly, to avoid circular dependencies, hence this hack.
|
2017-11-29 22:29:26 +01:00
|
|
|
|
(module-ref (resolve-interface '(gnu packages guile))
|
2020-02-23 00:20:30 +01:00
|
|
|
|
'guile-3.0))
|
2014-05-01 18:53:16 +02:00
|
|
|
|
|
2018-05-28 18:14:37 +02:00
|
|
|
|
(define* (load-path-expression modules #:optional (path %load-path)
|
2019-07-26 23:48:03 +02:00
|
|
|
|
#:key (extensions '()) system target)
|
2016-07-04 22:19:23 +02:00
|
|
|
|
"Return as a monadic value a gexp that sets '%load-path' and
|
2018-03-23 18:21:28 +01:00
|
|
|
|
'%load-compiled-path' to point to MODULES, a list of module names. MODULES
|
2019-01-07 23:45:15 +01:00
|
|
|
|
are searched for in PATH. Return #f when MODULES and EXTENSIONS are empty."
|
|
|
|
|
(if (and (null? modules) (null? extensions))
|
|
|
|
|
(with-monad %store-monad
|
|
|
|
|
(return #f))
|
|
|
|
|
(mlet %store-monad ((modules (imported-modules modules
|
2019-07-26 23:48:03 +02:00
|
|
|
|
#:module-path path
|
|
|
|
|
#:system system))
|
2019-01-07 23:45:15 +01:00
|
|
|
|
(compiled (compiled-modules modules
|
|
|
|
|
#:extensions extensions
|
2019-07-26 23:48:03 +02:00
|
|
|
|
#:module-path path
|
|
|
|
|
#:system system
|
|
|
|
|
#:target target)))
|
2019-10-03 22:54:28 +02:00
|
|
|
|
(return
|
|
|
|
|
(gexp (eval-when (expand load eval)
|
|
|
|
|
;; Augment the load paths and delete duplicates. Do that
|
|
|
|
|
;; without loading (srfi srfi-1) or anything.
|
2019-08-18 11:00:23 +02:00
|
|
|
|
(let ((extensions '((ungexp-splicing extensions)))
|
2019-10-03 22:54:28 +02:00
|
|
|
|
(prepend (lambda (items lst)
|
|
|
|
|
;; This is O(N²) but N is typically small.
|
|
|
|
|
(let loop ((items items)
|
|
|
|
|
(lst lst))
|
|
|
|
|
(if (null? items)
|
|
|
|
|
lst
|
|
|
|
|
(loop (cdr items)
|
|
|
|
|
(cons (car items)
|
|
|
|
|
(delete (car items) lst))))))))
|
|
|
|
|
(set! %load-path
|
|
|
|
|
(prepend (cons (ungexp modules)
|
|
|
|
|
(map (lambda (extension)
|
|
|
|
|
(string-append extension
|
|
|
|
|
"/share/guile/site/"
|
|
|
|
|
(effective-version)))
|
|
|
|
|
extensions))
|
|
|
|
|
%load-path))
|
|
|
|
|
(set! %load-compiled-path
|
|
|
|
|
(prepend (cons (ungexp compiled)
|
|
|
|
|
(map (lambda (extension)
|
|
|
|
|
(string-append extension
|
|
|
|
|
"/lib/guile/"
|
|
|
|
|
(effective-version)
|
|
|
|
|
"/site-ccache"))
|
|
|
|
|
extensions))
|
|
|
|
|
%load-compiled-path)))))))))
|
2016-07-04 22:19:23 +02:00
|
|
|
|
|
2014-04-28 23:00:57 +02:00
|
|
|
|
(define* (gexp->script name exp
|
2018-03-23 18:21:28 +01:00
|
|
|
|
#:key (guile (default-guile))
|
2019-07-26 23:48:03 +02:00
|
|
|
|
(module-path %load-path)
|
|
|
|
|
(system (%current-system))
|
2020-03-06 10:06:54 +01:00
|
|
|
|
(target 'current))
|
2016-07-12 17:57:28 +02:00
|
|
|
|
"Return an executable script NAME that runs EXP using GUILE, with EXP's
|
2018-03-23 18:21:28 +01:00
|
|
|
|
imported modules in its search path. Look up EXP's modules in MODULE-PATH."
|
2020-03-06 10:06:54 +01:00
|
|
|
|
(mlet* %store-monad ((target (if (eq? target 'current)
|
|
|
|
|
(current-target-system)
|
|
|
|
|
(return target)))
|
|
|
|
|
(set-load-path
|
|
|
|
|
(load-path-expression (gexp-modules exp)
|
|
|
|
|
module-path
|
|
|
|
|
#:extensions
|
|
|
|
|
(gexp-extensions exp)
|
|
|
|
|
#:system system
|
|
|
|
|
#:target target)))
|
2014-04-28 23:00:57 +02:00
|
|
|
|
(gexp->derivation name
|
|
|
|
|
(gexp
|
|
|
|
|
(call-with-output-file (ungexp output)
|
|
|
|
|
(lambda (port)
|
2014-06-04 17:26:54 +02:00
|
|
|
|
;; Note: that makes a long shebang. When the store
|
|
|
|
|
;; is /gnu/store, that fits within the 128-byte
|
|
|
|
|
;; limit imposed by Linux, but that may go beyond
|
|
|
|
|
;; when running tests.
|
2014-04-28 23:00:57 +02:00
|
|
|
|
(format port
|
|
|
|
|
"#!~a/bin/guile --no-auto-compile~%!#~%"
|
|
|
|
|
(ungexp guile))
|
2014-09-07 23:57:36 +02:00
|
|
|
|
|
2019-01-07 23:45:15 +01:00
|
|
|
|
(ungexp-splicing
|
|
|
|
|
(if set-load-path
|
|
|
|
|
(gexp ((write '(ungexp set-load-path) port)))
|
|
|
|
|
(gexp ())))
|
|
|
|
|
|
2014-04-28 23:00:57 +02:00
|
|
|
|
(write '(ungexp exp) port)
|
2018-03-23 18:21:28 +01:00
|
|
|
|
(chmod port #o555))))
|
2019-07-26 23:48:03 +02:00
|
|
|
|
#:system system
|
|
|
|
|
#:target target
|
2020-01-03 12:39:48 +01:00
|
|
|
|
#:module-path module-path
|
|
|
|
|
|
|
|
|
|
;; These derivations are not worth offloading or
|
|
|
|
|
;; substituting.
|
|
|
|
|
#:local-build? #t
|
|
|
|
|
#:substitutable? #f)))
|
2014-04-28 23:00:57 +02:00
|
|
|
|
|
2018-03-23 18:21:28 +01:00
|
|
|
|
(define* (gexp->file name exp #:key
|
|
|
|
|
(set-load-path? #t)
|
2018-04-11 00:52:40 +02:00
|
|
|
|
(module-path %load-path)
|
2019-12-14 17:52:53 +01:00
|
|
|
|
(splice? #f)
|
|
|
|
|
(system (%current-system))
|
2020-03-06 10:06:54 +01:00
|
|
|
|
(target 'current))
|
2018-04-11 00:52:40 +02:00
|
|
|
|
"Return a derivation that builds a file NAME containing EXP. When SPLICE?
|
|
|
|
|
is true, EXP is considered to be a list of expressions that will be spliced in
|
|
|
|
|
the resulting file.
|
|
|
|
|
|
|
|
|
|
When SET-LOAD-PATH? is true, emit code in the resulting file to set
|
|
|
|
|
'%load-path' and '%load-compiled-path' to honor EXP's imported modules.
|
|
|
|
|
Lookup EXP's modules in MODULE-PATH."
|
2018-05-28 18:14:37 +02:00
|
|
|
|
(define modules (gexp-modules exp))
|
|
|
|
|
(define extensions (gexp-extensions exp))
|
|
|
|
|
|
2020-03-06 10:06:54 +01:00
|
|
|
|
(mlet* %store-monad
|
|
|
|
|
((target (if (eq? target 'current)
|
|
|
|
|
(current-target-system)
|
|
|
|
|
(return target)))
|
|
|
|
|
(no-load-path? -> (or (not set-load-path?)
|
|
|
|
|
(and (null? modules)
|
|
|
|
|
(null? extensions))))
|
|
|
|
|
(set-load-path
|
|
|
|
|
(load-path-expression modules module-path
|
|
|
|
|
#:extensions extensions
|
|
|
|
|
#:system system
|
|
|
|
|
#:target target)))
|
|
|
|
|
(if no-load-path?
|
|
|
|
|
(gexp->derivation name
|
|
|
|
|
(gexp
|
|
|
|
|
(call-with-output-file (ungexp output)
|
|
|
|
|
(lambda (port)
|
|
|
|
|
(for-each
|
|
|
|
|
(lambda (exp)
|
|
|
|
|
(write exp port))
|
|
|
|
|
'(ungexp (if splice?
|
|
|
|
|
exp
|
|
|
|
|
(gexp ((ungexp exp)))))))))
|
|
|
|
|
#:local-build? #t
|
|
|
|
|
#:substitutable? #f
|
|
|
|
|
#:system system
|
|
|
|
|
#:target target)
|
2018-05-28 18:14:37 +02:00
|
|
|
|
(gexp->derivation name
|
|
|
|
|
(gexp
|
|
|
|
|
(call-with-output-file (ungexp output)
|
|
|
|
|
(lambda (port)
|
|
|
|
|
(write '(ungexp set-load-path) port)
|
2020-03-06 10:06:54 +01:00
|
|
|
|
(for-each
|
|
|
|
|
(lambda (exp)
|
|
|
|
|
(write exp port))
|
|
|
|
|
'(ungexp (if splice?
|
|
|
|
|
exp
|
|
|
|
|
(gexp ((ungexp exp)))))))))
|
2018-05-28 18:14:37 +02:00
|
|
|
|
#:module-path module-path
|
|
|
|
|
#:local-build? #t
|
2019-12-14 17:52:53 +01:00
|
|
|
|
#:substitutable? #f
|
|
|
|
|
#:system system
|
|
|
|
|
#:target target))))
|
2014-04-28 23:00:57 +02:00
|
|
|
|
|
2015-01-12 23:26:52 +01:00
|
|
|
|
(define* (text-file* name #:rest text)
|
|
|
|
|
"Return as a monadic value a derivation that builds a text file containing
|
2015-03-28 21:26:33 +01:00
|
|
|
|
all of TEXT. TEXT may list, in addition to strings, objects of any type that
|
|
|
|
|
can be used in a gexp: packages, derivations, local file objects, etc. The
|
|
|
|
|
resulting store file holds references to all these."
|
2015-01-12 23:26:52 +01:00
|
|
|
|
(define builder
|
|
|
|
|
(gexp (call-with-output-file (ungexp output "out")
|
|
|
|
|
(lambda (port)
|
|
|
|
|
(display (string-append (ungexp-splicing text)) port)))))
|
|
|
|
|
|
2015-11-25 10:48:55 +01:00
|
|
|
|
(gexp->derivation name builder
|
|
|
|
|
#:local-build? #t
|
|
|
|
|
#:substitutable? #f))
|
2015-01-12 23:26:52 +01:00
|
|
|
|
|
2015-09-09 09:44:43 +02:00
|
|
|
|
(define* (mixed-text-file name #:rest text)
|
|
|
|
|
"Return an object representing store file NAME containing TEXT. TEXT is a
|
|
|
|
|
sequence of strings and file-like objects, as in:
|
|
|
|
|
|
|
|
|
|
(mixed-text-file \"profile\"
|
|
|
|
|
\"export PATH=\" coreutils \"/bin:\" grep \"/bin\")
|
|
|
|
|
|
|
|
|
|
This is the declarative counterpart of 'text-file*'."
|
|
|
|
|
(define build
|
|
|
|
|
(gexp (call-with-output-file (ungexp output "out")
|
|
|
|
|
(lambda (port)
|
|
|
|
|
(display (string-append (ungexp-splicing text)) port)))))
|
|
|
|
|
|
|
|
|
|
(computed-file name build))
|
|
|
|
|
|
2017-10-16 09:57:44 +02:00
|
|
|
|
(define (file-union name files)
|
|
|
|
|
"Return a <computed-file> that builds a directory containing all of FILES.
|
|
|
|
|
Each item in FILES must be a two-element list where the first element is the
|
|
|
|
|
file name to use in the new directory, and the second element is a gexp
|
|
|
|
|
denoting the target file. Here's an example:
|
|
|
|
|
|
|
|
|
|
(file-union \"etc\"
|
|
|
|
|
`((\"hosts\" ,(plain-file \"hosts\"
|
|
|
|
|
\"127.0.0.1 localhost\"))
|
|
|
|
|
(\"bashrc\" ,(plain-file \"bashrc\"
|
2018-09-08 22:56:40 +02:00
|
|
|
|
\"alias ls='ls --color'\"))
|
|
|
|
|
(\"libvirt/qemu.conf\" ,(plain-file \"qemu.conf\" \"\"))))
|
2017-10-16 09:57:44 +02:00
|
|
|
|
|
|
|
|
|
This yields an 'etc' directory containing these two files."
|
|
|
|
|
(computed-file name
|
2018-09-08 22:56:40 +02:00
|
|
|
|
(with-imported-modules '((guix build utils))
|
|
|
|
|
(gexp
|
|
|
|
|
(begin
|
|
|
|
|
(use-modules (guix build utils))
|
|
|
|
|
|
|
|
|
|
(mkdir (ungexp output))
|
|
|
|
|
(chdir (ungexp output))
|
|
|
|
|
(ungexp-splicing
|
|
|
|
|
(map (match-lambda
|
|
|
|
|
((target source)
|
|
|
|
|
(gexp
|
|
|
|
|
(begin
|
|
|
|
|
;; Stat the source to abort early if it does
|
|
|
|
|
;; not exist.
|
|
|
|
|
(stat (ungexp source))
|
|
|
|
|
|
|
|
|
|
(mkdir-p (dirname (ungexp target)))
|
|
|
|
|
(symlink (ungexp source)
|
|
|
|
|
(ungexp target))))))
|
|
|
|
|
files)))))))
|
2017-10-16 09:57:44 +02:00
|
|
|
|
|
2017-10-19 16:07:34 +02:00
|
|
|
|
(define* (directory-union name things
|
2018-04-08 16:22:25 +02:00
|
|
|
|
#:key (copy? #f) (quiet? #f)
|
|
|
|
|
(resolve-collision 'warn-about-collision))
|
2017-10-16 10:12:53 +02:00
|
|
|
|
"Return a directory that is the union of THINGS, where THINGS is a list of
|
|
|
|
|
file-like objects denoting directories. For example:
|
|
|
|
|
|
|
|
|
|
(directory-union \"guile+emacs\" (list guile emacs))
|
|
|
|
|
|
2017-10-19 16:07:34 +02:00
|
|
|
|
yields a directory that is the union of the 'guile' and 'emacs' packages.
|
|
|
|
|
|
2018-04-08 16:22:25 +02:00
|
|
|
|
Call RESOLVE-COLLISION when several files collide, passing it the list of
|
|
|
|
|
colliding files. RESOLVE-COLLISION must return the chosen file or #f, in
|
|
|
|
|
which case the colliding entry is skipped altogether.
|
|
|
|
|
|
2017-10-19 16:10:18 +02:00
|
|
|
|
When HARD-LINKS? is true, create hard links instead of symlinks. When QUIET?
|
|
|
|
|
is true, the derivation will not print anything."
|
2017-10-19 16:07:34 +02:00
|
|
|
|
(define symlink
|
|
|
|
|
(if copy?
|
|
|
|
|
(gexp (lambda (old new)
|
|
|
|
|
(if (file-is-directory? old)
|
|
|
|
|
(symlink old new)
|
|
|
|
|
(copy-file old new))))
|
|
|
|
|
(gexp symlink)))
|
|
|
|
|
|
2017-10-19 16:10:18 +02:00
|
|
|
|
(define log-port
|
|
|
|
|
(if quiet?
|
|
|
|
|
(gexp (%make-void-port "w"))
|
|
|
|
|
(gexp (current-error-port))))
|
|
|
|
|
|
2017-10-16 10:12:53 +02:00
|
|
|
|
(match things
|
|
|
|
|
((one)
|
|
|
|
|
;; Only one thing; return it.
|
|
|
|
|
one)
|
|
|
|
|
(_
|
|
|
|
|
(computed-file name
|
|
|
|
|
(with-imported-modules '((guix build union))
|
|
|
|
|
(gexp (begin
|
2018-04-08 16:22:25 +02:00
|
|
|
|
(use-modules (guix build union)
|
|
|
|
|
(srfi srfi-1)) ;for 'first' and 'last'
|
|
|
|
|
|
2017-10-16 10:12:53 +02:00
|
|
|
|
(union-build (ungexp output)
|
2017-10-19 16:07:34 +02:00
|
|
|
|
'(ungexp things)
|
|
|
|
|
|
2017-10-19 16:10:18 +02:00
|
|
|
|
#:log-port (ungexp log-port)
|
2018-04-08 16:22:25 +02:00
|
|
|
|
#:symlink (ungexp symlink)
|
|
|
|
|
#:resolve-collision
|
|
|
|
|
(ungexp resolve-collision)))))))))
|
2017-10-16 10:12:53 +02:00
|
|
|
|
|
2014-04-28 23:00:57 +02:00
|
|
|
|
|
|
|
|
|
;;;
|
|
|
|
|
;;; Syntactic sugar.
|
|
|
|
|
;;;
|
|
|
|
|
|
|
|
|
|
(eval-when (expand load eval)
|
gexp: Add 'ungexp-native' and 'ungexp-native-splicing'.
* guix/gexp.scm (<gexp>)[natives]: New field.
(write-gexp): Use both 'gexp-references' and
'gexp-native-references'.
(gexp->derivation): Use both 'gexp-inputs' and 'gexp-native-inputs',
and append them.
(gexp-inputs): Add 'references' parameter and honor it.
(gexp-native-inputs): New procedure.
(gexp->sexp)[reference->sexp]: Add 'native?' parameter and honor it.
Use it, and use 'gexp-native-references'.
(gexp)[collect-native-escapes]: New procedure.
[escape->ref]: Handle 'ungexp-native' and 'ungexp-native-splicing'.
[substitute-ungexp, substitute-ungexp-splicing]: New procedures.
[substitute-references]: Use them, and handle 'ungexp-native' and
'ungexp-native-splicing'.
Adjust generated 'make-gexp' call to provide both normal references
and native references.
[read-ungexp]: Support 'ungexp-native' and
'ungexp-native-splicing'.
Add reader extension for #+.
* tests/gexp.scm (gexp-native-inputs): New procedure.
(gexp->sexp*): Add 'target' parameter.
("ungexp + ungexp-native",
"input list + ungexp-native",
"input list splicing + ungexp-native-splicing",
"gexp->derivation, ungexp-native",
"gexp->derivation, ungexp + ungexp-native"): New tests.
("sugar"): Add tests for #+ and #+@.
* doc/guix.texi (G-Expressions): Document 'ungexp-native' et al.
2014-08-18 14:53:10 +02:00
|
|
|
|
(define* (read-ungexp chr port #:optional native?)
|
|
|
|
|
"Read an 'ungexp' or 'ungexp-splicing' form from PORT. When NATIVE? is
|
|
|
|
|
true, use 'ungexp-native' and 'ungexp-native-splicing' instead."
|
2014-04-28 23:00:57 +02:00
|
|
|
|
(define unquote-symbol
|
|
|
|
|
(match (peek-char port)
|
|
|
|
|
(#\@
|
|
|
|
|
(read-char port)
|
gexp: Add 'ungexp-native' and 'ungexp-native-splicing'.
* guix/gexp.scm (<gexp>)[natives]: New field.
(write-gexp): Use both 'gexp-references' and
'gexp-native-references'.
(gexp->derivation): Use both 'gexp-inputs' and 'gexp-native-inputs',
and append them.
(gexp-inputs): Add 'references' parameter and honor it.
(gexp-native-inputs): New procedure.
(gexp->sexp)[reference->sexp]: Add 'native?' parameter and honor it.
Use it, and use 'gexp-native-references'.
(gexp)[collect-native-escapes]: New procedure.
[escape->ref]: Handle 'ungexp-native' and 'ungexp-native-splicing'.
[substitute-ungexp, substitute-ungexp-splicing]: New procedures.
[substitute-references]: Use them, and handle 'ungexp-native' and
'ungexp-native-splicing'.
Adjust generated 'make-gexp' call to provide both normal references
and native references.
[read-ungexp]: Support 'ungexp-native' and
'ungexp-native-splicing'.
Add reader extension for #+.
* tests/gexp.scm (gexp-native-inputs): New procedure.
(gexp->sexp*): Add 'target' parameter.
("ungexp + ungexp-native",
"input list + ungexp-native",
"input list splicing + ungexp-native-splicing",
"gexp->derivation, ungexp-native",
"gexp->derivation, ungexp + ungexp-native"): New tests.
("sugar"): Add tests for #+ and #+@.
* doc/guix.texi (G-Expressions): Document 'ungexp-native' et al.
2014-08-18 14:53:10 +02:00
|
|
|
|
(if native?
|
|
|
|
|
'ungexp-native-splicing
|
|
|
|
|
'ungexp-splicing))
|
2014-04-28 23:00:57 +02:00
|
|
|
|
(_
|
gexp: Add 'ungexp-native' and 'ungexp-native-splicing'.
* guix/gexp.scm (<gexp>)[natives]: New field.
(write-gexp): Use both 'gexp-references' and
'gexp-native-references'.
(gexp->derivation): Use both 'gexp-inputs' and 'gexp-native-inputs',
and append them.
(gexp-inputs): Add 'references' parameter and honor it.
(gexp-native-inputs): New procedure.
(gexp->sexp)[reference->sexp]: Add 'native?' parameter and honor it.
Use it, and use 'gexp-native-references'.
(gexp)[collect-native-escapes]: New procedure.
[escape->ref]: Handle 'ungexp-native' and 'ungexp-native-splicing'.
[substitute-ungexp, substitute-ungexp-splicing]: New procedures.
[substitute-references]: Use them, and handle 'ungexp-native' and
'ungexp-native-splicing'.
Adjust generated 'make-gexp' call to provide both normal references
and native references.
[read-ungexp]: Support 'ungexp-native' and
'ungexp-native-splicing'.
Add reader extension for #+.
* tests/gexp.scm (gexp-native-inputs): New procedure.
(gexp->sexp*): Add 'target' parameter.
("ungexp + ungexp-native",
"input list + ungexp-native",
"input list splicing + ungexp-native-splicing",
"gexp->derivation, ungexp-native",
"gexp->derivation, ungexp + ungexp-native"): New tests.
("sugar"): Add tests for #+ and #+@.
* doc/guix.texi (G-Expressions): Document 'ungexp-native' et al.
2014-08-18 14:53:10 +02:00
|
|
|
|
(if native?
|
|
|
|
|
'ungexp-native
|
|
|
|
|
'ungexp))))
|
2014-04-28 23:00:57 +02:00
|
|
|
|
|
|
|
|
|
(match (read port)
|
|
|
|
|
((? symbol? symbol)
|
|
|
|
|
(let ((str (symbol->string symbol)))
|
|
|
|
|
(match (string-index-right str #\:)
|
|
|
|
|
(#f
|
|
|
|
|
`(,unquote-symbol ,symbol))
|
|
|
|
|
(colon
|
|
|
|
|
(let ((name (string->symbol (substring str 0 colon)))
|
|
|
|
|
(output (substring str (+ colon 1))))
|
|
|
|
|
`(,unquote-symbol ,name ,output))))))
|
|
|
|
|
(x
|
|
|
|
|
`(,unquote-symbol ,x))))
|
|
|
|
|
|
|
|
|
|
(define (read-gexp chr port)
|
|
|
|
|
"Read a 'gexp' form from PORT."
|
|
|
|
|
`(gexp ,(read port)))
|
|
|
|
|
|
|
|
|
|
;; Extend the reader
|
|
|
|
|
(read-hash-extend #\~ read-gexp)
|
gexp: Add 'ungexp-native' and 'ungexp-native-splicing'.
* guix/gexp.scm (<gexp>)[natives]: New field.
(write-gexp): Use both 'gexp-references' and
'gexp-native-references'.
(gexp->derivation): Use both 'gexp-inputs' and 'gexp-native-inputs',
and append them.
(gexp-inputs): Add 'references' parameter and honor it.
(gexp-native-inputs): New procedure.
(gexp->sexp)[reference->sexp]: Add 'native?' parameter and honor it.
Use it, and use 'gexp-native-references'.
(gexp)[collect-native-escapes]: New procedure.
[escape->ref]: Handle 'ungexp-native' and 'ungexp-native-splicing'.
[substitute-ungexp, substitute-ungexp-splicing]: New procedures.
[substitute-references]: Use them, and handle 'ungexp-native' and
'ungexp-native-splicing'.
Adjust generated 'make-gexp' call to provide both normal references
and native references.
[read-ungexp]: Support 'ungexp-native' and
'ungexp-native-splicing'.
Add reader extension for #+.
* tests/gexp.scm (gexp-native-inputs): New procedure.
(gexp->sexp*): Add 'target' parameter.
("ungexp + ungexp-native",
"input list + ungexp-native",
"input list splicing + ungexp-native-splicing",
"gexp->derivation, ungexp-native",
"gexp->derivation, ungexp + ungexp-native"): New tests.
("sugar"): Add tests for #+ and #+@.
* doc/guix.texi (G-Expressions): Document 'ungexp-native' et al.
2014-08-18 14:53:10 +02:00
|
|
|
|
(read-hash-extend #\$ read-ungexp)
|
|
|
|
|
(read-hash-extend #\+ (cut read-ungexp <> <> #t)))
|
2014-04-28 23:00:57 +02:00
|
|
|
|
|
|
|
|
|
;;; gexp.scm ends here
|