unofficial mirror of guix-patches@gnu.org 
 help / color / mirror / code / Atom feed
* [bug#29296] [PATCH 0/2] gexp: Add 'let-system'
@ 2017-11-14 16:18 Ludovic Courtès
  2017-11-14 16:25 ` [bug#29296] [PATCH 1/2] gexp: Compilers can now return lowerable objects Ludovic Courtès
  0 siblings, 1 reply; 7+ messages in thread
From: Ludovic Courtès @ 2017-11-14 16:18 UTC (permalink / raw)
  To: 29296

Hello!

This patch adds the ‘let-system’ form to (guix gexp), as discussed with
Mathieu at <https://bugs.gnu.org/29281>.  It allows you to insert
system-dependent code inside a gexp, as in this example:

      #~(system*
         #+(let-system system
             (cond ((string-prefix? "armhf-" system)
                    (file-append qemu "/bin/qemu-system-arm"))
                   ((string-prefix? "x86_64-" system)
                    (file-append qemu "/bin/qemu-system-x86_64"))
                   (else
                    (error "dunno!"))))
         "-net" "user" #$image)

(Using (%current-system) and (%current-target-system) does *not* achieve
this, in case you’re wondering, because at the time the gexp is defined
they carry their default value.)

Feedback welcome!

Ludo’.

Ludovic Courtès (2):
  gexp: Compilers can now return lowerable objects.
  gexp: Add 'let-system'.

 doc/guix.texi  |  26 ++++++++++++++
 guix/gexp.scm  | 105 ++++++++++++++++++++++++++++++++++++++++++++++++---------
 tests/gexp.scm |  50 +++++++++++++++++++++++++++
 3 files changed, 165 insertions(+), 16 deletions(-)

-- 
2.15.0

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [bug#29296] [PATCH 1/2] gexp: Compilers can now return lowerable objects.
  2017-11-14 16:18 [bug#29296] [PATCH 0/2] gexp: Add 'let-system' Ludovic Courtès
@ 2017-11-14 16:25 ` Ludovic Courtès
  2017-11-14 16:25   ` [bug#29296] [PATCH 2/2] gexp: Add 'let-system' Ludovic Courtès
  0 siblings, 1 reply; 7+ messages in thread
From: Ludovic Courtès @ 2017-11-14 16:25 UTC (permalink / raw)
  To: 29296

* guix/gexp.scm (lower-object): Iterate if LOWERED is a struct.
(lower+expand-object): New procedure.
(gexp->sexp): Use it.
(define-gexp-compiler): Adjust docstring.
---
 guix/gexp.scm | 54 +++++++++++++++++++++++++++++++++++++++---------------
 1 file changed, 39 insertions(+), 15 deletions(-)

diff --git a/guix/gexp.scm b/guix/gexp.scm
index b9525603e..c2d942c7f 100644
--- a/guix/gexp.scm
+++ b/guix/gexp.scm
@@ -195,24 +195,50 @@ procedure to expand it; otherwise return #f."
 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>."
-  (match (lookup-compiler obj)
-    (#f
-     (raise (condition (&gexp-input-error (input obj)))))
-    (lower
-     (lower obj system target))))
+  (let loop ((obj obj))
+    (match (lookup-compiler obj)
+      (#f
+       (raise (condition (&gexp-input-error (input obj)))))
+      (lower
+       (mlet %store-monad ((lowered (lower obj system target)))
+         (if (and (struct? lowered) (not (eq? lowered obj)))
+             (loop lowered)
+             (return lowered)))))))
+
+(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 ((lowered (lower obj system target)))
+         ;; 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)))
+             (return lowered)))))))               ;lists, vectors, etc.
 
 (define-syntax define-gexp-compiler
   (syntax-rules (=> compiler expander)
     "Define NAME as a compiler for objects matching PREDICATE encountered in
 gexps.
 
-In the simplest form of the macro, BODY must return a derivation for PARAM, an
-object that matches PREDICATE, for SYSTEM and TARGET (the latter of which is
-#f except when cross-compiling.)
+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.
 
 The more elaborate form allows you to specify an expander:
 
-  (define-gexp-compiler something something?
+  (define-gexp-compiler something-compiler <something>
     compiler => (lambda (param system target) ...)
     expander => (lambda (param drv output) ...))
 
@@ -795,12 +821,10 @@ and in the current monad setting (system type, etc.)"
                            (or n? native?)))
                         refs)))
         (($ <gexp-input> (? struct? thing) output n?)
-         (let ((target (if (or n? native?) #f target))
-               (expand (lookup-expander thing)))
-           (mlet %store-monad ((obj (lower-object thing system
-                                                  #:target target)))
-             ;; OBJ must be either a derivation or a store file name.
-             (return (expand thing obj output)))))
+         (let ((target (if (or n? native?) #f target)))
+           (lower+expand-object thing system
+                                #:target target
+                                #:output output)))
         (($ <gexp-input> x)
          (return x))
         (x
-- 
2.15.0

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [bug#29296] [PATCH 2/2] gexp: Add 'let-system'.
  2017-11-14 16:25 ` [bug#29296] [PATCH 1/2] gexp: Compilers can now return lowerable objects Ludovic Courtès
@ 2017-11-14 16:25   ` Ludovic Courtès
  2017-11-15 11:27     ` Mathieu Othacehe
  0 siblings, 1 reply; 7+ messages in thread
From: Ludovic Courtès @ 2017-11-14 16:25 UTC (permalink / raw)
  To: 29296

* guix/gexp.scm (<system-binding>): New record type.
(let-system): New macro.
(system-binding-compiler): New procedure.
(default-expander): Add catch-all case.
* tests/gexp.scm ("let-system", "let-system, target")
("let-system, ungexp-native, target")
("let-system, nested"): New tests.
* doc/guix.texi (G-Expressions): Document it.
---
 doc/guix.texi  | 26 ++++++++++++++++++++++++++
 guix/gexp.scm  | 51 ++++++++++++++++++++++++++++++++++++++++++++++++++-
 tests/gexp.scm | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 126 insertions(+), 1 deletion(-)

diff --git a/doc/guix.texi b/doc/guix.texi
index 098ff5e54..0e795ada6 100644
--- a/doc/guix.texi
+++ b/doc/guix.texi
@@ -4799,6 +4799,32 @@ procedures called from @var{body}@dots{}.
 Return @code{#t} if @var{obj} is a G-expression.
 @end deffn
 
+@deffn {Scheme Syntax} let-system @var{system} @var{body}@dots{}
+@deffnx {Scheme Syntax} let-system (@var{system} @var{target}) @var{body}@dots{}
+Bind @var{system} to the currently targeted system---e.g.,
+@code{"x86_64-linux"}---within @var{body}.
+
+In the second case, additionally bind @var{target} to the current
+cross-compilation target---a GNU triplet such as
+@code{"arm-linux-gnueabihf"}---or @code{#f} if we are not
+cross-compiling.
+
+@code{let-system} is useful in the occasional case where the object
+spliced into the gexp depends on the target system, as in this example:
+
+@example
+#~(system*
+   #+(let-system system
+       (cond ((string-prefix? "armhf-" system)
+              (file-append qemu "/bin/qemu-system-arm"))
+             ((string-prefix? "x86_64-" system)
+              (file-append qemu "/bin/qemu-system-x86_64"))
+             (else
+              (error "dunno!"))))
+   "-net" "user" #$image)
+@end example
+@end deffn
+
 G-expressions are meant to be written to disk, either as code building
 some derivation, or as plain files in the store.  The monadic procedures
 below allow you to do that (@pxref{The Store Monad}, for more
diff --git a/guix/gexp.scm b/guix/gexp.scm
index c2d942c7f..c65c6e5f3 100644
--- a/guix/gexp.scm
+++ b/guix/gexp.scm
@@ -32,6 +32,7 @@
   #:export (gexp
             gexp?
             with-imported-modules
+            let-system
 
             gexp-input
             gexp-input?
@@ -169,7 +170,9 @@ returns its output file name of OBJ's OUTPUT."
     ((? derivation? drv)
      (derivation->output-path drv output))
     ((? string? file)
-     file)))
+     file)
+    (obj                                          ;lists, vectors, etc.
+     obj)))
 
 (define (register-compiler! compiler)
   "Register COMPILER as a gexp compiler."
@@ -262,6 +265,52 @@ The expander specifies how an object is converted to its sexp representation."
     (return drv)))
 
 \f
