midnqp
midnqp

Reputation: 29

using static libcurl.a in C program by minGW64

(I saw answers of every single StOF questions regarding this - none fully helped. I'm very frustrated after trying so hard for 3 days & nights.)



Case 1 - as if curl isn't statically linked

x86_64-w64-mingw32-gcc-10.2.0.exe -o main.exe main.c "C:\curl-7.77.0-win64-mingw\lib\libcurl.a" -DCURL_STATICLIB

Throws unending lines of error, as if libcurl isn't statically linked with its dependencies*:

...\lib\libcurl.a(http2.o):(.text+0x7f): undefined reference to `nghttp2_version'
...\lib\libcurl.a(http2.o):(.text+0x297): undefined reference to `nghttp2_submit_rst_stream' 

... (then the errors include many more undefined reference to symbols from nghttp2, ssl, crypt, ssh, gsasl)

Upvotes: 0

Views: 3052

Answers (2)

midnqp
midnqp

Reputation: 29

It is so enormously saddening to see how many people have struggled and are still struggling to statically link libcurl to their program. So much so that a very active Curl maintainer said: "building static is a roller coaster left for the users to deal with on their own as its such a never-ending race for us to try to support."


Since linker is saying undefined references, then libcurl.a must be:

  • not statically linked
  • Or, you've got the sequence of libraries unarranged. Linker is sensitive to sequence. Example: If libbrotlidec-static.a needs a function/symbol which is inside libbrotlienc-static.a, then libbrotlienc-static.a must be mentioned before libbrotlidec-static.a

A static library is an archive .a of object .obj files. And they're not statically linked in themselves. That's why, to link some-static-library.a to a program, you need to collect and manually mention every.a single.a static.a library.a that are dependencies of some-static-library.a.


In my Chat@Terminal:~$ project, I should have a make.bat file which shows how to statically link libcurl to a program using gcc or mingw. And finally static-compile the whole program, and ship without any runtime dependency!


On a side-note, curl's precompiled-binary website says: Curl_x.x.x is statically linked with: [list of libraries you provided]. Break your misconception that, the statement made at the website means: Curl.exe is statically linked with the libs, not libcurl.

Upvotes: 1

Brecht Sanders
Brecht Sanders

Reputation: 7287

The best way to use libcurl is to get the necessary flags via pkg-config. In MSYS2 this works quite well. Otherwise you may need to point the environment variable PKG_CONFIG_PATH to the location of libcurl.pc.

On my system

pkg-config --define-prefix --static --libs libcurl

returns:

-LD:/Prog/winlibs64-11.1.0/custombuilt/lib -lcurl -lidn2 -lrtmp -lssh2 -lnettle
-lgnutls -ladvapi32 -lcrypt32 -lgss -lwldap32 -lzstd -lz -lws2_32 -lrtmp

Note that with MinGW the order of the libraries is also important. The library providing a symbol should be mention on the linker command line after the object that refers to that symbol.

Finally you need to make sure that each library you include was in fact built and used statically. With that I mean no stuff like __declspec(dllexport) may be used when building it, and no __declspec(dllimport) may be used when compiling anything that depends on it. For some libraries this may require specific defines before including the library's header(s).

Specifically for libcurl and nghttp2 I find that it helps to add the following at the top of lib/http2.c and lib/http.c when building libcurl:

#if defined(BUILDING_LIBCURL) && !defined(DLL_EXPORT)
#define NGHTTP2_STATICLIB
#endif

This will define NGHTTP2_STATICLIB when building static libcurl.

I have reported this as a bug at: https://github.com/curl/curl/issues/7353

Upvotes: 0

Related Questions