这是一篇从主博客转移而来的文章。
本文本来是写在Ubuntu 14.04 LTS下配置MPICH、NetCDF、ifort环境这篇文章中的,后来考虑到篇幅太长,因此单独把它拿出来了。
以*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
。也就是说,编译器会先去找so动态链接库,如果找不到则再去找a静态链接库,若还是找不到则报错。
我们知道,若想让一个程序运行时去调用某个动态链接库,则程序编译时需要使用-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
参数手动指定。不过不同编译器使用的环境变量可能会不一样。
最后要提一点:如果在编译时链接了so动态链接库,程序想要运行,就得使用LD_LIBRARY_PATH
指定动态链接库所在目录。因为动态链接库的特性就是在运行时才载入,如果不指定它的路径,那么程序肯定就找不到相关函数和变量,没法运行。那既然只在运行时才需要它的内容,为什么编译的时候也需要链接它呢?这是为了让编译器知道它需要哪些so文件以及在其中可以找到哪些函数和变量,这样当程序运行的时候,就会将它需要的so文件载入,不然程序怎么知道它要载入哪些动态链接库文件呢?而且这样做的话如果找不到某个库,也可以提示出具体缺少哪个so文件。
Comments
注:如果长时间无法加载,请针对 disq.us | disquscdn.com | disqus.com 启用代理。