Subject: [PATCH 1/2] self: Use a 'guile' that doesn't complain about locales.

From: Ludovic Courtès <[email-masked]>
Date: Thu, 1 Oct 2020 10:38:47 +0200

Since commit ba48895899a117d6ace2209c3f54411a4a989133, selected UTF-8
locales are bundled.  However, because 'guix-command' is itself a Guile
script, users would still see Guile's warning, particularly on foreign
distros:

  $ LC_ALL=sdf guix foo
  guile: warning: failed to install locale
  hint: Consider installing the `glibc-utf8-locales' [...]

User commands would print that warning, but more importantly, each
invocation of 'guix substitute' would print it, even though
'guix-daemon.service' explicitly chooses "en_US.utf8", which is in
'glibc-utf8-locales'.  This leads to confusion since users would keep
seeing this message unless/until they realize they also need to install
'glibc-utf8-locales' in root's profile.

This patch gets rid of "guile: warning: ..." for a guix-pulled 'guix'
command.

* guix/self.scm (specification->package): Add "gcc-toolchain".
(quiet-guile): New procedure.
(guix-command): Use it.
* gnu/packages/aux-files/guile-launcher.c: New file.
* Makefile.am (AUX_FILES): Add it.
---
 Makefile.am                             |  1 +
 gnu/packages/aux-files/guile-launcher.c | 46 ++++++++++++++++++++++++
 guix/self.scm                           | 48 ++++++++++++++++++++++++-
 3 files changed, 94 insertions(+), 1 deletion(-)
 create mode 100644 gnu/packages/aux-files/guile-launcher.c

diff --git a/Makefile.am b/Makefile.am
index 8e91e1e558..bc3efd2b6f 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -330,6 +330,7 @@ dist_noinst_DATA =				\
 
 # Auxiliary files for packages.
 AUX_FILES =						\
+  gnu/packages/aux-files/guile-launcher.c		\
   gnu/packages/aux-files/chromium/master-preferences.json		\
   gnu/packages/aux-files/emacs/guix-emacs.el		\
   gnu/packages/aux-files/linux-libre/5.8-arm.conf       \
diff --git a/gnu/packages/aux-files/guile-launcher.c b/gnu/packages/aux-files/guile-launcher.c
new file mode 100644
index 0000000000..886ede2846
--- /dev/null
+++ b/gnu/packages/aux-files/guile-launcher.c
@@ -0,0 +1,46 @@
+/* GNU Guix --- Functional package management for GNU
+   Copyright 1996-1997,2000-2001,2006,2008,2011,2013,2018
+      Free Software Foundation, Inc.
+   Copyright (C) 2020 Ludovic Courtès <[email-masked]>
+
+   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/>.  */
+
+/* This file implements a variant of the 'guile' executable that does not
+   complain about locale issues.  */
+
+#include <locale.h>
+#include <libguile.h>
+
+static void
+inner_main (void *unused, int argc, char **argv)
+{
+  scm_shell (argc, argv);
+}
+
+int
+main (int argc, char **argv)
+{
+  /* Try to install the current locale; remain silent if it fails.  */
+  if (setlocale (LC_ALL, "") == NULL)
+    /* The 'guix pull'-provided 'guix' includes at least en_US.utf8 so use
+       that.  That gives us UTF-8 support for 'scm_to_locale_string', etc.,
+       which is always preferable over the C locale.  */
+    setlocale (LC_ALL, "en_US.utf8");
+
+  scm_install_gmp_memory_functions = 1;
+  scm_boot_guile (argc, argv, inner_main, 0);
+  return 0; /* never reached */
+}
diff --git a/guix/self.scm b/guix/self.scm
index 5eb80f42fe..bbfd2f1b95 100644
--- a/guix/self.scm
+++ b/guix/self.scm
@@ -27,6 +27,7 @@
   #:use-module (guix packages)
   #:use-module (guix sets)
   #:use-module (guix modules)
+  #:use-module ((guix utils) #:select (version-major+minor))
   #:use-module ((guix build utils) #:select (find-files))
   #:use-module (srfi srfi-1)
   #:use-module (srfi srfi-9)
@@ -62,6 +63,7 @@
       ("xz"         (ref '(gnu packages compression) 'xz))
       ("po4a"       (ref '(gnu packages gettext) 'po4a))
       ("gettext"       (ref '(gnu packages gettext) 'gettext-minimal))
+      ("gcc-toolchain" (ref '(gnu packages commencement) 'gcc-toolchain))
       (_            #f))))                        ;no such package
 
 
@@ -580,6 +582,48 @@ that provide Guile modules."
 
   (computed-file name build))
 
+(define (quiet-guile guile)
+  "Return a wrapper that does the same as the 'guile' executable of GUILE,
+except that it does not complain about locales and falls back to 'en_US.utf8'
+instead of 'C'."
+  (define gcc
+    (specification->package "gcc-toolchain"))
+
+  (define source
+    (search-path %load-path
+                 "gnu/packages/aux-files/guile-launcher.c"))
+
+  (define effective
+    (version-major+minor (package-version guile)))
+
+  (define build
+    ;; XXX: Reuse <c-compiler> from (guix scripts pack) instead?
+    (with-imported-modules '((guix build utils))
+      #~(begin
+          (use-modules (guix build utils)
+                       (srfi srfi-26))
+
+          (mkdir-p (string-append #$output "/bin"))
+
+          (setenv "PATH" #$(file-append gcc "/bin"))
+          (setenv "C_INCLUDE_PATH"
+                  (string-join
+                   (map (cut string-append <> "/include")
+                        '#$(match (bag-transitive-build-inputs
+                                   (package->bag guile))
+                             (((labels packages . _) ...)
+                              (filter package? packages))))
+                   ":"))
+          (setenv "LIBRARY_PATH" #$(file-append gcc "/lib"))
+
+          (invoke "gcc" #$(local-file source) "-Wall" "-g0" "-O2"
+                  "-I" #$(file-append guile "/include/guile/" effective)
+                  "-L" #$(file-append guile "/lib")
+                  #$(string-append "-lguile-" effective)
+                  "-o" (string-append #$output "/bin/guile")))))
+
+  (computed-file "guile-wrapper" build))
+
 (define* (guix-command modules
                        #:key source (dependencies '())
                        guile (guile-version (effective-version)))
@@ -634,7 +678,9 @@ load path."
                       ;; XXX: It would be more convenient to change it to:
                       ;;   (exit (apply guix-main (command-line)))
                       (apply guix-main (command-line))))
-                #:guile guile))
+
+                ;; Use a 'guile' variant that doesn't complain about locales.
+                #:guile (quiet-guile guile)))
 
 (define (miscellaneous-files source)
   "Return data files taken from SOURCE."
-- 
2.28.0