The hack to define the DLL export stub directly in the source file is useful with mingw and Cygwin. But it causes the MSVC 14 linker to crash. Seen when building GNU gettext:
/bin/sh ../libtool --tag=CC --mode=link /home/bruno/msvc/compile cl -nologo -MD -Wl,--export-all-symbols -liconv -ladvapi32 -no-undefined -export-symbols-regex '^([^g]|g[^l]|gl[^w]|glw[^t]|glwt[^h]|glwth[^r]|glwthr[^e]|glwthre[^a]|glwthrea[^d]).*' -version-info 9:6:1 -rpath /usr/local/msvc32/lib -L/usr/local/msvc32/lib -Wl,--disable-auto-import -o libintl.la bindtextdom.lo dcgettext.lo dgettext.lo gettext.lo finddomain.lo hash-string.lo loadmsgcat.lo localealias.lo textdomain.lo l10nflist.lo explodename.lo dcigettext.lo dcngettext.lo dngettext.lo ngettext.lo plural.lo plural-exp.lo localcharset.lo threadlib.lo lock.lo relocatable.lo langprefs.lo localename.lo localename-table.lo log.lo printf.lo setlocale.lo setlocale-lock.lo setlocale_null.lo version.lo xsize.lo osdep.lo intl-compat.lo windows-mutex.lo windows-rwlock.lo windows-recmutex.lo windows-once.lo libintl.res.lo libtool: link: dumpbin -symbols .libs/bindtextdom.obj .libs/dcgettext.obj .libs/dgettext.obj .libs/gettext.obj .libs/finddomain.obj .libs/hash-string.obj .libs/loadmsgcat.obj .libs/localealias.obj .libs/textdomain.obj .libs/l10nflist.obj .libs/explodename.obj .libs/dcigettext.obj .libs/dcngettext.obj .libs/dngettext.obj .libs/ngettext.obj .libs/plural.obj .libs/plural-exp.obj .libs/localcharset.obj .libs/threadlib.obj .libs/lock.obj .libs/relocatable.obj .libs/langprefs.obj .libs/localename.obj .libs/localename-table.obj .libs/log.obj .libs/printf.obj .libs/setlocale.obj .libs/setlocale-lock.obj .libs/setlocale_null.obj .libs/version.obj .libs/xsize.obj .libs/osdep.obj .libs/intl-compat.obj .libs/windows-mutex.obj .libs/windows-rwlock.obj .libs/windows-recmutex.obj .libs/windows-once.obj .libs/libintl.res.obj | gawk ' {last_section=section; section=$ 3}; /^COFF SYMBOL TABLE/{for(i in hide) delete hide[i]}; /Section length .*#relocs.*(pick any)/{hide[last_section]=1}; /^ *Symbol name *: /{split($ 0,sn,":"); si=substr(sn[2],2)}; /^ *Type *: code/{print "T",si,substr(si,length(prfx))}; /^ *Type *: data/{print "I",si,substr(si,length(prfx))}; $ 0!~/External *\|/{next}; / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next}; {if(hide[section]) next}; {f="D"}; $ 0~/\(\).*\|/{f="T"}; {split($ 0,a,/\||\r/); split(a[2],s)}; s[1]~/^[@?]/{print f,s[1],s[1]; next}; s[1]~prfx {split(s[1],t,"@"); print f,t[1],substr(t[1],length(prfx))} ' prfx=^_ | sed '/ __gnu_lto/d' | /usr/bin/sed -e '/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1,DATA/' | /usr/bin/sed -e '/^[AITW][ ]/s/.*[ ]//' | sort | uniq > .libs/intl.exp libtool: link: /usr/bin/grep -E -e "^([^g]|g[^l]|gl[^w]|glw[^t]|glwt[^h]|glwth[^r]|glwthr[^e]|glwthre[^a]|glwthrea[^d]).*" ".libs/intl.exp" > ".libs/intl.expT" libtool: link: mv -f ".libs/intl.expT" ".libs/intl.exp" libtool: link: if test DEF = "`/usr/bin/sed -n -e 's/^[ ]*//' -e '/^\(;.*\)*$/d' -e 's/^\(EXPORTS\|LIBRARY\)\([ ].*\)*$/DEF/p' -e q .libs/intl.exp`" ; then cp ".libs/intl.exp" ".libs/intl-8.dll.def"; echo ".libs/intl-8.dll.def" > ".libs/intl-8.dll.exp"; else /usr/bin/sed -e 's/^/-link -EXPORT:/' < .libs/intl.exp > .libs/intl-8.dll.exp; fi libtool: link: /home/bruno/msvc/compile cl -nologo -o .libs/intl-8.dll .libs/bindtextdom.obj .libs/dcgettext.obj .libs/dgettext.obj .libs/gettext.obj .libs/finddomain.obj .libs/hash-string.obj .libs/loadmsgcat.obj .libs/localealias.obj .libs/textdomain.obj .libs/l10nflist.obj .libs/explodename.obj .libs/dcigettext.obj .libs/dcngettext.obj .libs/dngettext.obj .libs/ngettext.obj .libs/plural.obj .libs/plural-exp.obj .libs/localcharset.obj .libs/threadlib.obj .libs/lock.obj .libs/relocatable.obj .libs/langprefs.obj .libs/localename.obj .libs/localename-table.obj .libs/log.obj .libs/printf.obj .libs/setlocale.obj .libs/setlocale-lock.obj .libs/setlocale_null.obj .libs/version.obj .libs/xsize.obj .libs/osdep.obj .libs/intl-compat.obj .libs/windows-mutex.obj .libs/windows-rwlock.obj .libs/windows-recmutex.obj .libs/windows-once.obj .libs/libintl.res.obj --export-all-symbols --disable-auto-import /usr/local/msvc32/lib/iconv.dll.lib -L/usr/local/msvc32/lib -ladvapi32 "@.libs/intl-8.dll.exp" -Wl,-DLL,-IMPLIB:".libs/intl.dll.lib" cl : Command line warning D9002 : ignoring unknown option '--export-all-symbols' cl : Command line warning D9002 : ignoring unknown option '--disable-auto-import' Creating library .libs/intl.dll.lib and object .libs/intl.dll.exp LINK : fatal error LNK1000: Internal error during CImplib::ReSortExportNamePtrs Version 14.00.24210.0 ExceptionCode = C0000005 ExceptionFlags = 00000000 ExceptionAddress = 00FF07A2 (00FB0000) "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\bin\link.exe" NumberParameters = 00000002 ExceptionInformation[ 0] = 00000000 ExceptionInformation[ 1] = 0555999A CONTEXT: Eax = 03559C91 Esp = 00EFD6A0 Ebx = 02000002 Ebp = 00EFD6C0 Ecx = 0555999A Esi = 00000046 Edx = 03553BD8 Edi = 00000047 Eip = 00FF07A2 EFlags = 00010206 SegCs = 00000023 SegDs = 0000002B SegSs = 0000002B SegEs = 0000002B SegFs = 00000053 SegGs = 0000002B Dr0 = 00000000 Dr3 = 00000000 Dr1 = 00000000 Dr6 = 00000000 Dr2 = 00000000 Dr7 = 00000000 make[5]: *** [Makefile:1500: libintl.la] Error 2 This patch avoids it. 2020-01-02 Bruno Haible <br...@clisp.org> setlocale-null: Avoid crashing the MSVC linker. * lib/setlocale-lock.c: Don't define IMP(gl_get_setlocale_null_lock) on MSVC. diff --git a/lib/setlocale-lock.c b/lib/setlocale-lock.c index 4bbe6eb..7dde32d 100644 --- a/lib/setlocale-lock.c +++ b/lib/setlocale-lock.c @@ -136,7 +136,7 @@ gl_get_setlocale_null_lock (void) # endif -# if defined _WIN32 || defined __CYGWIN__ +# if (defined _WIN32 || defined __CYGWIN__) && !defined _MSC_VER /* Make sure the '__declspec(dllimport)' in setlocale_null.c does not cause a link failure when no DLLs are involved. */ # if defined _WIN64 || defined _LP64