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.
This commit is contained in:
parent
137d957ed3
commit
34760ae703
|
@ -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}.
|
||||
|
||||
@item @code{locale-libcs} (default: @code{(list @var{glibc})})
|
||||
The list of GNU@tie{}libc 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
|
||||
|
||||
@subsubsection Locale Data Compatibility Considerations
|
||||
|
||||
@cindex incompatibility, of locale data
|
||||
@code{operating-system} declarations provide a @code{locale-libcs} field
|
||||
to specify the GNU@tie{}libc 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.
|
||||
|
||||
@c See <https://sourceware.org/ml/libc-alpha/2015-09/msg00575.html>
|
||||
@c 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
|
||||
@emph{aborts} instead of simply ignoring the incompatible locale
|
||||
data@footnote{Versions 2.23 and later of GNU@tie{}libc 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,
|
||||
@code{GUIX_LOCPATH} and locale packages}).
|
||||
|
||||
Still, it is best if the system-wide locale data at
|
||||
@file{/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
|
||||
@code{locale-libcs} field of @code{operating-system}:
|
||||
|
||||
@example
|
||||
(use-package-modules base)
|
||||
|
||||
(operating-system
|
||||
;; @dots{}
|
||||
(locale-libcs (list glibc-2.21 (canonical-package glibc))))
|
||||
@end example
|
||||
|
||||
This example would lead to a system containing locale definitions for
|
||||
both libc 2.21 and the current version of libc in
|
||||
@file{/run/current-system/locale}.
|
||||
|
||||
|
||||
@node Services
|
||||
@subsection Services
|
||||
|
||||
|
|
|
@ -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."
|
||||
|
|
|
@ -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 #$@dirs)))
|
||||
#: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
|
||||
|
|
Loading…
Reference in New Issue