ICode9

精准搜索请尝试: 精确搜索
首页 > 系统相关> 文章详细

Ubuntu下使用GCC制作库文件

2021-09-07 21:31:32  阅读:210  来源: 互联网

标签:文件 GCC main 静态 链接库 Ubuntu 动态链接库 动态 制作


GCC制作库文件

什么是库文件

所谓库文件,读者可以将其等价为压缩包文件,该文件内部通常包含不止一个目标文件(也就是二进制文件)。值得一提的是,库文件中每个目标文件存储的代码,并非完整的程序,而是一个个实用的功能模块。例如,C 语言库文件提供有大量的函数(如 scanf()printf()strlen() 等),C++ 库文件不仅提供有使用的函数,还有大量事先设计好的类(如 string 字符串类)。

库文件的产生,极大的提高了程序员的开发效率,因为很多功能根本不需要从 0 开发,直接调取包含该功能的库文件即可。并且,库文件的调用方法也很简单,以 C 语言中的 printf() 输出函数为例,程序中只需引入 <stdio.h> 头文件,即可调用 printf() 函数。

事实上,库文件只是一个统称,代指的是一类压缩包,它们都包含有功能实用的目标文件。要知道,虽然库文件用于程序的链接阶段,但编译器提供有 2 种实现链接的方式,分别称为静态链接方式和动态链接方式,其中采用静态链接方式实现链接操作的库文件,称为 静态链接库 ;采用动态链接方式实现链接操作的库文件,称为 动态链接库

静态链接库实现链接操作的方式很简单,即程序文件中哪里用到了库文件中的功能模块,GCC 编译器就会将该模板代码直接复制到程序文件的适当位置,最终生成可执行文件。

静态链接库

使用静态库文件实现程序的链接操作,既有优势也有劣势:

  • 优势是,生成的可执行文件不再需要任何静态库文件的支持就可以独立运行(可移植性强);
  • 劣势是,如果程序文件中多次调用库中的同一功能模块,则该模块代码势必就会被复制多次,生成的可执行文件中会包含多段完全相同的代码,造成代码的冗余。

注:

  1. 和使用动态链接库生成的可执行文件相比,静态链接库生成的可执行文件的体积更大。

  2. 另外值得一提的是,在 Linux 发行版系统中,静态链接库文件的后缀名通常用 .a 表示;在 Windows 系统中,静态链接库文件的后缀名为 .lib。

动态链接库

动态链接库,又称为共享链接库。和静态链接库不同,采用动态链接库实现链接操作时,程序文件中哪里需要库文件的功能模块,GCC 编译器不会直接将该功能模块的代码拷贝到文件中,而是将功能模块的位置信息记录到文件中,直接生成可执行文件。

显然,这样生成的可执行文件是无法独立运行的。采用动态链接库生成的可执行文件运行时,GCC 编译器会将对应的动态链接库一同加载在内存中,由于可执行文件中事先记录了所需功能模块的位置信息,所以在现有动态链接库的支持下,也可以成功运行。

采用动态链接库实现程序的连接操作,其优势和劣势恰好和静态链接库相反:

  • 优势是,由于可执行文件中记录的是功能模块的地址,真正的实现代码会在程序运行时被载入内存,这意味着,即便功能模块被调用多次,使用的都是同一份实现代码(这也是将动态链接库称为共享链接库的原因)。
  • 劣势是,此方式生成的可执行文件无法独立运行,必须借助相应的库文件(可移植性差)。

注:

  1. 和使用静态链接库生成的可执行文件相比,动态链接库生成的可执行文件的体积更小,因为其内部不会被复制一堆冗余的代码。

  2. 在 Linux 发行版系统中,动态链接库的后缀名通常用 .so 表示;在 Windows 系统中,动态链接库的后缀名为 .dll。

值得一提的是,GCC 编译器生成可执行文件时,默认情况下会优先使用动态链接库实现链接操作,除非当前系统环境中没有程序文件所需要的动态链接库,GCC 编译器才会选择相应的静态链接库。如果两种都没有(或者 GCC 编译器未找到),则链接失败。

在 Linux 发行版中,静态链接库和动态链接库通常存放在 /usr/bin 或者 /bin 目录下。图 1 所示是在 CentOS 系统中,系统库文件在 /usr/bin 目录下的存储状态。

实验代码

假设有如下代码:

//test.h