+;;;
+;;; 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)
+
+\f
 ;;;
 ;;; File declarations.
 ;;;
diff --git a/tests/gexp.scm b/tests/gexp.scm
index 5873abdd4..f98d1e70e 100644
--- a/tests/gexp.scm
+++ b/tests/gexp.scm
@@ -258,6 +258,56 @@
            (((thing "out"))
             (eq? thing file))))))
 
+(test-equal "let-system"
+  (list `(begin ,(%current-system) #t) '(system-binding) '())
+  (let ((exp  #~(begin
+                  #$(let-system system system)
+                  #t)))
+    (list (gexp->sexp* exp)
+          (match (gexp-inputs exp)
+            (((($ (@@ (guix gexp) <system-binding>)) "out"))
+             '(system-binding))
+            (x x))
+          (gexp-native-inputs exp))))
+
+(test-equal "let-system, target"
+  (list `(list ,(%current-system) #f)
+        `(list ,(%current-system) "aarch64-linux-gnu"))
+  (let ((exp #~(list #$@(let-system (system target)
+                          (list system target)))))
+    (list (gexp->sexp* exp)
+          (gexp->sexp* exp "aarch64-linux-gnu"))))
+
+(test-equal "let-system, ungexp-native, target"
+  `(here it is: ,(%current-system) #f)
+  (let ((exp #~(here it is: #+@(let-system (system target)
+                                 (list system target)))))
+    (gexp->sexp* exp "aarch64-linux-gnu")))
+
+(test-equal "let-system, nested"
+  (list `(system* ,(string-append "qemu-system-" (%current-system))
+                  "-m" "256")
+        '()
+        '(system-binding))
+  (let ((exp #~(system*
+                #+(let-system (system target)
+                    (file-append (@@ (gnu packages virtualization)
+                                     qemu)
+                                 "/bin/qemu-system-"
+                                 system))
+                "-m" "256")))
+    (list (match (gexp->sexp* exp)
+            (('system* command rest ...)
+             `(system* ,(and (string-prefix? (%store-prefix) command)
+                             (basename command))
+                       ,@rest))
+            (x x))
+          (gexp-inputs exp)
+          (match (gexp-native-inputs exp)
+            (((($ (@@ (guix gexp) <system-binding>)) "out"))
+             '(system-binding))
+            (x x)))))
+
 (test-assert "ungexp + ungexp-native"
   (let* ((exp    (gexp (list (ungexp-native %bootstrap-guile)
                              (ungexp coreutils)
-- 
2.15.0

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [bug#29296] [PATCH 2/2] gexp: Add 'let-system'.
  2017-11-14 16:25   ` [bug#29296] [PATCH 2/2] gexp: Add 'let-system' Ludovic Courtès
@ 2017-11-15 11:27     ` Mathieu Othacehe
  2017-11-16  9:10       ` Ludovic Courtès
  0 siblings, 1 reply; 7+ messages in thread
From: Mathieu Othacehe @ 2017-11-15 11:27 UTC (permalink / raw)
  To: Ludovic Courtès; +Cc: 29296


Hi Ludo,

I must admit i don't have a perfect understanding of what is going on in
gexp.scm but your serie LGTM.

When diffing with the initial patch it seems that the entry in
.dir-locals.el is gone but it is a minor point.

About the integration of let-system in "system-disk-image", i'm not sure
how to proceed. let-system is meant to be used in a gexp but the
operating-system is not defined in a gexp.

Do you have any advice on how to turn os declaration into a gexp so that
i can use let-system to parameterize kernel field ?

Thanks,

Mathieu

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [bug#29296] [PATCH 2/2] gexp: Add 'let-system'.
  2017-11-15 11:27     ` Mathieu Othacehe
@ 2017-11-16  9:10       ` Ludovic Courtès
  2020-05-22 22:44         ` Danny Milosavljevic
  0 siblings, 1 reply; 7+ messages in thread
From: Ludovic Courtès @ 2017-11-16  9:10 UTC (permalink / raw)
  To: Mathieu Othacehe; +Cc: 29296

[-- Attachment #1: Type: text/plain, Size: 1146 bytes --]

Hi Mathieu,

Mathieu Othacehe <m.othacehe@gmail.com> skribis:

> I must admit i don't have a perfect understanding of what is going on in
> gexp.scm but your serie LGTM.
>
> When diffing with the initial patch it seems that the entry in
> .dir-locals.el is gone but it is a minor point.

Oops.

> About the integration of let-system in "system-disk-image", i'm not sure
> how to proceed. let-system is meant to be used in a gexp but the
> operating-system is not defined in a gexp.
>
> Do you have any advice on how to turn os declaration into a gexp so that
> i can use let-system to parameterize kernel field ?

The idea is that you can write:

  (kernel (let-system system
            (if (string-prefix? "arm-" system)
                linux-libre-arm
                linux-libre)))

and things will just work.

Now I found a couple of issues.  First one is addressed with the patch
below.  Second one is trickier: (file-append (let-system …) …), as is
used to compute the kernel file name, doesn’t work due to the way the
<file-append> expander works.

I’ll see what I can do.

Thanks,
Ludo’.


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: Type: text/x-patch, Size: 829 bytes --]

diff --git a/gnu/system.scm b/gnu/system.scm
index 9e05c4b21..a4804cf86 100644
--- a/gnu/system.scm
+++ b/gnu/system.scm
@@ -876,10 +876,12 @@ listed in OS.  The C library expects to find it under
 
 (define (kernel->boot-label kernel)
   "Return a label for the bootloader menu entry that boots KERNEL."
-  (string-append "GNU with "
-                 (string-titlecase (package-name kernel)) " "
-                 (package-version kernel)
-                 " (beta)"))
+  (if (package? kernel)
+      (string-append "GNU with "
+                     (string-titlecase (package-name kernel)) " "
+                     (package-version kernel)
+                     " (beta)")
+      "GNU GuixSD (beta)"))
 
 (define (store-file-system file-systems)
   "Return the file system object among FILE-SYSTEMS that contains the store."

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [bug#29296] [PATCH 2/2] gexp: Add 'let-system'.
  2017-11-16  9:10       ` Ludovic Courtès
@ 2020-05-22 22:44         ` Danny Milosavljevic
  2020-05-22 23:01           ` Marius Bakke
  0 siblings, 1 reply; 7+ messages in thread
From: Danny Milosavljevic @ 2020-05-22 22:44 UTC (permalink / raw)
  To: Ludovic Courtès; +Cc: Mathieu Othacehe, 29296

[-- Attachment #1: Type: text/plain, Size: 1074 bytes --]

Hi Ludo,

maybe a little off-topic, but why do I have to use the following patch on
armhf-linux (*not* cross compiling) in order to stop it from pulling in
i686-cross-gcc?

Makes no sense to me at all...

diff --git a/gnu/packages/mes.scm b/gnu/packages/mes.scm
index 347aef0..524b8e8 100644
--- a/gnu/packages/mes.scm
+++ b/gnu/packages/mes.scm
@@ -120,8 +120,9 @@ extensive examples, including parsers for the Javascript and C99 languages.")
             ((string-prefix? "x86_64-linux" target-system)
              ;; Use cross-compiler rather than #:system "i686-linux" to get
              ;; MesCC 64 bit .go files installed ready for use with Guile.
-             `(("i686-linux-binutils" ,(cross-binutils "i686-unknown-linux-gnu"))
-               ("i686-linux-gcc" ,(cross-gcc "i686-unknown-linux-gnu"))))
+             `( ;("i686-linux-binutils" ,(cross-binutils "i686-unknown-linux-gnu"))
+                ;("i686-linux-gcc" ,(cross-gcc "i686-unknown-linux-gnu"))
+))
             (else
              '())))
        ("graphviz" ,graphviz)

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [bug#29296] [PATCH 2/2] gexp: Add 'let-system'.
  2020-05-22 22:44         ` Danny Milosavljevic
@ 2020-05-22 23:01           ` Marius Bakke
  0 siblings, 0 replies; 7+ messages in thread
From: Marius Bakke @ 2020-05-22 23:01 UTC (permalink / raw)
  To: Danny Milosavljevic, Ludovic Courtès; +Cc: Mathieu Othacehe, 29296

[-- Attachment #1: Type: text/plain, Size: 1436 bytes --]

Danny Milosavljevic <dannym@scratchpost.org> writes:

> Hi Ludo,
>
> maybe a little off-topic, but why do I have to use the following patch on
> armhf-linux (*not* cross compiling) in order to stop it from pulling in
> i686-cross-gcc?

Can you give a little more context?  Did this occur after the let-system
patch, or is this when using let-system?

Can you paste the derivation for mes@0.19 in the context this occurs?

Also, please file a new bug report.

> Makes no sense to me at all...

If only all bugs were obvious, our jobs would be so much easier!

> diff --git a/gnu/packages/mes.scm b/gnu/packages/mes.scm
> index 347aef0..524b8e8 100644
> --- a/gnu/packages/mes.scm
> +++ b/gnu/packages/mes.scm
> @@ -120,8 +120,9 @@ extensive examples, including parsers for the Javascript and C99 languages.")
>              ((string-prefix? "x86_64-linux" target-system)
>               ;; Use cross-compiler rather than #:system "i686-linux" to get
>               ;; MesCC 64 bit .go files installed ready for use with Guile.
> -             `(("i686-linux-binutils" ,(cross-binutils "i686-unknown-linux-gnu"))
> -               ("i686-linux-gcc" ,(cross-gcc "i686-unknown-linux-gnu"))))
> +             `( ;("i686-linux-binutils" ,(cross-binutils "i686-unknown-linux-gnu"))
> +                ;("i686-linux-gcc" ,(cross-gcc "i686-unknown-linux-gnu"))
> +))
>              (else
>               '())))
>         ("graphviz" ,graphviz)

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 487 bytes --]

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2020-05-22 23:02 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2017-11-14 16:18 [bug#29296] [PATCH 0/2] gexp: Add 'let-system' Ludovic Courtès
2017-11-14 16:25 ` [bug#29296] [PATCH 1/2] gexp: Compilers can now return lowerable objects Ludovic Courtès
2017-11-14 16:25   ` [bug#29296] [PATCH 2/2] gexp: Add 'let-system' Ludovic Courtès
2017-11-15 11:27     ` Mathieu Othacehe
2017-11-16  9:10       ` Ludovic Courtès
2020-05-22 22:44         ` Danny Milosavljevic
2020-05-22 23:01           ` Marius Bakke

Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/guix.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).