记录一个以前遇到一个问题,代码没问题,但是g++编译出现了问题。
这边先说结果:
g++ ... obj($?) -l(上层逻辑lib) -l(中间封装lib) -l(基础lib) -l(系统lib) -o $@
gcc -l 官方解释如下:
-l library
Search the library named library when linking. (The second alter-
native with the library as a separate argument is only for POSIX
compliance and is not recommended.)
It makes a difference where in the command you write this option;
the linker searches and processes libraries and object files in the
order they are specified. Thus, foo.o -lz bar.o searches library z
after file foo.o but before bar.o. If bar.o refers to functions in
z, those functions may not be loaded.
翻译一下
如果你的库在链接时安排的顺序是:foo.o -lz bar.o。
那么gcc的链接器先搜索库foo,然后是z库,然后是bar库。
这样就带来一个问题,如果库bar调用了库z里面的函数,但是链接器是先搜索的库z,这时候并没有发现库bar调用库z啊,所以就不会把库z中的这部分函数体挑出来进行链接。而是只把库z中,被foo库调用的函数体挑出来。
所以要把最基础实现的库放在最后,这样左边的lib就可以调用右边的lib中的代码。
查看一个可执行文件或动态库依赖哪些动态库
readelf -d
ldd
文件结构:
fun.h
#ifndef _FUN_H
#define _FUN_H
void fun();
#endif //!_FUN_H
fun.cpp
#include
#include "fun.h"
void fun()
{
std::cout << "fun" << std::endl;
}
编译链接库
g++ -c -fpic fun.cpp -I./include/
g++ -shared *.o -o ./lib/libFun.so
main.cpp
#include "fun.h"
int main()
{
fun();
return 0;
}
编译程序
g++ main.cpp -o main -I./include/ -L./lib/ -lFun
运行发现报错
发现在系统默认路径里面找不到我们的动态链接库
去网上找了一下默认查找路径:
- gcc 编译时指定的运行时库路径
-Wl,-rpath
- 环境变量
LD_LIBRARY_PATH
- ldconfig 缓存
/etc/ld.so.cache
- 系统默认库位置
/lib /usr/lib
这边就使用第一个吧
g++ main.cpp -o main -Wl,--rpath=./lib/ -I./include/ -L./lib/ -lFun
运行没问题了
现在的问题我们编译的时候命令会不会写成下面这种:
g++ -o main -Wl,--rpath=./lib/ -I./include/ -L./lib/ -lFun main.cpp
编译直接报错,找不到库,我们把动态链接库放到了.o文件前面,因为解析的时候是从右往左,所以解析.o文件的时候找不到动态链接库了。