gcc 静态编译与动态编译

 gcc中的连接选项(Linker Options)

-LDirectory

-L    用于指定连接库所需要的搜索路径,后面的参数“Directory”为相对路径或绝对路径
-llibrary

-l    用于指定连接库文件选项例如:-lmylib 如果存在静态库,则意味着需要连接libmylib.a;如果存在动态库,则意味着需要连接libmylib.so

-static       

-static     采用静态连接的方式连接程序
-shared     
生成可共享的被其他程序连接的目标模块

gcc程序生成过程的两个阶段:

step1.编译源文件生成目标文件(*.o
gcc -c -o main.o main.c
step2.连接目标文件,生成可执行程序
gcc main.o -o test               //
动态连接方式生成可执行程序
gcc main.o -static -o test_static     //
生成静态连接的可执行程序

生成动态库:

比如:gcc -shared test.o -o libtest_d.so //test.o文件连接,生成动态库的名称为libtest_d.so
生成动态可执行文件:
gcc test.o -L. -ltest_d -o test_dlib //
生成动态连接的可执行程序test_dlib
-L.
在连接时搜索库文件的时候包含当前目录;-ltest_d连接名称为libtest_d.so的动态库。


实验步骤:

1.编写测试程序:

用vi编写say.c程序如下:
#include "stdio.h"
void say()
{
printf("Say!");
}

用vi编写test.c程序如下:
#include "stdio.h"
void say();
main(){
say();
}


2.静态编译:

2.1. 编译源文件生成目标文件say.o

gcc -c say.c
2.2. 使用静态编译归档命令ar将目标文件编译成say.a静态库文件

ar -r say.a say.o
2.3. 编译test.c文件并连接目标静态库文件say.a生成可执行程序test

gcc test.c say.a -o test (或上一步用名字libsay.a,这里用命令gcc test.c -L. -lsay -o test)
2.4. 测试

file test
test: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), for GNU/Linux2.2.5, dynamically linked (uses shared libs), not stripped

ldd test
       libc.so.6 => /lib/tls/libc.so.6(0x42000000)
       /lib/ld-linux.so.2 =>/lib/ld-linux.so.2 (0x40000000)
输出结果让我们看不到任何跟say.a这个我们自己写的静态库的关系.说明程序运行时已经不需要这个静态库了,它已经被ld链接进最终的程序了.

3.动态编译

3.1.

gcc -fPIC -shared say.c -o say.so
3.2.

gcc test.c say.so -o test(如果这里用gcc test.c ./say.so -o test则把say.so的相对路径硬编码进了程序里,ldd查看可知能找到)
3.3.测试

ldd test
(或用gcc -shared -Wall -g say.c -olibsay_d.so;再gcc test.c -L. -lsay_d -o test;最后用ldd test查看)
4.测试结果
ldd test
       say.so => not found
       libc.so.6 => /lib/tls/libc.so.6(0x42000000)
       /lib/ld-linux.so.2 =>/lib/ld-linux.so.2 (0x40000000)
file test
test: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), for GNU/Linux2.2.5, dynamically linked (uses shared libs), not stripped
如果不出意外的话,会出现say.so => notfound.这时的./test是不能运行的.这是因为默认动态库搜索路径还没有设置,所以找不到say.so在哪,但至少说明程序运行时是需要这个库的.

===========================
.so文件 搜索顺序:
LD_LIBRARY_PATH
变量
ld.so.cache (由 ldconfig 生成)
binutils 编译时候指定的 --with-lib-path 参数

还有,如果要让 ldconfig 搜索到相应的 so 文件,文件名必须要是 libXXXX.so 这样的格式才行。
===========================

所以想让上面动态编译的程序能够运行,可以用如下方法将当前路径“.目录”加入搜索范围,或将say.so拷贝至/lib等默认搜索路径:

exportLD_LIBRARY_PATH=.
******************************(或可直接LD_LIBRARY_PATH=1 ./test1)
******************************(或/sbin/ldconfig ./;./test)

猜你喜欢

转载自blog.csdn.net/Mrs_Yu/article/details/79940799