1. 参数介绍
1.1 -i( -include:i 的小写) :包含头文件名字
- 用来
包含头文件名字
,但一般情况下包含头文件
都在源码里
用#include xxxxxx实
现,-include参数很少用
(一般不使用,而是直接放在**.c
文件中通过#include<***.h> 添加);
1.2 -I
- 指定
头文件路径
(相对路径或觉得路径,建议相对路径),/usr/include
目录一般是不用指定的,gcc知道去那里找
; - 如果头文件
不在/usr/include
里我们就要用-I
参数指定了,比如头文件放在/myinclude
目录里,那编译命令行就要加上-I/myinclude
参数了,如果不加你会得到一个"xxxx.h: No such file or directory"的错误。` -
-I
参数可以用相对路径
,比如头文件在当前目录可以用-I.
来指定;
1.2 -l
- 指定需要链接的
库的名字
(链接 libc.a :-lc 链接动态库:libc.so : -lc 注意:-l后面直接添加库名省区“lib”和“.so”或“.a” );
1.2 -L
- 指定连接的
动态库或者静态库路径
(相对路径或觉得路径,建议相对路径) ;
2. 搜索路径
2.1 静态库链接时搜索路径顺序
- ld会去找GCC命令中的
参数-L
- 再找gcc的环境变量
LIBRARY_PATH
(用法:LIBRARY_PATH= path
) - 再找内定目录
/lib
、/usr/lib
、/usr/local/lib
这是当初compile gcc时写在程序内的
(因系统版本而定 :/lib64)
2.2 动态库链接时、执行时搜索路径顺序
- 去找GCC命令中的
参数-L
- 环境变量
LD_LIBRARY_PATH
指定的动态库搜索路径 (LD_LIBRARY_PATH=path
) - 配置文件
/etc/ld.so.conf
中指定的动态库搜索路径 (修改/etc/ld.so.conf文件,将路径添加进去,运行/sbin/ldconfig
) - 默认的动态库搜索路径
/lib
(因系统版本而定:/lib64
) - 默认的动态库搜索路径
/usr/lib
(因系统版本而定)
2.3 头文件搜索路径
- 去
-I( i 的大写 )
指定的路径 - 源程序头(
#include ""
)文件中指定的路径 /usr/include
/usr/local/include
2.4 静态库、动态库环境变量
-
LIBRARY_PATH环境变量
:指定程序静态
链接库文件搜索路径 -
LD_LIBRARY_PATH环境变量
:指定程序动态
链接库文件搜索路径
3. -Wl,-rpath选项
-
-Wl,-rpath=<动态库文件位置>
,是为程序添加一个运行时库文件搜索路径
的命令,在使用gcc
编译链接时添加即可。即通过-Wl,-rpath=《lib_path》
可添加文件夹
作为动态库搜索路径
,并记录在
程序ELF可执行程序中
。我们调用程序时会去我们写入的目录中查找
的第三方库文件;-并非指定-rpath参数
后,就抛弃LD_LIBRARY_PATH
环境变量,只是多了个可选的依赖库路径而已。LD_LIBRARY_PATH
不仅指定可执行文件的库路径,还指定了库所依赖其它库的路径 - 假设
main.cpp、hello.h、hello.cpp
,其中main.cpp
调用了hello
类中的方法 - 使用
linux
编写c/c++
程序时,需要用到第三方的动态库
文件。刚开始编译完后,运行提示找不到动态库文件
。我就使用了ldd命令
查看了一下,发现是有一个库文件显示”not found
”,如下图所示; - 其中,有两个单独的部分
-Wl
和-rpath
组成。 -
-Wl
:
这个是gcc
的参数,表示编译器将后面的参数传递给链接器ld
。请注意此处的W是大写
的。 -
-rpath
:
使用man ld命令查看手册,找到了-rpath的讲解:运行
可执行文件时路径
还有效
(链接器已经将库的路径包含
在可执行文件中了) -
-rpath-link
:
运行
可执行文件时指定的路径
就不再有效
(链接器没有包含
进可执行文件中)
gcc test.c -lhello -L . -Wl,-rpath-link ./lib_tmp
-
-rpath
和-rpath-link
都可以在链接时指定库的路径
;但是运行可执行文件时
,-rpath-link
指定的路径就不再有效
(链接器没有包含
进可执行文件中),而-rpath
指定的路径还有效
(因为链接器已经将库的路径包含
在可执行文件中了)。 最后,不管使用了-rpath
还是-rpath-link
,LD_LIBRARY_PATH
还是有效的
3.1 生成hello.so
g++ -shared hello.cpp -o libhello.so
3.2 编译main.cpp、链接、指定运行时链接库(libhello.so)的位置
g++ main.cpp -lhello -L./ -Wl,-rpath=./ -o main
3.3 带版本号的动态库
- 例如
libhello.so.2
,链接命令可使用
g++ main.cpp libhello.so.2 -L./ -Wl,-rpath=./ -o main
3.4 加入第二个so库
g++ main.cpp -L./second/ -Wl,-rpath=./second/ -lsecond -L./hello/ -Wl,-rpath=./hello/ -lhello -o main
4. 可能问题
4.1 对于库文件未找到
- 因为
编译
、链接
都没有问题,那运行链接动态库时找不到动态库
了。对于运行链接动态库时找不到动态库的方法,最基本的解决方法四种
:
4.1.1 第一种方法(找到so放到/lib、/usr/lib目录中)
- 找到缺少的动态库(由于
编译
和链接
时候的使用到了这个动态库,所以很容易找得到),将其加到/lib、/usr/lib
和/usr/local/lib
中的一个文件夹下,这几个文件夹是系统默认的搜索路径
。将库文件放置在其中,运行时就可以搜索到了。
4.1.2 第二种方法(设置临时增加链接动态库的路径)
- 使用命令行
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:《your_lib_path》
- 比如我的
libhello.so
在/home/huyf/myapp/lib
目录下,那我使用的是:
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/huyf/myapp/lib
- 这种方法设置的是
临时的
,系统重启之后
就没了
。当然也可以设置为持久的
,这里就不过多讲述。
4.1.3 第三种方法(更改配置文件)
-
/etc/ld.so.cache
中缓存
了动态库路径
,可以通过修改配置
文件/etc/ld.so.conf
中指定的动态库搜索路径
,然后执行ldconfig命令
来改变。 - 不过,我又想了一下,感觉这几种方法都不适合我现在的情况,这些都是事后补救的方法。首先,我不可能每次需要用到一个第三方的动态库的时候都要往几个系统默认的文件夹里面扔,这会导致这几个文件夹越来越大,越来越乱;再者,我也不想每次都设置临时动态库搜索路径,每个程序这么做的话得设置多少次啊,而且也导致文件夹变多,总归不好;而更改配置我就更不推荐了,会导致配置文件越来越乱。
4.1.4 第四种方法(在链接时使用-Wl,-rpath命令)
-Wl,-rpath=《my_thirdparty_lib_path》
4.2 -l(L的小写)链接的到底是动态库还是静态库?
如果链接路径下同时有 .so 和 .a 那优先链接 .so
4.3 如果路径下同时有静态库和动态库如何链接静态库?
- 使用显示链接,
gcc -l:lib***.a (将静态库的名字显示写出来)
或者在 gcc 编译的时候 加入参数-static -lxxx
, 则可以添加路径下面的静态库。比如同一目录下有libxxx.a
文件和libxxx.so
文件,gcc默认会链接xxx.so
,改变这一默认行为的方法就是:将"-lxxx
"改为"-l:libxxx.a
",或者-static -lxxx
,把.a
它当.o
文件一样链接 - 验证方法:
可以通过ldd 命令
查看生成的目标文件
链接的库,使用方法:ldd ***.o