From 70f89fd9c5deb8df0968f8a64faa4791f20479c9 Mon Sep 17 00:00:00 2001 From: Christophe CURIS Date: Mon, 17 May 2021 16:32:13 +0200 Subject: [PATCH] WRaster: Add initialisation for locale support Because the library does not have an initialisation function, we need to rely on an automatic called-on-load mechanism, which is provided through a compiler attribute 'constructor'. However, as the project aims to still compile on old hard/software, we include a check in 'configure' to ensure it works, and if not use the legacy solution. Note: Because we introduce a new DEFINE, the 'config.h.in' needs to be regenerated, otherwise you may get a compilation error in wrlib. This is done by re-running './autogen.sh' Signed-off-by: Christophe CURIS --- configure.ac | 10 ++++++ m4/wm_library_constructors.m4 | 67 +++++++++++++++++++++++++++++++++++ wrlib/misc.c | 21 +++++++++++ 3 files changed, 98 insertions(+) create mode 100644 m4/wm_library_constructors.m4 diff --git a/configure.ac b/configure.ac index de761848..4c0418d2 100644 --- a/configure.ac +++ b/configure.ac @@ -455,6 +455,7 @@ dnl that the gettext environment works WM_I18N_LANGUAGES WM_I18N_XGETTEXT WM_I18N_MENUTEXTDOMAIN +WM_LIBRARY_CONSTRUCTORS dnl =========================================== dnl Stuff that uses X @@ -978,6 +979,15 @@ AS_IF([test "x$enable_jpeg" = xno], [dnl AS_ECHO(["WARNING WARNING WARNING WARNING WARNING WARNING WARNING"])dnl ]) +AS_IF([test "x$LINGUAS" != "x"], + [AS_IF([test "X$wm_cv_library_constructors" = "Xlegacy"], + [AC_MSG_WARN([I18N is enabled, but library constructor attribute is not supported]) + AS_ECHO([" If you have translation problems in lib WRaster, yet you know that the translation"]) + AS_ECHO([" file (po) is valid, this could be a cause."]) + AS_ECHO([])dnl + ])dnl + ]) + dnl This is for Emacs. I'm lazy, I know... (nicolai) dnl ================================================ diff --git a/m4/wm_library_constructors.m4 b/m4/wm_library_constructors.m4 new file mode 100644 index 00000000..35250827 --- /dev/null +++ b/m4/wm_library_constructors.m4 @@ -0,0 +1,67 @@ +# wm_library_constructors.m4 - Macros to see if compiler supports attributes "constructors" for libraries +# +# Copyright (c) 2021 Christophe CURIS +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + + +# WM_LIBRARY_CONSTRUCTORS +# ----------------------- +# +# GCC introduced the attribute 'constructor' which says that a function must be +# called when a library is loaded (needed for C++ support). However this may not +# be totally portable, so we may use the old method "_init" as a fall-back +# solution, which is considered Obsolete/Dangerous. +# +# This is explained here: +# https://tldp.org/HOWTO/Program-Library-HOWTO/miscellaneous.html#INIT-AND-CLEANUP +# +# This macro is making sure that the compiler supports the attribute, because we +# need it for the WRaster library (see RStartup in wrlib/misc.c to see why). +AC_DEFUN_ONCE([WM_LIBRARY_CONSTRUCTORS], +[AC_CACHE_CHECK([how to declare a library constructor], [wm_cv_library_constructors], + [save_CFLAGS="$CFLAGS" + dnl We need this to cause a detectable failure in case of unsupported attribute name + dnl if we don't do this, we just get a warning and AC_COMPILE suppose it was ok. + CFLAGS="$CFLAGS -Werror" + AC_COMPILE_IFELSE( + [AC_LANG_SOURCE([[ +static int is_initialised = 0; + +void __attribute__ ((constructor)) special_function(void) +{ + is_initialised = 1; +} + +int main(int argc, char **argv) +{ + /* To avoid warning on unused parameters, they could cause a false failure */ + (void) argc; + (void) argv; + return (is_initialised)?0:1; +} +]]) ], + [wm_cv_library_constructors=attribute], + [wm_cv_library_constructors=legacy]) + CFLAGS="$save_CFLAGS"]) + dnl In a perfect world we should also make sure that the feature works, but that implies + dnl to be able to actually build and run a program, which is not compatible with a + dnl cross-compiling user setup + AS_IF([test "X$wm_cv_library_constructors" = "Xattribute"], + [AC_DEFINE([WLIB_CONSTRUCTOR(func_name)], [__attribute__ ((constructor)) func_name], + [Method for defining a library initialisation function])], + [AC_DEFINE([WLIB_CONSTRUCTOR(func_name)], [_init], + [Method for defining a library initialisation function])] ) +]) diff --git a/wrlib/misc.c b/wrlib/misc.c index c504a9a4..7cd1c0fa 100644 --- a/wrlib/misc.c +++ b/wrlib/misc.c @@ -245,6 +245,27 @@ const char *RMessageForError(int errorCode) } } +#ifdef I18N +/* + * Setup internationalization on startup + * + * For historical reason, the WRaster library does not have a function that + * user is supposed to call to initialise the library. Because we need to do + * some stuff now, we rely on the compiler attribute to tell this function + * has to be called automatically when library is loaded. + */ +void WLIB_CONSTRUCTOR(RStartup) (void) +{ + const char *locale_path; + + locale_path = getenv("NLSPATH"); + if (locale_path == NULL) + locale_path = LOCALEDIR; + + bindtextdomain("WRaster", locale_path); +} +#endif + /* * cleaning third-party libs at shutdown */