zoukankan      html  css  js  c++  java
  • 动态库静态库差异对比

    最近在做一个项目需要http接口,由此将框架中依赖libcurl的http单独拿来用

    libcurl提供两种库:静态库跟动态库,首先curl目下只提供了libcurl.a,并没有生成libcurl.so,由此开始编译依赖静态的http.so
    g++ -shared -fPIC -o lib/libhttp.so http_handle.cpp -I./ -I./curl-7.34.0/include -L./ -lcurl

    ./lib/libhttp.so: undefined reference to `SSL_connect'
    ./lib/libhttp.so: undefined reference to `X509_check_issued'
    ./lib/libhttp.so: undefined reference to `SSL_CTX_set_srp_password'
    ./lib/libhttp.so: undefined reference to `BIO_free'
    ./lib/libhttp.so: undefined reference to `BIO_s_mem'
    ./lib/libhttp.so: undefined reference to `UI_method_get_reader'
    ./lib/libhttp.so: undefined reference to `UI_get_string_type'
    ./lib/libhttp.so: undefined reference to `sk_pop_free'
    ./lib/libhttp.so: undefined reference to `BIO_ctrl'
    ./lib/libhttp.so: undefined reference to `DES_set_odd_parity'


    爆出一堆未定义符号,然后用nm libhttp.so查看符号
    000000000000ca80 T curl_multi_info_read
    000000000000cff0 T curl_multi_init
    000000000000e5f0 T curl_multi_perform
    000000000000ead0 T curl_multi_remove_handle
    000000000000c800 T curl_multi_setopt
    000000000000ea80 T curl_multi_socket
    000000000000ea30 T curl_multi_socket_action
    000000000000e9e0 T curl_multi_socket_all

    发现静态库的libcurl.a的符号已经在http.so中定义了,那这些符号通过google可以发现是openssl crypto libdl libz librt
    接着将上面的静态库加入链接中
    g++ -shared -fPIC -o lib/libhttp.so http_handle.cpp -I./ -I./curl-7.34.0/include -L./ -lcurl -lssl -lcrypto -ldl -lz -lrt
    g++ -o main main.cpp -L./lib -lhttp -Wl,--rpath=./lib
    可以正常编译通过


    后来下载了libcurl库然后make编译出了libcurl.so
    则只需要g++ -shared -fPIC -o lib/libhttp.so http_handle.cpp -I./ -I./curl-7.34.0/include -lcurl就可以了,不需要加-lssl -lcrypto等
    使用readelf -d libcurl.so查看其.dynamic段可以看出,此段已经将所依赖的共享库包含了,其ldd命令原理也是通过链接器查看.dynamic段中
    的d_tag类型为DT_NEED(表示依赖的共享对象文件)将其打印
    Dynamic section at offset 0x5c1c0 contains 25 entries:
    Tag Type Name/Value
    0x0000000000000001 (NEEDED) Shared library: [libssl.so.1.0.0]
    0x0000000000000001 (NEEDED) Shared library: [libcrypto.so.1.0.0]
    0x0000000000000001 (NEEDED) Shared library: [libz.so.1]
    0x0000000000000001 (NEEDED) Shared library: [librt.so.1]
    0x0000000000000001 (NEEDED) Shared library: [libc.so.6]

    而gcc在编译链接的默认搜索路径可以通过ld --verbose显示
    SEARCH_DIR("/usr/x86_64-redhat-linux/lib64");
    SEARCH_DIR("/usr/local/lib64");
    SEARCH_DIR("/lib64");
    SEARCH_DIR("/usr/lib64");
    SEARCH_DIR("/usr/x86_64-redhat-linux/lib");
    SEARCH_DIR("/usr/lib64");
    SEARCH_DIR("/usr/local/lib");
    SEARCH_DIR("/lib");
    SEARCH_DIR("/usr/lib");
    由于自己的开发环境已经将openssl.so libdl.so libz.so libcrypto.so librt.so放入/usr/lib64中,恰好gcc在链接可执行文件时搜寻可执行文件所需要的符号定义都在
    搜索路径中,由此gcc编译生成http.so时,只需要跟curl.so形成依赖关系即可,curl所依赖的库不需要再编译http.so时再次添加。
    再将libcurl.so添加到/usr/lib64(后来发现有人已经添加到了)
    编译可执行文件时只需要g++ -o main main.cpp -L./lib -lhttp -Wl,--rpath=./lib

    执行./main可以正常运行,原因加了-rpath,通过readelf -d main
    ......
    0x0000000000000001 (NEEDED) Shared library: [libpthread.so.0]
    0x000000000000000f (RPATH) Library rpath: [./lib]
    RPATH是可执行文件执行时所依赖的动态库搜索路径(不是编译生成的路径),通过rpath来指定了。
    也可以将http.so添加到LD_LIBRARY_PATH,这样main也可以正常启动


    Linux gcc编译链接时的动态库搜索路径
    GCC编译、链接生成可执行文件时,动态库的搜索路径就包含LIBRARY_PATH,具体的搜索路径顺序如下(注意不会递归性地在其子目录下搜索):

    1、gcc编译、链接命令中的-L选项;
    2、gcc的环境变量的LIBRARY_PATH(多个路径用冒号分割);
    3、gcc默认动态库目录:/lib:/usr/lib:usr/lib64:/usr/local/lib。


    总结:执行可执行文件时,动态库的加载器将按照以下路径搜索
    1、编译目标代码时指定的动态库搜索路径:用选项-Wl,rpath和include指定的动态库的搜索路径,比如gcc -Wl,-rpath,include -L. -ldltest hello.c,在执行文件时会搜索路径`./include`;
    2、环境变量LD_LIBRARY_PATH(多个路径用冒号分割);
    3、在 /etc/ld.so.conf.d/ 目录下的配置文件指定的动态库绝对路径(通过ldconfig生效,一般是非root用户时使用);
    4、gcc默认动态库目录:/lib:/usr/lib:usr/lib64:/usr/local/lib等。

  • 相关阅读:
    爬取豆瓣电影
    post get 请求 headers注释哪些
    matlab 子图像subplot
    post请求get请求
    UA伪装
    urllib.request encode()/decode()
    urllib.parse quote/unquate/urlencode
    python 爬取图片
    二叉树满二叉树完全二叉树
    Linux | 性能分析系列学习 (1)
  • 原文地址:https://www.cnblogs.com/zengyiwen/p/10368383.html
Copyright © 2011-2022 走看看