最近尝试用libcurl写点东西,但是自己基本没啥会的,又遇上了编译链接的问题。(以下以ubuntu系统作为环境)
在此之前,我对动态链接和静态链接的错误理解是,通过静态方式链接的程序需要在目录中留存这个静态链接库;而通过动态方式链接的程序则在目录中留一个动态链接库,用来查找系统中变量路径和内存中是否存在对应的库。所以我那时认为如果系统没有完整的对应库最终会导致通过动态链接的程序无法正常启动。。。
后来发现这样并不对,经由静态链接后产生的程序是可以删除.a文件的,完全不影响;而动态链接产生的程序是需要在动态链接库目录中存在对应的动态链接库的。
我根据教程进行了两种链接方式的实现,教程地址:静态链接库和动态链接库的区别 - 云+社区 - 腾讯云 (tencent.com)
静态链接
生成中间文件.o
将需要用到的源码编译成中间文件
1 |
|
生成的对应名称的中间文件
通过中间文件生成.a静态库
须知无论是静态库还是动态库都需要以lib作为文件名的开头,但是调用时候不需要带lib
1 |
|
将主程序编译并与静态库链接生成可执行文件
1 |
|
.
表示在当前目录中查找静态链接库。必须添加
编译完成后可通过使用./main
运行程序,此时删除libmymath.a
文件,程序依然能正常运行。
动态链接
生成中间文件.o
与之前相同
通过中间文件生成.so的动态库
1 |
|
将主程序编译并与动态库链接生成可执行文件
1 |
|
使用./main
运行程序
不出意外的话会报错
./main: error while loading shared libraries: libmymath.so: cannot open shared object file: No such file or directory
需要将libmymath.so
文件放至动态库文件中,比如/usr/lib
文件中,此时再运行文件,会发现程序可以正常运行。
分析
运行
1 |
|
输出
1 |
|
这些是ubuntu在运行此main
程序时调用到的动态库。
可以看到/lib/libmymath.so
,由于/lib实际上为/usr/lib路径的映射,所以main程序实际上调用的是/usr/lib目录中的libmymath.so文件。
手动指定该程序的动态链接库目录
可以通过在编译main并链接mymath动态库时候利用-Wl,-rpath
参数手动指定动态目录位置。
gcc -o main main.c -L. -l mymath -Wl,-rpath=.
由于之前生成的动态链接库libmypath.so
已经在程序目录中存在,所以当使用rpath指定动态链接库的目录时可以不用将自己编写的动态链接库放到系统的动态链接库目录中。
注意,rpath优先级强于ld.so
由于在未指定rpath参数的情况下,系统会将动态链接库的查找转交给ld.so程序(你可以在/etc/ld.so/
目录中查看相关配置)
而在指定rpath参数后,系统程序会优先使用rpath指定的路径查找动态链接库,所以可以将动态库放到自己设置的相对路径的文件夹中,而不是系统目录,来防止污染。
此时,如果你使用ldd main
会发现输出已经变成了
1 |
|