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