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