* gnu/packages/patches/glibc-versioned-locpath.patch: New file.
* gnu-system.am (dist_patch_DATA): Add it.
* gnu/packages/base.scm (glibc)[source]: Use it.
[arguments]: Remove explicit version sub-directory from
libc_cv_localedir.
(glibc-locales, glibc-utf8-locales): Write to a VERSION
sub-directory.
---
gnu-system.am | 1 +
gnu/packages/base.scm | 17 ++++----
gnu/packages/patches/glibc-versioned-locpath.patch | 47 ++++++++++++++++++++++
3 files changed, 56 insertions(+), 9 deletions(-)
create mode 100644 gnu/packages/patches/glibc-versioned-locpath.patch
diff --git a/gnu-system.am b/gnu-system.am
index aba8f8d..3aa9144 100644
--- a/gnu-system.am
+++ b/gnu-system.am
@@ -473,6 +473,7 @@ dist_patch_DATA = \
gnu/packages/patches/glibc-ldd-x86_64.patch \
gnu/packages/patches/glibc-locales.patch \
gnu/packages/patches/glibc-o-largefile.patch \
+ gnu/packages/patches/glibc-versioned-locpath.patch \
gnu/packages/patches/gmp-arm-asm-nothumb.patch \
gnu/packages/patches/gnucash-price-quotes-perl.patch \
gnu/packages/patches/gnutls-doc-fix.patch \
diff --git a/gnu/packages/base.scm b/gnu/packages/base.scm
index 337fdae..443c54e 100644
--- a/gnu/packages/base.scm
+++ b/gnu/packages/base.scm
@@ -477,6 +477,7 @@ store.")
(patches (map search-patch
'("glibc-ldd-x86_64.patch"
"glibc-guix-locpath.patch"
+ "glibc-versioned-locpath.patch"
"glibc-o-largefile.patch")))))
(build-system gnu-build-system)
@@ -510,16 +511,12 @@ store.")
;; Set the default locale path. In practice, $LOCPATH may be
;; defined to point whatever locales users want. However, setuid
;; binaries don't honor $LOCPATH, so they'll instead look into
- ;; $libc_cv_localedir; we choose /run/current-system/locale/X.Y,
+ ;; $libc_cv_localedir; we choose /run/current-system/locale
;; with the idea that it is going to be populated by the sysadmin.
- ;; The "X.Y" sub-directory is because locale data formats are
- ;; incompatible across libc versions; see
- ;; <https://lists.gnu.org/archive/html/guix-devel/2015-08/msg00737.html>.
;;
;; `--localedir' is not honored, so work around it.
;; See <http://sourceware.org/ml/libc-alpha/2013-03/msg00093.html>.
- (string-append "libc_cv_localedir=/run/current-system/locale/"
- ,version)
+ "libc_cv_localedir=/run/current-system/locale"
(string-append "--with-headers="
(assoc-ref %build-inputs "linux-headers")
@@ -655,7 +652,8 @@ the 'share/locale' sub-directory of this package.")
;; Use $(libdir)/locale as is the case by default.
(list (string-append "libc_cv_localedir="
(assoc-ref %outputs "out")
- "/lib/locale")))))))))
+ "/lib/locale/"
+ ,(package-version glibc))))))))))
(define-public glibc-utf8-locales
(package
@@ -664,7 +662,7 @@ the 'share/locale' sub-directory of this package.")
(source #f)
(build-system trivial-build-system)
(arguments
- '(#:modules ((guix build utils))
+ `(#:modules ((guix build utils))
#:builder (begin
(use-modules (srfi srfi-1)
(guix build utils))
@@ -672,7 +670,8 @@ the 'share/locale' sub-directory of this package.")
(let* ((libc (assoc-ref %build-inputs "glibc"))
(gzip (assoc-ref %build-inputs "gzip"))
(out (assoc-ref %outputs "out"))
- (localedir (string-append out "/lib/locale")))
+ (localedir (string-append out "/lib/locale/"
+ ,version)))
;; 'localedef' needs 'gzip'.
(setenv "PATH" (string-append libc "/bin:" gzip "/bin"))
diff --git a/gnu/packages/patches/glibc-versioned-locpath.patch b/gnu/packages/patches/glibc-versioned-locpath.patch
new file mode 100644
index 0000000..b643399
--- /dev/null
+++ b/gnu/packages/patches/glibc-versioned-locpath.patch
@@ -0,0 +1,47 @@
+The format of locale data can be incompatible between libc versions, and
+loading incompatible data can lead to 'setlocale' returning EINVAL at best
+or triggering an assertion failure at worst. See
+https://lists.gnu.org/archive/html/guix-devel/2015-09/msg00717.html
+for background information.
+
+To address that, this patch changes libc to look for locale data in
+version-specific sub-directories. So, if LOCPATH=/foo:/bar, locale data
+is searched for in /foo/X.Y and /bar/X.Y, where X.Y is the libc version
+number.
+
+That way, a single 'LOCPATH' setting can work even if different libc versions
+coexist on the system.
+
+--- a/intl/l10nflist.c
++++ b/intl/l10nflist.c
+@@ -25,6 +25,10 @@
+ # include <config.h>
+ #endif
+
++#ifdef _LIBC
++# include <version.h>
++#endif
++
+ #include <string.h>
+
+ #if defined _LIBC || defined HAVE_ARGZ_H
+@@ -164,6 +168,9 @@ _nl_make_l10nflist (struct loaded_l10nfile **l10nfile_list,
+
+ /* Allocate room for the full file name. */
+ abs_filename = (char *) malloc (dirlist_len
++#ifdef _LIBC
++ + strlen (VERSION) + 1
++#endif
+ + strlen (language)
+ + ((mask & XPG_TERRITORY) != 0
+ ? strlen (territory) + 1 : 0)
+@@ -185,6 +192,10 @@ _nl_make_l10nflist (struct loaded_l10nfile **l10nfile_list,
+ memcpy (abs_filename, dirlist, dirlist_len);
+ __argz_stringify (abs_filename, dirlist_len, ':');
+ cp = abs_filename + (dirlist_len - 1);
++#ifdef _LIBC
++ *cp++ = '/';
++ cp = stpcpy (cp, VERSION);
++#endif
+ *cp++ = '/';
+ cp = stpcpy (cp, language);