我们知道,C语言的编译过程可以分为下面几个步骤:
gcc -E hello.c -o hello.i 1.预处理 文件展开及宏展开
gcc -S hello.i -o hello.s 2.编译 将预处理之后的.i文件生成.s汇编文件
gcc -c hello.s -o hello.o 3.汇编 将.s汇编文件生成.o目标文件
gcc hello.o -o hello_elf 4.链接 将.o文件链接成目标文件
实际使用时,我们很可能会用到静态库和动态库,下面就来详细讲讲这两者的制作和使用方式。
静态编译和动态编译区别: 1、动态编译使用动态库,静态编译使用静态库 2、静态编译要把静态库文件打包到可执行程序中,动态编译不会把动态库文件打包到可执行程序中,它只是编译链接关系。
动态库
gcc hello.c -o hello
使用动态库文件进行编译,动态库并没有被编译到可执行程序当中去,在运行可执行程序的时候,根据链接关系去动态库中加载代码。
制作动态库: gcc -shared mylib.c -o libtestlib.so
编译程序:
方法一: gcc mytest.c libtestlib.so -o mytest
方法二: gcc mytest.c -o mytest -L/home/teacher -ltestlib -I/home/teacher
以上两种方式编译通过,运行时出错,编译时找到了库函数,但链接时找不到,执行以下操作: export LD_LIBRARY_PATH=./:$LD_LIBRARY_PATH 表示将当前路径./加到搜索路径中去,运行时链接动态库就会从当前路径中去寻找动态库
方法三: 将库文件和头文件放到系统默认指定的路径下(库文件默认的路径是/lib或者是/usr/lib,头文件默认的路径是/usr/include),此时就不需要设定环境变量了
sudo mv libtestlib.so /usr/lib
sudo mv mylib.h /usr/include
gcc mytest.c -o mytest -ltestlib
静态库
gcc -static hello.c -o hello
使用静态库文件进行编译,可执行文件体积大,但运行时不需要依赖额外的库文件。
制作静态库:
gcc -c mylib.c -o mylib.o
ar rc libtestlib.a mylib.o
注意:静态库起名的时候必须以lib开头,以.a结尾
编译程序:
方法一: gcc -static mytest.c libtestlib.a -o mytest
方法二: 比如将libtestlib.a和mylib.h移动到/home/teacher下(mv libtestlib.a mylib.h /home/teacher)
gcc -static mytest.c -o mytest -L/home/teacher -ltestlib -I/home/teacher
-L指定库文件的路径
-l指定找哪个库,取lib和.a之间的部分
-I指定头文件的路径
方法三: 将库文件和头文件放到系统默认指定的路径下(库文件默认的路径是/lib或者是/usr/lib,头文件默认的路径是/usr/include)
sudo mv libtestlib.a /usr/lib
sudo mv mylib.h /usr/include
gcc -static mytest.c -o mytest -ltestlib
注意:
上面将静态库和动态库都放在了/usr/lib下,那么链接(gcc mytest.c -o mytest -ltestlib)的到底是动态库还是静态库呢?
- 当静态库和动态库重名的时候,系统优先链接动态库,或者可以加入-static指定使用静态库