2

#导入Word文档图片# Linux下动态库与静态库的运用

 1 year ago
source link: https://blog.51cto.com/u_11822586/5398381
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

GCC编译器的常用选项​

1.1 gcc基本用法​

使用GCC编译器的时候,我们必须给出一系列必要的调用参数和文件名称。GCC编译器的调用参数大约有100多个,这里只介绍其中最基本、最常用的参数。

GCC最基本的用法∶

gcc [参数] [文件名称]

1.2 常用的参数​

-c 只编译:不链接成为可执行文件,编译器只是由输入的.c等源代码文件生成.o为后缀的目标文件,通常用于编译不包含主程序的子程序文件。

-o output_filename:确定输出文件的名称为output_filename,同时这个名称不能和源文件同名。如果不给出这个选项,gcc就给出预设的可执行文件a.out。

-g:产生符号调试工具(GNU的gdb)所必要的符号信息,要想对源代码进行调试,我们就必须加入这个选项。

-O:对程序进行优化编译、链接,采用这个选项,整个源代码会在编译、链接过程中进行优化处理,这样产生的可执行文件的执行效率可以提高,但是,编译、链接的速度就相应地要慢一些。

-O2:比-O更好的优化编译、链接,当然整个编译、链接过程会更慢。

-E:仅执行编译预处理;

-S:将C代码转换为汇编代码;

示例:

# gcc test.c -o app

1.3 编译时指定库与头文件路径​

-L:指定动态库路径。

示例:gcc test.c -o app -L/usr/lib

-I:指定头文件存放的路径。

示例:gcc test.c -o app -I/usr/include

-l: 指定库名称。

示例:gcc test.c -o app -lpthread

二、动态库与静态库的介绍​

我们通常把一些公用函数制作成函数库,供其它程序使用。函数库分为静态库和动态库两种。

通常情况下,对函数库的链接是放在编译时期(compile time)完成的。所有相关的对象文件(object file)与牵涉到的函数库(library)被链接合成一个可执行文件(executable file)。程序在运行时,与函数库再无瓜葛,因为所有需要的函数已拷贝到相应目录下下。所以这些函数库被成为静态库(static libaray),通常文件名为“libxxx.a”的形式。

两句话介绍解释:

静态库:在编译的时候加载生成目标文件,在运行时不用加载库,在运行时对库没有依赖性。

动态库:在目标文件运行时加载,对库有依赖性。

三、动态库的创建与调用​

3.1 生成和使用动态库的步骤​

linux下动态库文件的文件名形如 libxxx.so,其中so是 Shared Object 的缩写,即可以共享的目标文件。

在链接动态库生成可执行文件时,并不会把动态库的代码复制到执行文件中,而是在执行文件中记录对动态库的引用。

程序执行时,再去加载动态库文件。如果动态库已经加载,则不必重复加载,从而能节省内存空间。

Linux下生成和使用动态库的步骤如下:

1. 编写源文件。

2. 将一个或几个源文件编译链接,生成共享库。

3. 通过 -L<path> -lxxx 的gcc选项链接生成的libxxx.so。

4. 把libxxx.so放入链接库的标准路径,或指定 LD_LIBRARY_PATH,才能运行链接了libxxx.so的程序。

3.2 编译生成共享库的命令格式​

gcc -fPIC -shared -o <库文件名称>.so 源文件名称.c

gcc -fPIC -shared -o libabc.so abc.c

执行上面代码之后我们会得到libabc.so。

生成共享库之后可以通过file命令查看共享库的信息。

[wbyq@wbyq linux-share-dir]$ file sum/libsum.so

sum/libsum.so: ELF 32-bit LSB shared object, Intel 80386, version 1 (SYSV), dynamically linked, not stripped

实际上上述过程分为编译和链接两步, -fPIC是编译选项,PIC表示要生成位置无关的代码,这是动态库需要的特性; -shared是链接选项,告诉gcc生成动态库而不是可执行文件。

上述的一行命令等同于:

gcc -c -fPIC abc.c

gcc -shared -o libabc.so abc.o

3.3 调用动态库的例子​

gcc test.c -L ./ -labc 生成a.out,其中-labc表示要链接libabc.so。

-L ./表示指定搜索要链接的库文件时包含的路径。

注意,如果同一目录下同时存在同名的动态库和静态库,比如 libmax.so 和 libmax.a 都在当前路径下,则gcc会优先链接动态库。

执行程序:

运行 ./a.out 会得到以下的错误提示。

./a.out: error while loading shared libraries: libabc.so: cannot open shared object file: No such file or directory

找不到libabc.so,Linux是通过 /etc/ld.so.cache 文件搜寻要链接的动态库的。

而 /etc/ld.so.cache 是 ldconfig 程序读取 /etc/ld.so.conf 文件生成的。

(注意, /etc/ld.so.conf 中并不必包含 /lib 和 /usr/lib,ldconfig程序会自动搜索这两个目录)

如果我们把 libabc.so 所在的路径添加到 /etc/ld.so.conf 中,再以root权限运行 ldconfig 程序,更新 /etc/ld.so.cache ,a.out运行时,就可以找到 libabc.so。

但作为一个简单的测试例子,让我们改动系统的东西,似乎不太合适。

还有另一种简单的方法,就是为a.out指定 LD_LIBRARY_PATH。

LD_LIBRARY_PATH=. ./a.out

程序就能正常运行了。LD_LIBRARY_PATH=. 是告诉 a.out,先在当前路径寻找链接的动态库。

或者直接将xx.so拷贝到/lib下也可以。

3.4 查看系统环境变量​

设置系统环境变量: export <环境变名称>=环境变量的值

查看本地所有的环境变量: env

查看shell所有的环境变量: set

查看本地所有环境变量: export

四、静态库的创建与调用​

4.1 静态库介绍​

Linux上的静态库,其实是目标文件的归档文件。

在Linux上创建静态库的步骤如下:

  1. 写源文件,通过 gcc -c xxx.c 生成目标文件。
  2. 用 ar 归档目标文件,生成静态库。
  3. 配合静态库,写一个使用静态库中函数的头文件。
  4. 使用静态库时,在源码中包含对应的头文件,链接时记得链接自己的库。

4.2 创建静态库​

我们使用 ar 将目标文件归档:

ar crv libmylib.a my_print.o my_math.o

我们就得到了libmylib.a,这就是我们需要的静态库。

上述命令中 crv 是 ar的命令选项:

c 如果需要生成新的库文件,不要警告

r 代替库中现有的文件或者插入新的文件

v 输出详细信息

通过 ar t libmylib.a 可以查看 libmylib.a 中包含的目标文件。

注意:我们要生成的库的文件名必须形如 libxxx.a ,这样我们在链接这个库时,就可以用 -lxxx。

反过来讲,当我们告诉编译器 -lxxx时,编译器就会在指定的目录中搜索 libxxx.a 或是 libxxx.so。

4.3 调用静态库​

执行程序:

执行: gcc test.c -L. -lmylib

将会生成a.out,通过 ./a.out 可以运行该程序。说明我们的静态库能正常工作。

上面的命令中 -L. 告诉 gcc 搜索链接库时包含当前路径, -lmylib 告诉 gcc 生成可执行程序时要链接 libmylib.a。

注意:当同一个目录下,静态库与动态库重名时,优先使用动态库。

例如: libsum.a libsum.so 优先使用libsum.so


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK