昨天在本身的CentOs7.1上写makefile的时候,发如今一个C程序在编译并连接一个已生成好的lib动态库的时候出错。连接命令大概是这样的:html
[root@typecodes tcpmsg]# gcc -o hello main.c -lmyhello /usr/bin/ld: cannot find -lmyhello collect2: error: ld returned 1 exit status
自觉得在当前工程中设置好了环境变量 LD_LIBRARY_PATH
包含了工程中的lib库路径,而且还在 /etc/ld.so.conf/apphome.conf
中配置了lib库的路径。那么在调用动态库的时候,gcc就应该能自动去搜索该目录。linux
很遗憾ld连接器报了如上的错误,可是若是在上面的gcc命令中添加上 -L /root/gcc_test/tcp_msg/lib/
参数,即明确动态库的绝对路径,是可以连接成功的。app
gg了好久gcc ld连接动态库出错的缘由,结果仍是没找到理想的答案。后来猜测是否是在CentOs7中LD_LIBRARY_PATH不起做用的缘故,可是也不该该,由于本身用的GCC(version 4.8.3)跟操做系统不要紧。因而从新搜索了gcc LD_LIBRARY_PATH的做用,居然发现gcc在编译连接时连接的动态库跟 LIBRARY_PATH
有关而跟 LD_LIBRARY_PATH
不要紧!less
3 关于Linux gcc中的 LIBRARY_PATH
和 LD_LIBRARY_PATH
参数说明tcp
下面摘取了两篇较权威的说明资料:ui
一、 GNU 上关于LIBRARY_PATH的说明:spa
LIBRARY_PATH
The value of LIBRARY_PATH is a colon-separated list of directories, much like PATH. When configured as a native compiler, GCC tries the directories thus specified when searching for special linker files, if it can't find them using GCC_EXEC_PREFIX. Linking using GCC also uses these directories when searching for ordinary libraries for the -l option (but directories specified with -L come first).
二、 man7 上关于LD_LIBRARY_PATH的说明:操作系统
LD_LIBRARY_PATH
A colon-separated list of directories in which to search for ELF libraries at execution-time. Similar to the PATH environment variable. Ignored in set-user-ID and set-group-ID programs.
后面发现 StackOverflow 上关于 LIBRARY_PATH
和 LD_LIBRARY_PATH
的解释更直白:code
LIBRARY_PATH is used by gcc before compilation to search for directories containing libraries that need to be linked to your program. LD_LIBRARY_PATH is used by your program to search for directories containing the libraries after it has been successfully compiled and linked. EDIT: As pointed below, your libraries can be static or shared. If it is static then the code is copied over into your program and you don't need to search for the library after your program is compiled and linked. If your library is shared then it needs to be dynamically linked to your program and that's when LD_LIBRARY_PATH comes into play.
经过这三篇资料的说明,很快明白了 LIBRARY_PATH
和 LD_LIBRARY_PATH
的做用。因而,本身在项目配置文件中添加 export LIBRARY_PATH=${LIBRARY_PATH}:${APPHOME}/lib
。接着将这个配置文件加载到CentOs的环境变量中,这样就在gcc编译不用加 -L
参数生成目标文件CommuTcp了。regexp
关于 LIBRARY_PATH
和 LD_LIBRARY_PATH
的关系,这里本身再总结一下。
4.1 Linux gcc编译连接时的动态库搜索路径
GCC编译、连接生成可执行文件时,动态库的搜索路径顺序以下(注意不会递归性地在其子目录下搜索):
一、gcc编译、连接命令中的-L选项; 二、gcc的环境变量的LIBRARY_PATH(多个路径用冒号分割); 三、gcc默认动态库目录:/lib:/usr/lib:usr/lib64:/usr/local/lib。
4.2 执行二进制文件时的动态库搜索路径
连接生成二进制可执行文件后,在运行程序加载动态库文件时,搜索的路径顺序以下:
一、编译目标代码时指定的动态库搜索路径:用选项-Wl,rpath和include指定的动态库的搜索路径,好比gcc -Wl,-rpath,include -L. -ldltest hello.c,在执行文件时会搜索路径`./include`; 二、环境变量LD_LIBRARY_PATH(多个路径用冒号分割); 三、在 /etc/ld.so.conf.d/ 目录下的配置文件指定的动态库绝对路径(经过ldconfig生效,通常是非root用户时使用); 四、gcc默认动态库目录:/lib:/usr/lib:usr/lib64:/usr/local/lib等。
其中,Linux GCC默认的动态库搜索路径能够经过 ld --verbose
命令查看:
[root@typecodes tcpmsg]# ld --verbose ............ SEARCH_DIR("/usr/x86_64-redhat-linux/lib64"); SEARCH_DIR("/usr/local/lib64"); SEARCH_DIR("/lib64"); SEARCH_DIR("/usr/lib64"); ##### 64位系统 SEARCH_DIR("/usr/x86_64-redhat-linux/lib"); SEARCH_DIR("/usr/local/lib"); SEARCH_DIR("/lib"); SEARCH_DIR("/usr/lib");