[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
02/03: system: Add 'locale-libcs' field.
From: |
Ludovic Courtès |
Subject: |
02/03: system: Add 'locale-libcs' field. |
Date: |
Fri, 30 Oct 2015 22:10:56 +0000 |
civodul pushed a commit to branch master
in repository guix.
commit 34760ae7031b19529aff2355cc458f61a8daa41f
Author: Ludovic Courtès <address@hidden>
Date: Fri Oct 30 23:05:52 2015 +0100
system: Add 'locale-libcs' field.
* gnu/system/locale.scm (localedef-command)[maybe-version-directory]:
New procedure.
Use it.
(locale-directory): Rename to...
(single-locale-directory): ... this. Check the version of LIBC to
determine whether to create a "X.Y" sub-directory or to make it a
symlink to ".". Add the version number in the derivation name.
(locale-directory): New procedure.
(%default-locale-libcs): New variable.
* gnu/system.scm (<operating-system>)[locale-libcs]: New field.
(operating-system-locale-directory): Pass it to 'locale-directory'.
* doc/guix.texi (operating-system Reference): Document 'locale-libcs'.
(Locales)[Locale Data Compatibility Considerations]: New section.
---
doc/guix.texi | 56 ++++++++++++++++++++++++++++++++++++++++++++
gnu/system.scm | 6 ++++-
gnu/system/locale.scm | 62 +++++++++++++++++++++++++++++++++++++++++++++----
3 files changed, 118 insertions(+), 6 deletions(-)
diff --git a/doc/guix.texi b/doc/guix.texi
index a23d824..a164608 100644
--- a/doc/guix.texi
+++ b/doc/guix.texi
@@ -5562,6 +5562,11 @@ Library Reference Manual}). @xref{Locales}, for more
information.
The list of locale definitions to be compiled and that may be used at
run time. @xref{Locales}.
address@hidden @code{locale-libcs} (default: @code{(list @var{glibc})})
+The list of address@hidden packages whose locale data and tools are used
+to build the locale definitions. @xref{Locales}, for compatibility
+considerations that justify this option.
+
@item @code{name-service-switch} (default: @var{%default-nss})
Configuration of libc's name service switch (NSS)---a
@code{<name-service-switch>} object. @xref{Name Service Switch}, for
@@ -6020,6 +6025,57 @@ instance it has @code{uk_UA.utf8} but @emph{not}, say,
@code{uk_UA.UTF-8}.
@end defvr
address@hidden Locale Data Compatibility Considerations
+
address@hidden incompatibility, of locale data
address@hidden declarations provide a @code{locale-libcs} field
+to specify the address@hidden packages that are used to compile locale
+declarations (@pxref{operating-system Reference}). ``Why would I
+care?'', you may ask. Well, it turns out that the binary format of
+locale data is occasionally incompatible from one libc version to
+another.
+
address@hidden See <https://sourceware.org/ml/libc-alpha/2015-09/msg00575.html>
address@hidden and
<https://lists.gnu.org/archive/html/guix-devel/2015-08/msg00737.html>.
+For instance, a program linked against libc version 2.21 is unable to
+read locale data produced with libc 2.22; worse, that program
address@hidden instead of simply ignoring the incompatible locale
address@hidden 2.23 and later of address@hidden will simply skip
+the incompatible locale data, which is already an improvement.}.
+Similarly, a program linked against libc 2.22 can read most, but not
+all, the locale data from libc 2.21 (specifically, @code{LC_COLLATE}
+data is incompatible); thus calls to @code{setlocale} may fail, but
+programs will not abort.
+
+The ``problem'' in GuixSD is that users have a lot of freedom: They can
+choose whether and when to upgrade software in their profiles, and might
+be using a libc version different from the one the system administrator
+used to build the system-wide locale data.
+
+Fortunately, unprivileged users can also install their own locale data
+and define @var{GUIX_LOCPATH} accordingly (@pxref{locales-and-locpath,
address@hidden and locale packages}).
+
+Still, it is best if the system-wide locale data at
address@hidden/run/current-system/locale} is built for all the libc versions
+actually in use on the system, so that all the programs can access
+it---this is especially crucial on a multi-user system. To do that, the
+administrator can specify several libc packages in the
address@hidden field of @code{operating-system}:
+
address@hidden
+(use-package-modules base)
+
+(operating-system
+ ;; @dots{}
+ (locale-libcs (list glibc-2.21 (canonical-package glibc))))
address@hidden example
+
+This example would lead to a system containing locale definitions for
+both libc 2.21 and the current version of libc in
address@hidden/run/current-system/locale}.
+
+
@node Services
@subsection Services
diff --git a/gnu/system.scm b/gnu/system.scm
index 3d570c0..8fed857 100644
--- a/gnu/system.scm
+++ b/gnu/system.scm
@@ -76,6 +76,7 @@
operating-system-timezone
operating-system-locale
operating-system-locale-definitions
+ operating-system-locale-libcs
operating-system-mapped-devices
operating-system-file-systems
operating-system-activation-script
@@ -144,6 +145,8 @@
(default "en_US.utf8"))
(locale-definitions operating-system-locale-definitions ; list of
<locale-definition>
(default %default-locale-definitions))
+ (locale-libcs operating-system-locale-libcs ; list of <packages>
+ (default %default-locale-libcs))
(name-service-switch operating-system-name-service-switch ;
<name-service-switch>
(default %default-nss))
@@ -643,7 +646,8 @@ listed in OS. The C library expects to find it under
(raise (condition
(&message (message "system locale lacks a definition")))))
- (locale-directory (operating-system-locale-definitions os)))
+ (locale-directory (operating-system-locale-definitions os)
+ #:libcs (operating-system-locale-libcs os)))
(define (kernel->grub-label kernel)
"Return a label for the GRUB menu entry that boots KERNEL."
diff --git a/gnu/system/locale.scm b/gnu/system/locale.scm
index 010fb45..e798827 100644
--- a/gnu/system/locale.scm
+++ b/gnu/system/locale.scm
@@ -18,11 +18,15 @@
(define-module (gnu system locale)
#:use-module (guix gexp)
+ #:use-module (guix store)
+ #:use-module (guix monads)
#:use-module (guix records)
#:use-module (guix packages)
+ #:use-module (guix utils)
#:use-module (gnu packages base)
#:use-module (gnu packages compression)
#:use-module (srfi srfi-26)
+ #:use-module (ice-9 match)
#:export (locale-definition
locale-definition?
locale-definition-name
@@ -31,6 +35,7 @@
locale-directory
+ %default-locale-libcs
%default-locale-definitions))
;;; Commentary:
@@ -50,6 +55,15 @@
(define* (localedef-command locale
#:key (libc (canonical-package glibc)))
"Return a gexp that runs 'localedef' from LIBC to build LOCALE."
+ (define (maybe-version-directory)
+ ;; XXX: For libc prior to 2.22, GuixSD did not store locale data in a
+ ;; version-specific sub-directory. Check whether this is the case.
+ ;; TODO: Remove this hack once libc 2.21 is buried.
+ (let ((version (package-version libc)))
+ (if (version>=? version "2.22")
+ (list version "/")
+ '())))
+
#~(begin
(format #t "building locale '~a'...~%"
#$(locale-definition-name locale))
@@ -58,20 +72,29 @@
"-i" #$(locale-definition-source locale)
"-f" #$(locale-definition-charset locale)
(string-append #$output "/"
- #$(package-version libc) "/"
+ #$@(maybe-version-directory)
#$(locale-definition-name locale))))))
-(define* (locale-directory locales
- #:key (libc (canonical-package glibc)))
+(define* (single-locale-directory locales
+ #:key (libc (canonical-package glibc)))
"Return a directory containing all of LOCALES for LIBC compiled.
Because locale data formats are incompatible when switching from one libc to
another, locale data is put in a sub-directory named after the 'version' field
of LIBC."
+ (define version
+ (package-version libc))
+
(define build
#~(begin
(mkdir #$output)
- (mkdir (string-append #$output "/" #$(package-version libc)))
+
+ ;; XXX: For libcs < 2.22, locale data is stored in the top-level
+ ;; directory.
+ ;; TODO: Remove this hack once libc 2.21 is buried.
+ #$(if (version>=? version "2.22")
+ #~(mkdir (string-append #$output "/" #$version))
+ #~(symlink "." (string-append #$output "/" #$version)))
;; 'localedef' executes 'gzip' to access compressed locale sources.
(setenv "PATH" (string-append #$gzip "/bin"))
@@ -80,9 +103,38 @@ of LIBC."
(and #$@(map (cut localedef-command <> #:libc libc)
locales)))))
- (gexp->derivation "locale" build
+ (gexp->derivation (string-append "locale-" version) build
#:local-build? #t))
+(define* (locale-directory locales
+ #:key (libcs %default-locale-libcs))
+ "Return a locale directory containing all of LOCALES for each libc package
+listed in LIBCS.
+
+It is useful to list more than one libc when willing to support
+already-installed packages built against a different libc since the locale
+data format changes between libc versions."
+ (match libcs
+ ((libc)
+ (single-locale-directory locales #:libc libc))
+ ((libcs ..1)
+ (mlet %store-monad ((dirs (mapm %store-monad
+ (lambda (libc)
+ (single-locale-directory locales
+ #:libc libc))
+ libcs)))
+ (gexp->derivation "locale-multiple-versions"
+ #~(begin
+ (use-modules (guix build union))
+ (union-build #$output (list address@hidden)))
+ #:modules '((guix build union))
+ #:local-build? #t
+ #:substitutable? #f)))))
+
+(define %default-locale-libcs
+ ;; The libcs for which we build locales by default.
+ (list (canonical-package glibc)))
+
(define %default-locale-definitions
;; Arbitrary set of locales that are built by default. They are here mostly
;; to facilitate first-time use to some people, while others may have to add