#ifndef __TEST__
#define __TEST__

#include <iostream>
#include <string>

int func(std::string& str);

#endif

//test.cpp
#include "test.h"

int func(std::string& str){
    std::cout << "show something:" << std::endl;
    std::cout << str << std::endl;
    return str.size();
}
//main.cpp
#include "test.h"

int main(){
    std::string str = "你好世界!";
    std::cout << func(str) << std::endl;
    return 0;
}

GCC制作静态库

静态库文件的命名方式是:libxxx.a,库名前加“ lib ”,后缀用“ .a ”,“ xxx ”为静态库名。

  • 把程序文件public.cpp编译成静态库的指令:
g++ -c -o libtest.a test.cpp
  • 使用静态库的方法一,直接把调用者源代码和静态库文件名一起编译:
g++ -o main main.cpp libtest.a
  • 使用静态库的方法二,采用 -L 参数指定静态库文件的目录, -l 参数指定静态库名。
g++ -o main main.cpp -L./ -ltest

命令行中,./表示当前目录,test是库名

注:

  1. 如果要指定多个静态库文件的目录,用法是“-L/目录1 -L目录2 -L目录3”;
  2. 链接库的文件名是libpublic.a,但链接库名是”public”,不是“libpublic.a”;
  3. 如果要指定多个静态库,用法是“-l库名1 -l库名2 -l库名3”。
  • 运行结果:
littleboy@littleboy-workspace:~/CC++/test$ ./main
show something:
你好世界!
15

GCC制作动态库

动态库在编译时并不会被连接到目标代码中,而是在程序运行时才被载入,因此在程序运行时还需要指定动态库的目录。

动态库的命名方式与静态库类似,前缀相同,为“lib”,后缀变为“.so” “xxx”为动态库名。

把程序文件public.cpp编译成动态库的指令:

g++ -fPIC -shared -o libtest.so test.cpp

使用动态库的方法与使用静态库的方法基本相同。

g++ -o main main.cpp -L./ -ltest -Wl,-rpath=./

注:

  1. 如果在动态库文件和静态库文件同时存在,优先使用动态库编译。
  2. -L./只是制定了编译阶段库文件在./处找到所需库文件,运行时,需要把动态库复制到路径/lib/usr/lib(Linux动态库的默认搜索路径是/lib和/usr/lib)。
  3. 当需要自行指定运行时动态库时,有三种方法:
    • 方法一: 在配置文件/etc/ld.so.conf中指定动态库搜索路径;
    • 方法二: 通过环境变量LD_LIBRARY_PATH指定动态库搜索路径;(使用命令export LD_LIBRARY_PATH=/home/wucz/demo:.
    • 方法三: 在编译目标代码时指定该程序的动态库搜索路径。
  4. 此处在编译时使用参数 -Wl,-rpath=./ 指定运行时搜索路径为 ./

运行main:

  • 运行结果:
littleboy@littleboy-workspace:~/CC++/test$ ./main
show something:
你好世界!
15

修改动态库代码

动态库代码稍作修改:

//test.cpp
#include "test.h"

int func(std::string& str){
    std::cout << "我正在使用动态库..." << std::endl;
    std::cout << str << std::endl;
    return str.size();
}

直接编译(无需编译main.cpp):

g++ -fPIC -shared -o libtest.so test.cpp

运行main:

  • 运行结果:
littleboy@littleboy-workspace:~/CC++/test$ ./main 
我正在使用动态库...
你好世界!
15

从上面可以看出,动态库在编译的时候只做语法检查,并没有被编译进目标代码,当程序执行到动态库中的函数时才调用该函数库里的代码。
动态函数库并没有整合进程序,所以程序的运行环境必须提供动态库路径。
优点是,如果所使用的动态库发生更新改变,程序不需要重新编译,所以动态库升级比较方便。

  • 参考文献:
  1. 佚名. GCC使用静态链接库和动态链接库. C语言中文网[J/OL]. http://c.biancheng.net/view/8010.html , 发表日期:不详 / 2021/09/07

  2. 码农有道. Linux静态库与动态库. C语言技术网[J/OL]. http://www.freecplus.net/05944de09a3942a89a571d523712b548.html , 发表日期:不详 / 2021/09/07

标签:文件,GCC,main,静态,链接库,Ubuntu,动态链接库,动态,制作
来源: https://www.cnblogs.com/littleboy90/p/15240288.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有