【问题标题】:How to compile a program with static libcurl?如何使用静态 libcurl 编译程序?
【发布时间】:2015-08-19 18:07:30
【问题描述】:

有如下代码:

#include <stdio.h>
#include <curl/curl.h>

int main(void){
  CURL *curl;
  CURLcode res;

  curl = curl_easy_init();

  if(curl == NULL)
    return 0;

  curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/getAccessAttributes?id=1");

  res = curl_easy_perform(curl);

  if(res != CURLE_OK) {
    fprintf(stderr, "Error: %s\n", curl_easy_strerror(res));
    return 0;
  }

  curl_easy_cleanup(curl);
  return 0;
}

如果您从动态链接库中收集它,一切正常:

gcc test.c -lcurl -o test

现在我想提出一个静态程序:

gcc test.c /tmp/curl/lib/libcurl.a -static -lcurl -lssl -lcrypto -ldl -lm -lz -DCURL_STATICLIB -I/tmp/curl/include -o test

他犯了错误:

/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/libcrypto.a(dso_dlfcn.o):在函数dlfcn_globallookup': (.text+0x11): warning: Using 'dlopen' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking /tmp/curl/lib/libcurl.a(libcurl_la-netrc.o): In functionCurl_parsenetrc'中: netrc.c:(.text+0x3c8): 警告:在静态链接的应用程序中使用“getpwuid_r”需要在运行时使用 glibc 版本中用于链接的共享库 /tmp/curl/lib/libcurl.a(libcurl_la-curl_addrinfo.o):在函数“Curl_getaddrinfo_ex”中: curl_addrinfo.c:(.text+0x60): 警告:在静态链接的应用程序中使用“getaddrinfo”需要在运行时使用 glibc 版本中用于链接的共享库

该程序仅在您指定主机 IP 地址而不是 example.com 时才有效。 否则程序无法解析域名:

$ ./test
Error: Couldn't resolve host name

如何解决名称解析的问题?谢谢!

附: 静态libcurl我收集了如下方法:

wget http://curl.haxx.se/download/curl-7.44.0.tar.lzma
tar xf curl-7.44.0.tar.lzma
cd curl-7.44.0
./configure --disable-shared --enable-static --prefix=/tmp/curl --disable-ldap --disable-sspi --without-librtmp --disable-ftp --disable-file --disable-dict --disable-telnet --disable-tftp --disable-rtsp --disable-pop3 --disable-imap --disable-smtp --disable-gopher --disable-smb --without-libidn
make && make install

【问题讨论】:

  • 我看不出您发布的警告与您描述的问题有何关联。
  • 您想链接 all 库的静态版本还是简单地使用 libcurl?还有为什么要指定两次(tmp-lcurl 中的一个;您应该使用-L 来指定库路径:检查ld man page)。静态构建应用程序后,ldd test 输出是什么?

标签: c linux gcc curl


【解决方案1】:

这就是动态 libcurl 的样子。

$ ldd test
    linux-vdso.so.1 (0x00007ffcca3aa000)
    libcurl.so.4 => /usr/lib64/libcurl.so.4 (0x00007f5536ed6000)
    libc.so.6 => /lib64/libc.so.6 (0x00007f5536b3e000)
    libssl.so.1.0.0 => /usr/lib64/libssl.so.1.0.0 (0x00007f55368d3000)
    libcrypto.so.1.0.0 => /usr/lib64/libcrypto.so.1.0.0 (0x00007f5536503000)
    libz.so.1 => /lib64/libz.so.1 (0x00007f55362ed000)
    /lib64/ld-linux-x86-64.so.2 (0x00007f5537138000)
    libdl.so.2 => /lib64/libdl.so.2 (0x00007f55360e9000)

如果您只想静态链接 curl,请不要使用 -static。只需将 libcurl.a 添加为对象文件之一或使用 -lcurl,您无需指定两次。 之后

gcc test.c curl-7.44.0/lib/.libs/libcurl.a -lssl -lcrypto -ldl -lm -lz -DCURL_STATICLIB -o test

你会得到

$ ldd test
    linux-vdso.so.1 (0x00007ffd9a0a7000)
    libssl.so.1.0.0 => /usr/lib64/libssl.so.1.0.0 (0x00007f947cc7e000)
    libcrypto.so.1.0.0 => /usr/lib64/libcrypto.so.1.0.0 (0x00007f947c8ae000)
    libdl.so.2 => /lib64/libdl.so.2 (0x00007f947c6aa000)
    libm.so.6 => /lib64/libm.so.6 (0x00007f947c3b1000)
    libz.so.1 => /lib64/libz.so.1 (0x00007f947c19b000)
    libc.so.6 => /lib64/libc.so.6 (0x00007f947be03000)
    /lib64/ld-linux-x86-64.so.2 (0x00007f947cee9000)

-static 表示您希望全部静态链接。然后您需要将所有库准备为静态,结果将是:

$ ldd test
    not a dynamic executable

【讨论】:

  • 感谢您的回复,但您不理解我的意思。我对静态编译没有问题。问题是在静态编译的程序中,域名解析不起作用。
  • 您提到在遵守时会收到警告。您是否设法在没有警告的情况下编译它?我已经尝试过您的代码,即使是静态链接,它也能正常工作。
【解决方案2】:

我找到了办法。 libcurl 必须使用“--enable-ares”键配置。

./configure --disable-shared --enable-static --prefix=/tmp/curl --disable-ldap --disable-sspi --without-librtmp --disable-ftp --disable-file --disable-dict --disable-telnet --disable-tftp --disable-rtsp --disable-pop3 --disable-imap --disable-smtp --disable-gopher --disable-smb --without-libidn --enable-ares

然后程序将使用 gethostbyname 并能够解析域名。

谢谢大家的cmets。

【讨论】:

    猜你喜欢
    • 2012-03-27
    • 2016-06-18
    • 2016-07-28
    • 1970-01-01
    • 2013-08-31
    • 1970-01-01
    • 2019-09-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多