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

Reply via email to