静态编译curl 和 可选静态编译依赖库

新版的curl 支持了更细致时间粒度的curl_easy_getinfo,以及HTTP2, 这里介绍手工编译源码安装方式,并使用openssl1.1.1b

  1. https://www.openssl.org/ 下载1.1.1 序列的long-term 源码,并编译安装 ./config --prefix=/opt/itc/openssl enable-weak-ssl-ciphers no-shared && make && make install
  2. https://nghttp2.org/ 下载nghttp2库, curl 需要它才能支持HTTP2,编译安装, OPENSSL_LIBS="/opt/itc/openssl/lib/" ./configure --prefix=/opt/itc/curl/nghttp2 –enable-static=yes –enable-shared=no && make && make install
  3. 从https://curl.haxx.se/ 下载最新的curl版本,并编译安装,编译参数如下
./configure  LDFLAGS="-static" --prefix=/opt/itc/curl --with-ssl=/opt/itc/openssl  --with-nghttp2=/opt/itc/curl/nghttp2 --disable-ldaps --without-libidn2 --enable-static=yes --enable-shared=no
make
make install

这样子得到的是不依赖openssl和nghttp2动态链接库的curl,可以拷走给别的机器

./configure  LDFLAGS="-static" --prefix=/opt/itc/curl --with-ssl=/opt/itc/openssl  --with-nghttp2=/opt/itc/curl/nghttp2 --disable-ldaps --without-libidn2 --enable-static=yes --enable-shared=no
make LDFLAGS="-all-static -static -L/opt/itc/openssl/lib -L/opt/itc/curl/nghttp2/lib -ldl"
make install

这样子得到的是: 不依赖任何动态链接库的版本

可能遇到的问题:

1./usr/bin/ld: cannot find -lnghttp2 或者 -lssl 之类的

这是curl找不到对应的依赖库,请确认给了正确的configure参数,如果还不行,可以在configure的时候加上LIBS=-L/opt/itc/openssl/lib/ -L… 多个依赖库以空格分开

2. configure: error: one or more libs available at link-time are not available run-time. Libs used at link-time: -lnghttp2 -lssl -lz -lrt -lcrypto -ldl

这是curl找到了link-time 库,却没找到动态依赖库, 需要在configure的时候加入LDFLAGS=”-static”,让curl的编译程序知道我们要做静态的东西

3. 静态编译make的时候为什么要带那么长的参数,通常不是LDFLAGS=”-all-static”就可以了么?

是的,通常是可以的,打开src/Makefile能看到make LDFLAGS 带的参数会冲掉configure的时候找到的依赖库环境

LD = /usr/bin/ld -m elf_x86_64
 LDFLAGS = -static -L/opt/itc/openssl/lib -L/opt/itc/curl/nghttp2/lib
 LIBCURL_LIBS = -lnghttp2 -lssl -lrt -lcrypto -ldl

所以要么完整一点写上去,要么就使用curl提供的curl_LDFLAGS参数也OK

make curl_LDFLAGS="-all-static"

4. 那么要用这些新的库编译example里边的例子怎么办?

 #gcc  chkspeed.c /opt/itc/curl/lib/libcurl.a /opt/itc/curl/nghttp2/lib/libnghttp2.a /opt/itc/openssl/lib/libssl.a /opt/itc/openssl/lib/libcrypto.a  -I/opt/itc/curl/include -I/opt/itc/curl/nghttp2/include   -lrt  -ldl  -o chkspeed
 #ldd chkspeed
        linux-vdso.so.1 =>  (0x00007ffc475a2000)
        librt.so.1 => /lib64/librt.so.1 (0x00007fcb5d748000)
        libdl.so.2 => /lib64/libdl.so.2 (0x00007fcb5d544000)
        libc.so.6 => /lib64/libc.so.6 (0x00007fcb5d1af000)
        libpthread.so.0 => /lib64/libpthread.so.0 (0x00007fcb5cf92000)
        /lib64/ld-linux-x86-64.so.2 (0x00005593e1eb2000)
这样子编译出来是把这几个库都包含在里边的
gcc chkspeed.c -L/opt/itc/openssl/lib/   -L/opt/itc/curl/nghttp2/lib -L/opt/itc/curl/lib  -I/opt/itc/curl/include -I/opt/itc/curl/nghttp2/include -lcurl -lssl -lrt -lcrypto -ldl -lnghttp2
这样子编译出来是带动态链接库的,但是需要设置环境变量,告诉系统那些.so在哪里,或者修改/etc/ld.so.conf.d/, 增加路径

当然,我们的openssl选择的是静态编译,所以出来的程序依赖只有nghttp2.so

部分知识点:

o: 编译的目标文件
a: 静态库,其实就是把若干o文件打了个包
so: 动态链接库(共享库)

lo: 使用libtool编译出的目标文件,其实就是在o文件中添加了一些信息
la: 使用libtool编译出的库文件,其实是个文本文件,记录同名动态库和静态库的相关信息

./configure LDFLAGS="-static"
make LDFLAGS="-all-static"
-I include,头文件和库文件,通常都是源码
-L 依赖链接库的目录,可能是静态的也可能是动态的
-l 依赖库的名称,比如-lssl -ldl -lz 
pkgconfig 里边有对应的.pc文件,当-l 或者-L指定依赖的时候会自动去找

-l 是有顺序的,而且是从右到左开始包含的,比如

 -lcurl -lssl -lrt -lcrypto -ldl -lnghttp2
这里-lcurl 必须在最前边, -lssl 也必须在-lcrypto的前边,原因很简单: curl调用了所有的其他依赖库, 而ssl调用了crypto

参考文档:

https://github.com/curl/curl/issues/503

https://curl.haxx.se/mail/lib-2017-11/0107.html

https://stackoverflow.com/questions/48726825/setting-up-libcurl-on-linux

发表评论