locale-util: drop libintl dependency

Both glibc and musl provides dgettext(). Hence it is not necessary to
use libintl.so provided by gettext.

This partially reverts 590e226437,
fully reverts commit e6e65dc261 and
bd19ffd9cb.

Then, introduce minimal libintl.h for musl build, to avoid using
libintl.h by gettext, which is typically installed on musl-based
build systems.
This commit is contained in:
Yu Watanabe
2026-06-29 23:22:41 +09:00
parent 04c0b735a7
commit 25714364a9
6 changed files with 8 additions and 75 deletions
-7
View File
@@ -1011,13 +1011,6 @@ endif
libm = cc.find_library('m')
# Header presence check only — dgettext itself is resolved via dlopen_libintl() at runtime, so we never
# link against libintl. On glibc dgettext lives in libc; on musl gettext-dev provides libintl.h alongside
# libintl.so.8 which we dlopen() if present.
if not cc.has_header('libintl.h')
error('libintl.h not found (install gettext / gettext-dev)')
endif
# On some architectures, libatomic is required. But on some installations,
# it is found, but actual linking fails. So let's try to use it opportunistically.
# If it is installed, but not needed, it will be dropped because of --as-needed.
-27
View File
@@ -7,12 +7,7 @@
#include <sys/stat.h>
#include <unistd.h>
#ifndef __GLIBC__
#include "sd-dlopen.h"
#endif
#include "dirent-util.h"
#include "dlfcn-util.h"
#include "env-util.h"
#include "fd-util.h"
#include "fileio.h"
@@ -27,28 +22,6 @@
#include "strv.h"
#include "utf8.h"
#ifdef __GLIBC__
DLSYM_PROTOTYPE(dgettext) = dgettext;
#else
DLSYM_PROTOTYPE(dgettext) = NULL;
#endif
int dlopen_libintl(int log_level) {
#ifdef __GLIBC__
return 1;
#else
static void *libintl_dl = NULL;
LIBINTL_NOTE(SD_ELF_NOTE_DLOPEN_PRIORITY_SUGGESTED);
return dlopen_many_sym_or_warn(
&libintl_dl,
"libintl.so.8",
log_level,
DLSYM_ARG(dgettext));
#endif
}
static char* normalize_locale(const char *name) {
const char *e;
+1 -29
View File
@@ -4,33 +4,7 @@
#include <libintl.h> /* IWYU pragma: export */
#include <locale.h> /* IWYU pragma: export */
#include "sd-dlopen.h" /* IWYU pragma: export */
#include "basic-forward.h"
#include "dlfcn-util.h"
/* format_arg(2) propagates the format-string nature of the second argument to the return value, so that
* printf(_("Hello %s"), name) still gets checked. It survives both DLSYM_PROTOTYPE's typeof() and the
* ternary in _() below — verified on gcc and clang. */
extern DLSYM_PROTOTYPE(dgettext) __attribute__((format_arg(2)));
int dlopen_libintl(int log_level);
#ifdef __GLIBC__
#define DLOPEN_LIBINTL(log_level, priority) dlopen_libintl(log_level)
#else
#define LIBINTL_NOTE(priority) \
SD_ELF_NOTE_DLOPEN("intl", \
"Support for message translation via gettext", \
priority, \
"libintl.so.8")
#define DLOPEN_LIBINTL(log_level, priority) \
({ \
LIBINTL_NOTE(priority); \
dlopen_libintl(log_level); \
})
#endif
typedef enum LocaleVariable {
/* We don't list LC_ALL here on purpose. People should be
@@ -58,9 +32,7 @@ int get_locales(char ***ret);
bool locale_is_valid(const char *name);
int locale_is_installed(const char *name);
/* Falls back to the untranslated string if dlopen_libintl() hasn't run or has failed, so callers don't have
* to gate every translatable message on a runtime check. */
#define _(String) (sym_dgettext ? sym_dgettext(GETTEXT_PACKAGE, (String)) : (String))
#define _(String) dgettext(GETTEXT_PACKAGE, String)
#define N_(String) String
bool is_locale_utf8(void);
-10
View File
@@ -790,8 +790,6 @@ _public_ PAM_EXTERN int pam_sm_authenticate(
if (r < 0)
return PAM_SERVICE_ERR;
(void) DLOPEN_LIBINTL(LOG_DEBUG, SD_ELF_NOTE_DLOPEN_PRIORITY_RECOMMENDED); /* best-effort: messages won't be translated if this fails */
pam_log_setup();
if (parse_env(pamh, &flags) < 0)
@@ -857,8 +855,6 @@ _public_ PAM_EXTERN int pam_sm_open_session(
if (r < 0)
return PAM_SERVICE_ERR;
(void) DLOPEN_LIBINTL(LOG_DEBUG, SD_ELF_NOTE_DLOPEN_PRIORITY_RECOMMENDED); /* best-effort: messages won't be translated if this fails */
pam_log_setup();
if (parse_env(pamh, &flags) < 0)
@@ -916,8 +912,6 @@ _public_ PAM_EXTERN int pam_sm_close_session(
if (r < 0)
return PAM_SERVICE_ERR;
(void) DLOPEN_LIBINTL(LOG_DEBUG, SD_ELF_NOTE_DLOPEN_PRIORITY_RECOMMENDED); /* best-effort: messages won't be translated if this fails */
pam_log_setup();
if (parse_argv(pamh,
@@ -983,8 +977,6 @@ _public_ PAM_EXTERN int pam_sm_acct_mgmt(
if (r < 0)
return PAM_SERVICE_ERR;
(void) DLOPEN_LIBINTL(LOG_DEBUG, SD_ELF_NOTE_DLOPEN_PRIORITY_RECOMMENDED); /* best-effort: messages won't be translated if this fails */
pam_log_setup();
if (parse_env(pamh, &flags) < 0)
@@ -1104,8 +1096,6 @@ _public_ PAM_EXTERN int pam_sm_chauthtok(
if (r < 0)
return PAM_SERVICE_ERR;
(void) DLOPEN_LIBINTL(LOG_DEBUG, SD_ELF_NOTE_DLOPEN_PRIORITY_RECOMMENDED); /* best-effort: messages won't be translated if this fails */
pam_log_setup();
if (parse_argv(pamh,
+7
View File
@@ -0,0 +1,7 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#pragma once
/* On musl-based systems, libintl.h may be provided by GNU gettext even though musl itself provides
* dgettext(). Declare dgettext() directly to avoid an unnecessary dependency on libintl.so. */
char* dgettext(const char *domainname, const char *msgid) __attribute__((format_arg(2)));
-2
View File
@@ -18,7 +18,6 @@
#include "libcrypt-util.h"
#include "libfido2-util.h"
#include "libmount-util.h"
#include "locale-util.h"
#include "main-func.h"
#include "microhttpd-util.h"
#include "module-util.h"
@@ -66,7 +65,6 @@ static int run(int argc, char **argv) {
ASSERT_DLOPEN(dlopen_libblkid, HAVE_BLKID);
ASSERT_DLOPEN(dlopen_libcrypt, HAVE_LIBCRYPT);
ASSERT_DLOPEN(dlopen_libfido2, HAVE_LIBFIDO2);
ASSERT_OK(dlopen_libintl(LOG_DEBUG)); /* Required to be available at build time. */
ASSERT_DLOPEN(dlopen_libkmod, HAVE_KMOD);
ASSERT_DLOPEN(dlopen_libmount, HAVE_LIBMOUNT);
ASSERT_DLOPEN(dlopen_libpam, HAVE_PAM);