+
Skip to content

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

Closed
wants to merge 1 commit into from

Conversation

ThomasAdam
Copy link
Member

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.

@ThomasAdam ThomasAdam added this to the 1.1.3 milestone Apr 12, 2025
@ThomasAdam ThomasAdam added this to FVWM3 Apr 12, 2025
@github-project-automation github-project-automation bot moved this to PRs in FVWM3 Apr 12, 2025
@ThomasAdam ThomasAdam added the area:build Relates to compiling/buildsystem of fvwm label Apr 12, 2025
@ThomasAdam ThomasAdam self-assigned this Apr 12, 2025
@ThomasAdam ThomasAdam force-pushed the ta/meson-build branch 2 times, most recently from 9901194 to 5868db9 Compare April 13, 2025 10:27
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.
Comment on lines +276 to +289

# 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

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.

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.

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.

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

if cc.has_header_symbol('libcharset.h', 'locale_charset')
. If 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.

Copy link
Member Author

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

if cc.has_header_symbol('libcharset.h', 'locale_charset')

. If 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.

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. :)

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.

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.

Copy link

@eli-schwartz eli-schwartz May 19, 2025

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.

Copy link

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

  1. not all systems have nl_langinfo (CODESET), cf. https://www.gnu.org/software/gnulib/manual/html_node/nl_005flanginfo.html
  2. 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).

Copy link

@eli-schwartz eli-schwartz May 19, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fvwm3/libs/FlocaleCharset.c

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);

'nl_langinfo': {'have': 'HAVE_CODESET'},

#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.

Kangie added a commit to Kangie/fvwm3 that referenced this pull request May 23, 2025
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>
ThomasAdam pushed a commit that referenced this pull request May 29, 2025
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>
@ThomasAdam ThomasAdam removed this from the 1.1.3 milestone May 29, 2025
@ThomasAdam ThomasAdam added the skip:changelog Issue/PR should skip CHANGELOG label May 29, 2025
@ThomasAdam
Copy link
Member Author

Thanks all. Spoken with @Kangie who has provided PR #1203 -- I've tested this on a fair few systems now and this appears to work fine for me.

Thanks for all your help with this.

@ThomasAdam ThomasAdam closed this May 29, 2025
@github-project-automation github-project-automation bot moved this from PRs to Done in FVWM3 May 29, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area:build Relates to compiling/buildsystem of fvwm skip:changelog Issue/PR should skip CHANGELOG
Projects
Status: Done
Development

Successfully merging this pull request may close these issues.

4 participants
点击 这是indexloc提供的php浏览器服务,不要输入任何密码和下载