-
-
Notifications
You must be signed in to change notification settings - Fork 85
meson: set -liconv implicitly when iconv found #1186
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
9901194
to
5868db9
Compare
If iconv is found, it's possible that -liconv needs to be specified. But we can only do this if the linker allows for -liconv. On some systems, -liconv isn't needed, so we need to check for this.
5868db9
to
621ece6
Compare
|
||
# Look to see if -liconv can be used; on some platforms where iconv | ||
# is installed, -liconv might beed to be supplied; but isn't always | ||
# supported (Archinux, for example). | ||
# | ||
# Note that the point of this test program isn't to be iconv-specific | ||
# but to be sufficient enough to pass -liconv to test its existence. | ||
linker_iconv_code = 'void a(void) {}; void _start(void) { a(); }' | ||
linker_iconv_args = ['-lc', '-Wl'] | ||
if cc.links(linker_iconv_code, | ||
name : 'linker supports -liconv', | ||
args : [linker_iconv_args, '-liconv']) | ||
add_project_link_arguments('-liconv', language: 'c') | ||
endif |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I do not understand any of this.
Meson's builtin dependency('iconv')
attempts to search two different providers of iconv:
- builtin, checks if this code compiles and links using only -lc:
#include <iconv.h> int main() { iconv_open("",""); } ``
- system, checks if -liconv exists and
#include <iconv.h>
exists
The former case cannot and will not successfully compile and link if -liconv exists, since if -liconv exists then iconv.h will #define iconv_open libiconv_open
and linking will fail unless you provide libiconv_open
. And libc only provides iconv_open
, but -liconv
provides libiconv_open
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since this block already occurs inside if iconv.found()
, it stands to reason that if -liconv
exists, the iconv dependency already contains it. But, you could double check:
message('found iconv dependency using method: ' + iconv.type_name())
It will print either "builtin" or "system", and in the latter case it comes with -liconv
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Where precisely does one get -liconv
from? It is only relevant to systems NOT using GNU glibc. Arch Linux does not support non-glibc installation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the issue is at
Line 129 in 4592849
if cc.has_header_symbol('libcharset.h', 'locale_charset') |
libunistring
is installed, that check will fire and set HAVE_LIBCHARSET
, which will lead to locale_charset
being used, but nothing specifies we should link against libunistring.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the issue is at
Line 129 in 4592849
if cc.has_header_symbol('libcharset.h', 'locale_charset') . If
libunistring
is installed, that check will fire and setHAVE_LIBCHARSET
, which will lead tolocale_charset
being used, but nothing specifies we should link against libunistring.
Hey @thesamesam -- thanks for your comment here.
I looked into this, and outside of ArchLinux, also installed libunistring
. The issue did not occur, but still seems present on ArchLinux.
So my concern is what's best to fix this. Forgive me -- either your original premise here is incorrect -- or, it's ArchLinux speciic somehow.
Either way, we clearly need a solution which solves both of these.
I'll happily take any suggestions. :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll take a look and try reproduce in a container.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To obtain an undefined reference to locale_charset
as the user had, we have to refer to it in fvwm3.
The only place we do that is in libs/FlocaleCharset.c
with a call to Flocale_charset()
with:
#if FlocaleLibcharsetSupport
#define Flocale_charset() locale_charset()
#else
#define Flocale_charset() NULL
#endif
If I run pacman -S libiconv
(and libunistring
is already installed in this container, it seems), then the build fails for me with:
FAILED: modules/FvwmScript/FvwmScript
cc -o modules/FvwmScript/FvwmScript modules/FvwmScript/FvwmScript.p/FvwmScript.c.o modules/FvwmScript/FvwmScript.p/Instructions.c.o modules/FvwmScript/FvwmScript.p/libyywrap.c.o modules/FvwmScript/FvwmScript.p/scanner.c.o modules/FvwmScript/FvwmScript.p/script.c.o -Wl,--as-needed -Wl,--no-undefined -Wl,--start-group -lm -O3 -flto libs/libfvwm3.a modules/FvwmScript/libWidgets.a /usr/lib/libfontconfig.so /usr/lib/libICE.so /usr/lib/libevent.so /usr/lib/libX11.so /usr/lib/libXft.so /usr/lib/libXrandr.so /usr/lib/libXt.so /usr/lib/libXext.so /usr/lib/libxkbcommon.so /usr/lib/libreadline.so /usr/lib/libfreetype.so /usr/lib/libpng16.so /usr/lib/libSM.so /usr/lib/libXrender.so -Wl,--end-group
lto-wrapper: warning: using serial compilation of 5 LTRANS jobs
lto-wrapper: note: see the ‘-flto’ option documentation for more information
/usr/sbin/ld: /tmp/ccKjuck6.ltrans2.ltrans.o: in function `FlocaleCharsetInit.part.0.isra.0':
/fvwm3/build/../libs/FlocaleCharset.c:607:(.text+0x5ef0): undefined reference to `locale_charset'
collect2: error: ld returned 1 exit status
I think what makes it Arch-specific here is that it's unusual to allow libiconv
to be installed on a system with glibc installed, because it serves no purpose (and may well confuse configure checks like this). If libiconv
isn't installed, then the check for libcharset.h
is never going to succeed.
What confused me is that libunistring also provides locale_charset
if you want it.
So, all that said: if libcharset.h
is installed (from libiconv), HAVE_LIBCHARSET
gets set, and then we blow up when linking because we don't add -liconv
because Meson already checked if you need anything for the usual iconv functions (following Eli's algorithm at #1186 (comment)) and found it only needs libc.
What's not clear to me is what the cleanest way of fixing this is yet.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are two different headers, and three libraries, that provide a function called "locale_charset":
#include <unistring/localcharset.h>
&&gcc -lunistring
#include <localcharset.h>
&&gcc -lcharset
#include <localcharset.h>
&&gcc -liconv
Case 1 is provided by the libunistring software. Cases 3 and 3 are both provided by the libiconv software
I can't understand why case number 3 is even valid. I suspect @bhaible accidentally broke libiconv at some point and then had to preserve this forever. The ChangeLog inscrutably mentions GNU bash without any details.
The reason it doesn't matter whether you install libunistring is because you are not looking for the header name from libunistring!!! Therefore if libunistring is installed you don't detect locale_charset at all... only if libiconv is installed. If you do want libiconv's copy of locale_charset then maybe at least you should look for the correct library name, which is NOT -liconv
but rather -lcharset
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The locale_charset
function exists because
- not all systems have
nl_langinfo (CODESET)
, cf. https://www.gnu.org/software/gnulib/manual/html_node/nl_005flanginfo.html - on many systems, the values returned are not the same as on GNU systems. In order to avoid having to handle aliases in various places, it is the function
locale_charset
which maps system-dependent encoding names to GNU canonical encoding names (e.g. "ISO8859-1" → "ISO-8859-1", "UTF8" → "UTF-8").
locale_charset
is part of the GNU libunistring API, https://www.gnu.org/software/libunistring/manual/html_node/uniconv_002eh.html, but nothing in fvwm3 references libunistring, therefore there is no need to talk about it here.
The only other library that installs a header file that declares locale_charset
is GNU libiconv. It does so in two header files, libcharset.h
and localcharset.h
. fvwm3 includes libcharset.h
before using locale_charset ()
, which is fine.
GNU libiconv, however, is never supposed to be installed on GNU systems (such as Arch Linux or Gentoo with glibc). Therefore, on GNU systems, instead of asking "where can we get locale_charset
from", the question should be "why is it attempting to use locale_charset
? it should be using nl_langinfo (CODESET)
instead".
In other words, fvwm3 should use locale_charset
if and only if GNU libiconv has been found and is usable (i.e. you can link with it).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Lines 605 to 616 in 6370adf
if ((!charset || strlen(charset) < 3) && FlocaleLibcharsetSupport) | |
{ | |
charset = (char *)Flocale_charset(); | |
#if FLOCALE_DEBUG_CHARSET | |
fvwm_debug(__func__, | |
"[FlocaleInitCharset] FlocaleLibcharsetSupport: %s\n", | |
(!charset)? "null":charset); | |
#endif | |
} | |
if ((!charset || strlen(charset) < 3) && FlocaleCodesetSupport) | |
{ | |
charset = Fnl_langinfo(FCODESET); |
Line 147 in 6370adf
'nl_langinfo': {'have': 'HAVE_CODESET'}, |
Lines 14 to 24 in 6370adf
#ifdef HAVE_LIBCHARSET | |
#define FlocaleLibcharsetSupport 1 | |
#else | |
#define FlocaleLibcharsetSupport 0 | |
#endif | |
#ifdef HAVE_CODESET | |
#define FlocaleCodesetSupport 1 | |
#else | |
#define FlocaleCodesetSupport 0 | |
#endif |
It already is kinda doing that, but confusingly tries using header presence as a sentinel for "not GNU libc" and confuses it with implicit -liconv.
We can't just check for `locale_charset` as some (very silly) distributions ship, or allow end users to install, GNU libiconv on GNU libc systems. - Move `HAVE_CODESET` and `HAVE_LIBCHARSET` checks into `iconv` dep conditional - perform link test against libcharset to see if it is usable - add a visible warning that GNU libiconv should not be installed on a GNU libc system, if libcharset (libiconv) linking fails due to apparent conflicts with glibc iconv. See Also: fvwmorg#1186 Signed-off-by: Matt Jolly <kangie@gentoo.org>
We can't just check for `locale_charset` as some (very silly) distributions ship, or allow end users to install, GNU libiconv on GNU libc systems. - Move `HAVE_CODESET` and `HAVE_LIBCHARSET` checks into `iconv` dep conditional - perform link test against libcharset to see if it is usable - add a visible warning that GNU libiconv should not be installed on a GNU libc system, if libcharset (libiconv) linking fails due to apparent conflicts with glibc iconv. See Also: #1186 Signed-off-by: Matt Jolly <kangie@gentoo.org>
If iconv is found, make sure that it can be linked against, by
explicitly setting -liconv; there is no pkg-config option for it on some
systems.