curl-library
Re: msys2/mingw32 linking dll to libcurl.a suppresses DLL exports
Date: Fri, 15 Feb 2019 10:21:35 +0200 (EET)
On Fri, 15 Feb 2019, Martin Storsjö via curl-library wrote:
> On Fri, 15 Feb 2019, Bruce Cartland via curl-library wrote:
>
>> I'm finding this a bit bizarre. I feel like I'm missing something obvious.
>>
>> I have a very simple test dll with function "int zzz_init(void)" that uses
>> curl.
>>
>> Dynamically:
>> ------------
>>
>> /C/msys64/mingw32/bin/gcc.exe -O2 -Wl,--allow-multiple-definition -shared
>> -o libzzz.dll -Wl,--out-implib,libzzz.dll.a
>> -Wl,--major-image-version,3,--minor-image-version,0 -Wl,--whole-archive
>> CMakeFiles/zzz.dir/objects.a -Wl,--no-whole-archive -lcurl -Wl,-Bstatic
>> -lssl -lcrypto -lxml2 -ljansson -static-libgcc -lpsl -lidn2 -lnghttp2
>> -lcrypt32 -lunistring -lssh2 -lbrotlidec-static -lbrotlicommon-static -lz
>> -llzma -lintl -liconv -lwldap32 -lwsock32 -lws2_32 -lgdi32 -lcomdlg32
>> -lkernel32 -luser32 -lgdi32 -lwinspool -lshell32 -lole32 -loleaut32 -luuid
>> -lcomdlg32 -ladvapi32
>>
>> zzz_init exists:
>>
>> $ nm _build/mingw32-Release/atoakm3/libzzz.dll.a | grep zzz_init
>> 00000000 I __imp__zzz_init
>> 00000000 T _zzz_init
>>
>> Statically:
>> -----------
>>
>> /C/msys64/mingw32/bin/gcc.exe -O2 -Wl,--allow-multiple-definition -shared
>> -o libzzz.dll -Wl,--out-implib,libzzz.dll.a
>> -Wl,--major-image-version,3,--minor-image-version,0 -Wl,--whole-archive
>> CMakeFiles/zzz.dir/objects.a -Wl,--no-whole-archive -Wl,-Bstatic -lcurl
>> -lssl -lcrypto -lxml2 -ljansson -static-libgcc -lpsl -lidn2 -lnghttp2
>> -lcrypt32 -lunistring -lssh2 -lbrotlidec-static -lbrotlicommon-static -lz
>> -llzma -lintl -liconv -lwldap32 -lwsock32 -lws2_32 -lgdi32 -lcomdlg32
>> -lkernel32 -luser32 -lgdi32 -lwinspool -lshell32 -lole32 -loleaut32 -luuid
>> -lcomdlg32 -ladvapi32
>>
>> zzz_init does not exist:
>>
>> $ nm _build/mingw32-Release/atoakm3/libzzz.dll.a | grep zzz_init
>>
>>
>>
>> The only difference is that -lcurl is after -Wl,-Bstatic not before.
>
> This sounds like a case where the static libcurl contains dllexport
> directives.
>
> When linking a DLL, there are many different mechanisms for choosing what
> symbols to export. One way is to annotate individual functions with
> __declspec(dllexport). If there are no functions marked dllexport, the linker
> defaults to exporting all symbols.
>
> When linking in dependencies statically, this has two consequences. If there
> are no dllexport markings, all the functions from the dependency library are
> exported, together with your own functions. That's probably unexpected but
> mostly harmless.
>
> However if the static library contains dllexport markings, these functions
> will be exported, but the default mechanism for exporting all symbols won't
> be invoked.
>
> If you explicitly pass -Wl,--export-all-symbols to the linker, you enforce
> exporting all symbols, regardless of dllexport directives.
>
> I don't off-hand know of any common GNU binutils tool to list embedded
> directives in object files. If you happen to have llvm-readobj available
> though, you can do "llvm-readobj -coff-directives libcurl.a" and have it list
> all the object files that the static library contained, together with their
> embedded directives. That would look like this: "Directive(s): -export:func"
>
> Ideally a static library shouldn't have dllexport attributes - I haven't
> checked if static builds of curl normally include them or not. (If using
> dllexport attributes for limiting what to export from a library, one has to
> do two separate builds to get both a dynamic library and a static library
> without the dllexport attributes.)
I forgot to add the reference to the GNU ld manual that describes this
behaviour: https://sourceware.org/binutils/docs/ld/WIN32.html
// Martin
-------------------------------------------------------------------
Unsubscribe: https://cool.haxx.se/list/listinfo/curl-library
Etiquette: https://curl.haxx.se/mail/etiquette.html
Received on 2019-02-15