Kirill Makurin wrote:
> This issue was coming from "NM=llvm-nm.exe".
Well, I think the issue has two causes:
1) The MSVC <stdio.h> defines some functions, such as sprintf, as
non-static inline functions by default.
You can see that it is independent of the compiler and independent
of whether 'dumpbin' or 'llvm-nm' is used to inspect the object file:
$ cat hello.c
#include <stdio.h>
#include <stdlib.h>
int main () {
printf("Hello world\n");
fflush(stdout);
return 0;
}
$ cl -c -Os hello.c
$ dumpbin -nologo -symbols hello.obj | grep External | grep -v UNDEF
011 00000000 SECT5 notype () External | __local_stdio_printf_options
015 00000000 SECT6 notype () External | _vfprintf_l
016 00000000 SECT7 notype () External | printf
017 00000000 SECT4 notype () External | main
$ llvm-nm hello.obj | grep ' [A-TV-Z] '
00000008 C ?_OptionsStorage@?1??__local_stdio_printf_options@@9@9
00000000 T __local_stdio_printf_options
00000000 T _vfprintf_l
00000000 T main
00000000 T printf
$ clang-cl -c -Os hello.c
$ dumpbin -nologo -symbols hello.obj | grep External | grep -v UNDEF
00A 00000000 SECT5 notype () External | printf
00F 00000000 SECT6 notype () External | __local_stdio_printf_options
012 00000000 SECT7 notype External |
??_C@_0N@NLPDAPMJ@Hello?5world?6?$AA@ (`string')
01C 00000000 SECT1 notype () External | main
$ llvm-nm hello.obj | grep ' [A-TV-Z] '
00000000 R ??_C@_0N@NLPDAPMJ@Hello?5world?6?$AA@
00000000 T __local_stdio_printf_options
00000000 T main
00000000 T printf
And it can be turned off by defining the C macro _NO_CRT_STDIO_INLINE:
$ cl -c -Os hello.c -D_NO_CRT_STDIO_INLINE
$ dumpbin -nologo -symbols hello.obj | grep External | grep -v UNDEF
00E 00000000 SECT4 notype () External | main
$ llvm-nm hello.obj | grep ' [A-TV-Z] '
00000000 T main
$ clang-cl -c -Os hello.c -D_NO_CRT_STDIO_INLINE
$ dumpbin -nologo -symbols hello.obj | grep External | grep -v UNDEF
011 00000000 SECT1 notype () External | main
$ llvm-nm hello.obj | grep ' [A-TV-Z] '
00000000 T main
2)
> After changing to NM="dumpbin.exe -nologo -symbols" (which I use with cl.exe),
> both libtextstyle and libunistring build successfully.
In libtool invocations, the use of $NM is followed by a variable
'global_symbol_pipe'. In libtool.m4 [1] two possible values are defined
for this variable. Since you say that with 'dumpbin' the exports of the
DLL are controlled correctly whereas with 'llvm-nm' they are not, there
are two possibilities:
* Either the 'global_symbol_pipe' value for this case (libtool.m4 line 4211)
needs to be corrected.
* Or, possibly, there is no way to do so, because the output of 'llvm-nm'
does not contain the necessary information.
Looking at the complete output of 'llvm-nm hello.obj', even with various
command-line options like --no-weak, I conclude that the cause is the latter.
That is, you *can't* use "NM=llvm-nm.exe", and NM="dumpbin -symbols" is the
only choice that works. Like I documented in INSTALL.windows and repeated in
[2].
Bruno
[1]
https://gitweb.git.savannah.gnu.org/gitweb/?p=libtool.git;a=blob;f=m4/libtool.m4;h=99b53ad046fb46afeabc3824b6f2f6ddec9b6935;hb=HEAD#l4189
[2] https://lists.gnu.org/archive/html/bug-gnulib/2025-06/msg00098.html