Subject: bug#40839: Shepherd activation .GO files are not cross-compiled ... and the Hurd

From: Jan Nieuwenhuizen <[email-masked]>
Date: Sat, 25 Apr 2020 15:28:23 +0200

Mathieu Othacehe writes:

Hello Mathieu,

> I strongly suspect this is because we would need to wrap the
> "compile-file" call in "scm->go" procedure of (gnu services shepherd)
> inside a "with-target".

> That would look like:
>
> (if target
>     (with-target target
>                  (compile-file #$file #:output-file #$output
>                                #:env env))
>   (compile-file #$file #:output-file #$output
>                 #:env env))

Thank you!  I have tried this in the attached patch, and it seems to
work for me.

I was so puzzled why wrapping scm->go

--8<---------------cut here---------------start------------->8---
(use-modules (system base target))
(define (scm->go file)
  (with-target "i586-pc-gnu"
    (lambda _
     ((@@ (gnu services shepherd) scm->go) file))))
--8<---------------cut here---------------end--------------->8---

did not work; actually reading scm->go makes that pretty clear :-)

> Now, the tricky part is the value of target, because
> #$(%current-target-system) might not be correct in that context.

I did read this, but wanted to try it first anyway.  So, what are you
seeing here, when would this not be OK?  Any other ideas of how to
address this further?

Greetings,
janneke

>From cc9259a87c46cfa0dc2c59dc425b3656c9eecb13 Mon Sep 17 00:00:00 2001
From: "Jan (janneke) Nieuwenhuizen" <[email-masked]>
Date: Sat, 25 Apr 2020 15:20:04 +0200
Subject: [PATCH] services: shepherd: Cross-compilation fix.

Fixes <https://bugs.gnu.org/40839>.
Reported by Jan (janneke) Nieuwenhuizen <[email-masked]>
Fix suggested by Mathieu Othacehe <[email-masked]>

* gnu/services/shepherd.scm (scm->go): Use `with-target' when cross-compiling.
---
 gnu/services/shepherd.scm | 40 +++++++++++++++++++++++----------------
 1 file changed, 24 insertions(+), 16 deletions(-)

diff --git a/gnu/services/shepherd.scm b/gnu/services/shepherd.scm
index 2f30c6c907..ca4edd80ab 100644
--- a/gnu/services/shepherd.scm
+++ b/gnu/services/shepherd.scm
@@ -25,6 +25,7 @@
   #:use-module (guix store)
   #:use-module (guix records)
   #:use-module (guix derivations)                 ;imported-modules, etc.
+  #:use-module (guix utils)
   #:use-module (gnu services)
   #:use-module (gnu services herd)
   #:use-module (gnu packages admin)
@@ -260,22 +261,29 @@ stored."
 (define (scm->go file)
   "Compile FILE, which contains code to be loaded by shepherd's config file,
 and return the resulting '.go' file."
-  (with-extensions (list shepherd)
-    (computed-file (string-append (basename (scheme-file-name file) ".scm")
-                                  ".go")
-                   #~(begin
-                       (use-modules (system base compile))
-
-                       ;; Do the same as the Shepherd's 'load-in-user-module'.
-                       (let ((env (make-fresh-user-module)))
-                         (module-use! env (resolve-interface '(oop goops)))
-                         (module-use! env (resolve-interface '(shepherd service)))
-                         (compile-file #$file #:output-file #$output
-                                       #:env env)))
-
-                   ;; It's faster to build locally than to download.
-                   #:options '(#:local-build? #t
-                               #:substitutable? #f))))
+  (let ((target (%current-target-system)))
+    (with-extensions (list shepherd)
+      (computed-file (string-append (basename (scheme-file-name file) ".scm")
+                                    ".go")
+                     #~(begin
+                         (use-modules (system base compile)
+                                      (system base target))
+
+                         ;; Do the same as the Shepherd's 'load-in-user-module'.
+                         (let ((env (make-fresh-user-module)))
+                           (module-use! env (resolve-interface '(oop goops)))
+                           (module-use! env (resolve-interface '(shepherd service)))
+                           (if #$target
+                               (with-target #$target
+                                 (lambda _
+                                   (compile-file #$file #:output-file #$output
+                                                 #:env env)))
+                               (compile-file #$file #:output-file #$output
+                                             #:env env))))
+
+                     ;; It's faster to build locally than to download.
+                     #:options '(#:local-build? #t
+                                 #:substitutable? #f)))))
 
 (define (shepherd-configuration-file services)
   "Return the shepherd configuration file for SERVICES."
-- 
2.26.0

-- 
Jan Nieuwenhuizen <[email-masked]> | GNU LilyPond http://lilypond.org
Freelance IT http://JoyofSource.com | Avatar® http://AvatarAcademy.com