#. 前言
1. 无论在编译自己写的代码还是大型开源项目的源码(如mysql、opencv等)时,总会遇到链接器ld报错,提示找不到xxx头文件、库文件;
2. 终于历尽千辛万苦编译好了代码,当运行时又会报找不到xxx库文件;
以上两种情况是我们程序员在实际工作中经常会遇到的情况,我也是在经历了种种痛苦之后,痛定思痛下决心好好总结一下,下次遇到后起码可以自己尝试着去解决,免得一顿百度之后各种尝试最终无果,又开始各种抓狂各种问候。。。
这里有必要说明一下,需要明确区分是否是交叉编译,以及是代码编译时还是运行时,情况不同查找的位置也会不同。
#. 从简单的示例开始
add.h
add.c
test.c
编译并生成动态库libadd.so
一. 正常编译(x86)
1. 编译时
可以看到,当前目录下有如下几个文件:
执行如下命令,未加任何参数进行编译test.c,报错如下:
执行如下命令,仅加入-ladd参数进行编译test.c,报错如下:
执行如下命令,仅加入-L.参数进行编译test.c,报错如下:
执行如下命令,加入-ladd以及-L.参数进行编译test.c,编译成功:
,
将add.h移动到上一级目录,执行如下命令进行编译,报错如下:
执行如下命令,加入-ladd以及-L.以及-I..编译test.c,编译成功:
a. 头文件
#include <xxx> 优先级由高到低搜索顺序:
-I指定的头文件位置 > /usr/include 以及 /usr/local/include >
#include "xxx" 优先级由高到低搜索顺序:
当前目录 > -I指定的头文件位置 > /usr/include 以及 /usr/local/include >
b. 库文件
优先级由高到低搜索顺序:
-L指定的库文件位置 > /usr/lib/yi/u 以及 /local/lib 以及 /lib
2. 运行时
执行如下命令编译成功,并运行报错如下::
执行如下命令编译成功,并运行成功:
a. 头文件
运行时无需搜索头文件
b. 库文件
优先级由高到低搜索顺序:
-Wl,rpath库文件的位置 > LD_LIBRARY_PATH环境变量指定的位置 > /etc/ld.so.conf配置文件中指定的位置 > /usr/lib/ 以及 /usr/local/lib 以及 /lib
二. 交叉编译(arm)
1. 编译时
a. 头文件
#include <xxx> 优先级由高到低搜索顺序:
-I指定的头文件位置 > 交叉编译器目录下自带的头文件目录
#include "xxx" 优先级由高到低搜索顺序:
当前目录 > -I指定的头文件位置 > 交叉编译器目录下自带的头文件目录
b. 库文件
优先级由高到低搜索顺序:
-L指定的库文件位置 > 交叉编译器目录下自带的库文件目录
2. 运行时
a. 头文件
运行时无需搜索头文件
b. 库文件
优先级由高到低搜索顺序:
-Wl,rpath库文件的位置 > LD_LIBRARY_PATH环境变量指定的位置 > /etc/ld.so.conf配置文件中指定的位置 > 交叉编译器目 录下自带的库文件目录
附:对于elf格式的可执行程序,是由ld-linux.so*来完成的,它先后搜索elf文件的 DT_RPATH
段, 环境变量 LD_LIBRARY_PATH
, /etc/ld.so.cache文件列表, /lib/,/usr/lib目录, 找到库文件后将其载入内存. (http://blog.chinaunix.net/uid-23592843-id-223539.html)
#. 不同编译器编译出的产物的兼容性
这个留待日后再议。