【问题标题】:using static libcurl.a in C program by minGW64minGW64 在 C 程序中使用静态 libcurl.a
【发布时间】:2021-09-16 19:24:39
【问题描述】:

(我看到了关于这个问题的每一个 StOF 问题的答案 - 没有一个完全有帮助。经过 3 天三夜的努力,我感到非常沮丧。)


  • libcurl.a 静态链接:
    • OpenSSL 1.1.1k [64bit/32bit]
    • brotli 1.0.9 [64bit/32bit]
    • libgsasl 1.10.0 [64bit/32bit]
    • libidn2 2.3.1 [64bit/32bit]
    • libssh2 1.9.0 [64bit/32bit]
    • nghttp2 1.43.0 [64bit/32bit]
    • zlib 1.2.11 [64bit/32bit]
    • zstd 1.5.0 [64bit/32bit]

案例 1 - 好像 curl 不是静态链接的

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

抛出无休止的错误行,好像 libcurl 没有与其依赖项静态链接*:

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

【问题讨论】:

  • 我会提到其他相关的案例。
  • 静态库本身实际上并没有链接,它实际上只不过是一个目标文件的存档。因此,与静态库的链接就像与实际目标文件本身的链接一样。如果静态库有其他库依赖项,您也必须显式链接它们。
  • "libcurl.a is statically linked with..." 没有多大意义。 libcurl.dll 可以与它​​们链接,但不能与 libcurl.a 链接。当你链接静态库时,你必须手动链接它们的依赖。
  • 那是 curl 应用程序,独立程序,而不是库。
  • 是的,完全正确。或者考虑使用 pkg-config,它可以自动生成这些标志(最简单的方法是从 MSYS2 安装它)。

标签: c windows curl mingw static-libraries


【解决方案1】:

使用 libcurl 的最佳方式是通过 pkg-config 获取必要的标志。在 MSYS2 中,这工作得很好。否则您可能需要将环境变量PKG_CONFIG_PATH 指向libcurl.pc 的位置。

在我的系统上

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

返回:

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

请注意,对于 MinGW,库的顺序也很重要。提供符号的库应该在链接器命令行中引用该符号的对象之后提及。

最后,您需要确保您包含的每个库实际上都是静态构建和使用的。我的意思是在构建它时不能使用像__declspec(dllexport) 这样的东西,在编译任何依赖它的东西时也不能使用__declspec(dllimport)。对于某些库,这可能需要在包含库的标头之前进行特定定义。

特别是对于 libcurl 和 nghttp2,我发现在构建 libcurl 时在 lib/http2.clib/http.c 的顶部添加以下内容会有所帮助:

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

这将在构建静态 libcurl 时定义 NGHTTP2_STATICLIB

我已将此错误报告为:https://github.com/curl/curl/issues/7353

【讨论】:

  • 听起来很完美 - 将尝试 MSYS2!但是,我修复了所有问题,并且非常接近使用 x86_64-w64-mingw32-gcc-10.2.0.exe -DCURL_STATICLIB main.c .\libcurl.a ... .\lib\libbrotlicommon-static.a .\lib\libbrotlidec-static.a .\lib\libbrotlienc-static.a .... -lws2_32 -lwldap32 -ladvapi32 ... 编译我的程序但是,我得到:undefined reference to BrotliTransformDictionaryWord
  • @q-codes 我从源代码构建了 brotli 1.0.9,但我也将lib/*-static.a 复制到了lib/*.a,我没有这样的问题。你从哪里弄来的brotli?
  • Got Brotli from here。在答案中,pkg-config 来自 MSYS?而-LD:/Prog/.../lib -lcurl -lidn2 -lrtmp ...也指的是MSYS安装的库?
  • 我自己使用从源代码构建的 brotli,没有修改源代码。您可以从 MSYS2 获取pkg-config,但您可以设置环境变量PKG_CONFIG_PATH 来告诉它以何种顺序查找.pc 文件。请注意,静态构建需要所有依赖项可用,以及它们的依赖项等...
【解决方案2】:

看到有多少人一直在努力并且仍在努力将libcurl 静态链接到他们的程序,真是令人非常难过。以至于a very active Curl maintainer 说:“构建静态是留给用户自己处理的过山车,因为它是我们试图支持的永无止境的竞赛。”


由于linker 表示未定义的引用,那么libcurl.a 必须是:

  • 非静态链接
  • 或者,您的库序列未排列。 Linker 对序列敏感。示例:如果libbrotlidec-static.a 需要在libbrotlienc-static.a 内的函数/符号,则必须在libbrotlidec-static.a 之前提及libbrotlienc-static.a

静态库是对象.obj 文件的存档.a。而且它们本身并不是静态链接的。这就是为什么要将some-static-library.a链接到一个程序,你需要收集并手动提及every.asingle.astatic.alibrary.asome-static-library.a的依赖项。


在我的Chat@Terminal:~$ 项目中,我应该有一个make.bat 文件,该文件显示如何使用gccmingwlibcurl 静态链接到程序。最后静态编译整个程序,并在没有任何运行时依赖的情况下发布!


在旁注中,curl's precompiled-binary website 说:Curl_x.x.x 静态链接到:[您提供的库列表]。打破您的误解,网站上的声明意味着:Curl.exe 与库静态链接,而不是 libcurl

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-02-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多