curl / Mailing Lists / curl-library / Single Mail

curl-library

Re: msys2/mingw32 linking dll to libcurl.a suppresses DLL exports

From: Martin Storsjö via curl-library <curl-library_at_cool.haxx.se>
Date: Fri, 15 Feb 2019 10:13:35 +0200 (EET)

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.)

// Martin

-------------------------------------------------------------------
Unsubscribe: https://cool.haxx.se/list/listinfo/curl-library
Etiquette: https://curl.haxx.se/mail/etiquette.html
Received on 2019-02-15