目录
一、用gcc生成静态库和动态库
(一).用gcc生成.a静态库
(二)由.o文件创建动态库
二、使用库的实例1
(一)静态库.a 文件的生成与使用。
(二)共享库.so 文件的生成与使用
三、实例2
(一)静态库.a 文件的生成与使用。
(二)共享库.so 文件的生成与使用
(三)静态库和动态库生成文件比较
*静态库:在程序编译时会被链接到代码中,程序运行时将不再需要静态库。其后缀是lib。
*动态库:在程序编译并不会链接到代码中,而是在程序运行时被载入,动态库又被称为动态链接库,英文简称DLL,DLL是包含可以由多个程序使用的代码和数据的库,DLL是不可执行文件。
(1)编辑生成hello.h、hello.c和main.c。
用vim文本编辑器分别写出hello.h、hello.c和main.c。
hello.c:
main.c:
(2)将hello.c编译成.o文件
1.将程序hello.c通过gcc编译成.o文件,得到hello.o文件。
2.运行ls命令,看是否生成了hello.o文件。
出现了hello.o文件,即编译成功。
(3)由.o文件创建静态库
静态库文件名的命名以lib为前缀,然后跟库名,扩展名为.a。创建静态库用命令:ar。
此时可将我们的静态库名设置为hello,则静态库文件名为libhello.a。
创建静态库并查看创建是否成功:
输入命令:ar -crv libhello.a hello.o
再输入命令:ls
结果如图:
出现了libhello.a,创建成功。
(4)在程序里使用静态库
1:输入命令:gcc -o hello main.c -L. -lhello
用命令:./hello运行得到结果
2.输入命令:gcc main.c libhello.a -o hello
3.输入命令: gcc -c main.c(生成main.o)
再输入命令:gcc -o hello main.c libhello.a(生成可执行的文件)
动态库文件名命名规范和静态库文件名命名规范类似,也是在动态库名增加前缀 lib,但其 文件扩展名为.so。
1.得到动态库文件libhello.so,输入命令:gcc -shared -fPIC -o libhello.so hello。
2.检查是否成功创建,输入命令:ls。
如图所示,成功创建动态库文件libhello.so。
3.在程序里使用动态库
输入命令:gcc -o hello main.c -L. -lhello
在输入命令:./hello
得到结果如图所示:
创建A1.c:
创建A2.c:
创建A.h
创建test.c :
1.生成目标文件(A1.o和A2.o)
输入命令:gcc -c A1.c A2.c
2.生成静态库.a 文件
输入命令:ar crv libafile.a A1.o A2.o
3.使用.a 库文件,创建可执行程序
输入命令:gcc -o test test.c libafile.a和./test
1.生成目标文件(A1.o和A2.o)
输入命令:gcc -c -fpic A1.c A2.c
2. 生成共享库.so 文件
输入命令:gcc -shared *.o -o libsofile.so
3.使用.so 库文件,创建可执行程序
输入命令:gcc -o test test.c libsofile.so
发现错误,确实是找不到对应的.so 文件。
这是由于 linux 自身系统设定的相应的设置的原因,即其只在/lib and /usr/lib 下搜索对应 的.so 文件,故需将对应 so 文件拷贝到对应路径。
输入命令:sudo cp libsofile.so /usr/lib和./test来验证
结果可以成功运行。
还可以直接输入命令:gcc -o -test -test.c -L. -lsofile
创建sub1.c:
创建sub2.c:
创建sub.h:
创建main.c:
1.生成目标文件(sub1.o和sub2.o)
输入命令:gcc -c sub1.c sub2.c
2.生成静态库.a 文件
输入命令:ar crv libtest.a sub1.o sub2.o
3.使用.a 库文件,创建可执行程序
输入命令:gcc -o main main.c libtest.a和./main
1.生成目标文件(sub1.o和sub2.o)
输入命令:gcc -c -fpic sub1.c sub2.c
2. 生成共享库.so 文件并使用.so库文件,创建可执行程序
输入命令:gcc -shared -fPIC -o libtest.so sub1.o sub2.o和gcc -o main main.c libtest.so
移动动态库的目的地:sudo cp libtest.so /usr/lib
得出结果如图:
通过该图可知道,静态库生成的文件比动态库生成的文件更小。
GCC 的意思也只是 GNU C Compiler 而已。经过了这么多年的发展,GCC 已经不仅仅能支持 C 语言;它现在还支持 Ada 语言、C++ 语言、Java 语言、Objective C 语言、Pascal 语言、COBOL 语言,以及支持函数式编程和逻辑编程的 Mercury 语言,等等。
程序如下:
一步到位编译指令:gcc test.c -o test
但实质上,上述编译过程是分为四个阶段进行的,即预处理(也称预编译,Preprocessing)、编译 (Compilation)、汇编 (Assembly)和连接(Linking)。
1.预处理:gcc -E test.c -o test.i 或 gcc -E test.c
test.i的部分代码:
2.编译为汇编代码:gcc -S test.i -o test.s
test.s部分代码:
3.汇编:gcc -c test.s -o test.o或直接调用as,即$ as -c hello.s -o hello.o
4.连接:gcc test.o -o test
gcc test1.c test2.c -o test
可细分成下面三步:
gcc -c test1.c -o test1.o
gcc -c test2.c -o test2.o
gcc test1.o test2.o -o test
gcc -pedantic illcode.c -o illcode -pedantic
-pedantic 编译选项并不能保证被编译程序与 ANSI/ISO C 标准的完全兼容,它仅仅只能用来帮助 Linux 程序员离这个目标越来越近。
除了-pedantic 之外,GCC 还有一些其它编译选项也能够产生有用的警告信息。这些选项大多以-W 开头,其中最有价值的当数-Wall 了。
所以,在编译程序时带上-Werror 选项,那 么 GCC 会在所有产生警告的地方停止编译,迫使程序员对自己的代码进行修改,如下:
gcc -Werror test.c -o test
正确时:
出错时:
1.编译成可执行文件
2.链接
3.强制链接时使用静态链接库
默认情况下, GCC 在链接时优先使用动态链接库,只有当动态链接库不存在时才考虑使用静态链 接库,如果需要的话可以在编译时加上-static 选项,强制使用静态链接库.
gcc test.c -o test
size test //使用 size 查看大小
ldd test //可以看出该可执行文件链接了很多其他动态库
使用命令“gcc -static test.c -o test”则 会 使 用 静 态 库 进 行 链 接 ,如下图所示:
同样用size test和ldd test进行查看:
可以看出,现在text的代码尺寸变得极大并且说明没有链接动态库。
链接器链接后生成的最终文件为 ELF 格式可执行文件,一个 ELF 可执行文件通常 被链接为不同的段,常见的段譬如.text、.data、.rodata、.bss 等。
1.ELF 文件的段
ELF 文件格式如下图所示,位于 ELF Header 和 Section Header Table 之间的都 是段(Section)。一个典型的 ELF 文件包含下面几个段:
.text:已编译程序的指令代码段。
.rodata:ro 代表 read only,即只读数据(譬如常数 const)。
.data:已初始化的 C 程序全局变量和静态局部变量。
.bss:未初始化的 C 程序全局变量和静态局部变量。
.debug:调试符号表,调试器用此段的信息帮助调试。
输入命令:readelf -S test
2.反汇编 ELF
由于 ELF 文件无法被当做普通文本文件打开,如果希望直接查看一个 ELF 文件包 含的指令和数据,需要使用反汇编的方法。
输入命令:objdump -D test进行反汇编
再使用 objdump -S 将其反汇编并且将其 C 语言源代码混合显示出来:
输入命令:gcc -o test -g test.c
objdump -S test
四、总结
通过此次作业,我学会了gcc编译的静态和动态库的建立以及文件的编译运行,对我的启发很大,同时对于ubuntu系统也有了更深刻的理解和使用。
参考博客:https://blog.csdn.net/qq_43279579/article/details/109026927