Total Pageviews

Sunday, 3 July 2016

编译程序时,头文件、链接库文件的一些问题

以*nix为例,程序编译时,经常会使用到-I、-L、-l这三个参数,举例如下:
-I/home/fz/mpich/include
-L/usr/local/lib
-lmpi
-I+路径表示编译该程序时第一个寻找头文件的目录,之后是/usr/include、/usr/local/include(与lib不同,/usr/local/include一般是默认路径,而/usr/local/lib一般需要自己添加)。
-L+路径表示编译该程序时第一个寻找库文件的目录,之后是/lib、/usr/lib。用户常用库路径/usr/local/lib一般需要自己添加。
-l+库名称表示编译该程序时使用的动态链接库文件名称,例如-lmpi表示使用libmpi.so这一动态链接库。如果在该参数前使用-Bstatic参数,即-Bstatic -lmpi,则表示使用的是静态链接库,即libmpi.a。不加的话则默认是动态的,也就是-Bdynamic。
我们知道,若想让一个程序运行时去调用某个动态链接库,则程序编译时需要使用-l参数指定动态链接库。
这里有两个问题:
1、编译器从哪去找名为libmpi.so的动态链接库文件?
2、程序运行时从哪去找名为libmpi.so的动态链接库文件?
首先,编译器、程序运行都会从默认库文件路径里去找,也就是/lib和/usr/lib,但是如果不在这两个目录之中怎么办呢?
答案是:
1、编译器可以使用-L参数指定寻找动态链接库文件的路径。

2、想要程序运行时从某个目录寻找动态链接库文件,那就需要修改LD_LIBRARY_PATH这个环境变量的值了,例如这篇文章中配置NetCDF-C的过程。

不过,既然可以通过环境变量指定程序运行时调用的动态链接库路径,那么能否指定程序编译时所用的动态链接库路径,这样就无需使用-L参数了?

当然可以!使用LIBRARY_PATH环境变量即可!

另外,既然程序编译、运行时所有的动态链接库路径都可以用环境变量指定,那么程序编译时使用的头文件能否用环境变量指定呢?
其实也是可以的,不过不同编译器可能会使用不同的环境变量,例如GCC使用的是C_INCLUDE_PATH、CPLUS_INCLUDE_PATH、OBJC_INCLUDE_PATH。

总结一下上面所说的几点:
程序编译时所用的动态链接库路径,需要使用-L参数来指定。不过,也可以在LIBRARY_PATH环境变量中添加,从而无需使用-L参数手动指定。但是-l一直都是需要的,它用来告诉编译器该程序会调用哪个动态(静态)链接库。
程序运行时所用的动态链接库路径,需要在LD_LIBRARY_PATH环境变量中添加。
程序编译时所用的头文件路径,也可以在对应的环境变量中添加,而无需使用-I参数手动指定。不过不同编译器使用的环境变量可能会不一样.