From beb9975ed28e12b78f7043d76f2895c97cd7e4a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ludovic=20Court=C3=A8s?= Date: Thu, 24 Sep 2015 21:03:45 +0200 Subject: [PATCH 2/2] system: locale: Add a 'glibc-for-locales' knob. * gnu/system.scm ()[glibc-for-locales]: New field. (operating-system-locale-directory): Honor it. * gnu/system/locale.scm (sanity-check): New procedure. (locale-directory): Use it. * doc/guix.texi (Locales)[Locale Data Compatibility Considerations]: New section. --- doc/guix.texi | 42 +++++++++++++++++++++++ gnu/system.scm | 5 ++- gnu/system/locale.scm | 95 +++++++++++++++++++++++++++++++++------------------ 3 files changed, 108 insertions(+), 34 deletions(-) diff --git a/doc/guix.texi b/doc/guix.texi index 07c5add..6c0adda 100644 --- a/doc/guix.texi +++ b/doc/guix.texi @@ -5158,6 +5158,10 @@ 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{glibc-for-locales} (default: @var{glibc-2.21}) +The GNU@tie{}libc package whose locale data and tools are used to build +the locale definitions. @xref{Locales}. + @item @code{name-service-switch} (default: @var{%default-nss}) Configuration of libc's name service switch (NSS)---a @code{} object. @xref{Name Service Switch}, for @@ -5615,6 +5619,44 @@ 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{glibc-for-locales} +field to specify the GNU@tie{}libc package that is 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 may be incompatible from one libc version to another. + +@c See +@c and . +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.}. On the +other hand, a program linked against libc 2.22 can read locale data from +libc 2.21, except for @code{LC_COLLATE} data; 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, users can also install their own locale data and define +@var{LOCPATH} accordingly (@pxref{locales-and-locpath, @code{LOCPATH} +and locale packages}). + +Still, it is best if the system-wide locale data at +@file{/run/current-system/locale} is built using an older libc. That +way, both programs linked against the new libc and programs linked +against the older one can load locale data. For this reason, the +@code{glibc-for-locales} field defaults to a libc version slightly older +than the current one, with the caveat that some locale categories may be +incompatible. + + @node Services @subsection Services diff --git a/gnu/system.scm b/gnu/system.scm index cee5f37..8b5f981 100644 --- a/gnu/system.scm +++ b/gnu/system.scm @@ -146,6 +146,8 @@ (default "en_US.utf8")) (locale-definitions operating-system-locale-definitions ; list of (default %default-locale-definitions)) + (glibc-for-locales operating-system-glibc-for-locales ; + (default glibc-2.21)) (name-service-switch operating-system-name-service-switch ; (default %default-nss)) @@ -866,7 +868,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) + #:libc (operating-system-glibc-for-locales 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 393dd42..f7e17f8 100644 --- a/gnu/system/locale.scm +++ b/gnu/system/locale.scm @@ -20,8 +20,11 @@ #:use-module (guix gexp) #:use-module (guix records) #:use-module (gnu packages base) + #:use-module (gnu packages guile) + #:use-module (gnu packages linux) #:use-module (gnu packages compression) #:use-module (srfi srfi-26) + #:use-module (ice-9 match) #:export (locale-definition locale-definition? locale-definition-name @@ -59,6 +62,25 @@ (string-append #$output "/" #$(locale-definition-name locale)))))) +(define (sanity-check locale-data locale) + "Return an expression that returns true if a program linked against the +current glibc package can read locale data for LOCALE from LOCALE-DATA." + #~(begin + (format #t "checking whether current libc can \ +load this locale data from '~a'...~%" + #$locale-data) + (setenv "LOCPATH" #$locale-data) + (setenv "LC_ALL" #$locale) + + ;; If this fails with an assertion failure, then this is bad. See + ;; + ;; and . + ;; We can't check whether (setlocale LC_ALL "") works because it is + ;; likely to fail, at least because of one locale category whose data + ;; format has changed incompatibly. + (zero? (system* (string-append #$(canonical-package glibc) + "/bin/locale"))))) + (define* (locale-directory locales #:key (libc (canonical-package glibc))) "Return a directory containing all of LOCALES compiled." @@ -70,8 +92,15 @@ (setenv "PATH" (string-append #$gzip "/bin")) (exit - (and #$@(map (cut localedef-command <> #:libc libc) - locales))))) + (and (system* (string-append #$libc "/bin/localedef") "--version") + #$@(map (cut localedef-command <> #:libc libc) + locales) + #$(match locales + ((first . _) + (sanity-check #~#$output + (locale-definition-name first))) + (() + #t)))))) (gexp->derivation "locale" build #:local-build? #t)) @@ -97,37 +126,37 @@ (source "en_US") (charset "UTF-8")) (utf8-locales "ca_ES" - "cs_CZ" - "da_DK" - "de_DE" - "el_GR" - "en_AU" - "en_CA" - "en_GB" - "en_US" - "es_AR" - "es_CL" - "es_ES" - "es_MX" - "fi_FI" - "fr_BE" - "fr_CA" - "fr_CH" - "fr_FR" - "ga_IE" - "it_IT" - "ja_JP" - "ko_KR" - "nb_NO" - "nl_NL" - "pl_PL" - "pt_PT" - "ro_RO" - "ru_RU" - "sv_SE" - "tr_TR" - "uk_UA" - "vi_VN" + ;; "cs_CZ" + ;; "da_DK" + ;; "de_DE" + ;; "el_GR" + ;; "en_AU" + ;; "en_CA" + ;; "en_GB" + ;; "en_US" + ;; "es_AR" + ;; "es_CL" + ;; "es_ES" + ;; "es_MX" + ;; "fi_FI" + ;; "fr_BE" + ;; "fr_CA" + ;; "fr_CH" + ;; "fr_FR" + ;; "ga_IE" + ;; "it_IT" + ;; "ja_JP" + ;; "ko_KR" + ;; "nb_NO" + ;; "nl_NL" + ;; "pl_PL" + ;; "pt_PT" + ;; "ro_RO" + ;; "ru_RU" + ;; "sv_SE" + ;; "tr_TR" + ;; "uk_UA" + ;; "vi_VN" "zh_CN")))) ;;; locale.scm ends here -- 2.5.0