This issue was coming from "NM=llvm-nm.exe". I was setting some of variables to use llvm tools, since they are installed alongside clang-cl.exe. I *did not* expect this to cause any issues, since most packages were building successfully.
It was happening when libtool was running $NM on all object files. With llvm-nm.exe it was marking sprintf for export, while with dumpbin.exe it was not. Btw, this is the feature we mentioned on libtool mailing list. I think it is safe to assume that other unwanted symbols were exported as well. Interesting thing is that both llvm-nm.exe and dumpbin.exe *do* list sprintf function as a defined symbol (unless I misunderstand their output). Should this be considered a libtool bug? With "dumpbin -symbols": ``` 019 00000000 SECT8 notype () External | sprintf ``` With "llvm-nm -A": ``` ./srclib/libicrt_a-strerror.obj: 00000000 T sprintf ``` After changing to NM="dumpbin.exe -nologo -symbols" (which I use with cl.exe), both libtextstyle and libunistring build successfully. - Kirill Makurin ________________________________ From: bug-gnulib-bounces+maiddaisuki=outlook....@gnu.org <bug-gnulib-bounces+maiddaisuki=outlook....@gnu.org> on behalf of Kirill Makurin <maiddais...@outlook.com> Sent: Monday, June 16, 2025 9:26 AM To: Bruno Haible <br...@clisp.org> Cc: bug-gnulib@gnu.org <bug-gnulib@gnu.org> Subject: Re: clang-cl: undeclared library function 'sprintf' Thanks for the info. Now I see that affected files are compiled twice and only the second compilation fails. I will try to find out what causes iconv-2.dll to export sprintf. It should at least give us some answers. - Kirill Makurin ________________________________ From: Bruno Haible <br...@clisp.org> Sent: Monday, June 16, 2025 8:56 AM To: Kirill Makurin <maiddais...@outlook.com> Cc: bug-gnulib@gnu.org <bug-gnulib@gnu.org> Subject: Re: clang-cl: undeclared library function 'sprintf' Kirill Makurin wrote: > I tried further investigate this issue and I have discovered that > libtextstyle/lib/config.h contains following lines: > > ``` > #define sprintf libtextstyle_sprintf > #define sscanf libtextstyle_sscanf > ``` > > Since config.h is included before any system header file, later when system's > stdio.h is included, I assume this macro is defined and instead of > declaring/defining inline sprintf it ends up declaring/defining > libtextstyle_sprintf. What you are seeing here is similar to what you saw with iconv-2.dll: These config.h lines get generated by libtextstyle/lib/Makefile.am: In a first pass all object files are compiled without these #defines, then the exported symbols of these files (look at the file 'exported.sh') are collected and remapped to symbols with a 'libtextstyle_' prefix. So, it means that during this first pass, at least one object file had 'sprintf' as an exported symbol, and likewise for 'sscanf'. libiconv does not have this same compilation-in-two-passes technique; this is why there the symbol 'sprintf' is exported without a prefix. Still, the origin seems to be the same: the MSVC headers must contain some inlinable definition of sprintf and sscanf, and your 'clang-cl' must be stuffing these into the object files as exported symbols. Which, as you noted, is a no-go for shared libraries. Bruno