• GCC 使用库文件名进行链接


    使用 GCC 进行 C/C++ 代码编译时,如果代码中使用到了库函数,需要使用 -l 选项指定该库函数所在的库。如:-lm-lrt-lpthread等。这种方式使用的是库的缩写。一个库的文件名如果是:libxxx.solibxxx.a,则可以使用 -lxxx 进行链接。这种规则很常见,但是缺点也很明显。假设在一台 Linux 机器上,同时具有 libxxx.solibxxx.a,GCC 会优先链接 libxxx.so。虽然,GCC 也提供了 -static 选项可以强制链接静态库。但是,这时候新的问题出现了,假设有两个库 xy,他们都具有静态库和动态库两个版本。如果我想要链接 libx.soliby.a,使用 -static 选项就无法满足这个要求。我需要更加精细的控制,最好是直接根据文件名直接指定链接哪个版本的库文件,就没有任何歧义。

    GCC 文档的关于 -l 选项的描述没有告诉我如何直接使用一个库文件名。于是翻看 ld 的文档。在关于 -l 选项的描述中,有这样一段话:

    If namespec is of the form ‘:filename’, ld will search the library path for a file called filename, otherwise it will search the library path for a file called ‘libnamespec.a’.

    也就是说可以使用 -l:filename 的形式直接指定库文件名。这个只是 ld 的选项,GCC 能不能直接使用还需要验证。设计三个 .cpp 文件,分为 x.cpp y.cppmain.cpp

    // x.cpp
    #include <iostream>
    
    void print_x()
    {
        std::cout << "x" << std::endl;
    }
    
    // y.cpp
    #include <iostream>
    
    void print_y()
    {
        std::cout << "y" << std::endl;
    }
    
    // main.cpp
    void print_x();
    void print_y();
    
    int main()
    {
        print_x();
        print_y();
    }
    

    使用如下 Makefile 进行编译。x.cpp 编译成 libx.solibx.ay.cpp 编译成 liby.soliby.amain.cpplibx.soliby.a 编译链接成 main.out

    all : main
    	
    x :
    	gcc -o libx.so -shared -fPIC x.cpp
    	gcc -o x.o -c x.cpp
    	ar crs libx.a x.o
    
    y :
    	gcc -o liby.so -shared -fPIC y.cpp
    	gcc -o y.o -c y.cpp
    	ar crs liby.a y.o
    
    clean :
    	rm -f *.out *.o *.so *.a
    
    main : x y
    	gcc -o main.out main.cpp -Wl,-rpath=./  -lstdc++ -L. -l:libx.so -l:liby.a
    

    能直接通过编译,使用 ldd main.out 查看一下动态库依赖:

            linux-vdso.so.1 (0x00007ffe71ace000)
            libstdc++.so.6 => /lib64/libstdc++.so.6 (0x00007f1bdea54000)
            libx.so => ./libx.so (0x00007f1bdea4f000)
            libc.so.6 => /lib64/libc.so.6 (0x00007f1bde845000)
            libm.so.6 => /lib64/libm.so.6 (0x00007f1bde769000)
            /lib64/ld-linux-x86-64.so.2 (0x00007f1bdec7b000)
            libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x00007f1bde74e000)
    

    可以看到 libx.so 被动态链接,而 liby.a 被静态链接,没有显示。执行 main.out,输出结果也符合预期。

    x
    y
    

    由此可见,-l:filename 能直接用于 GCC。这种方法除了控制链接的库是静态的还是动态的之外,还能用于控制库的版本号。例如 libx.so 同时存在两个版本 libx.so.1libx.so.2 ,可以使用 -l:libx.so.1 指定版本号为 1 的库。

  • 相关阅读:
    动态规划:09 0-1背包理论基础I
    Node.js 是怎么找到模块的?
    Compose LazyColumn 对比 RecyclerView ,谁的性能更好?
    浙大恩特客户资源管理系统CustomerAction.entphone;.js 接口任意文件上传漏洞复现 [附POC]
    2-Python程序执行机制
    一次简单的 JVM 调优,拿去写到简历里
    洛谷 P7695 [COCI2009-2010#4] PLANINA
    从零开始学Spring Boot系列-集成MyBatis-Plus
    【24种设计模式】单例模式(Singleton Pattern)
    Pikachu靶场之SSRF服务器端请求伪造
  • 原文地址:https://www.cnblogs.com/mkckr0/p/15914118.html