Total Pageviews

Saturday, 6 October 2018

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

以*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这个环境变量的值了.
不过,既然可以通过环境变量指定程序运行时调用的动态链接库路径,那么能否指定程序编译时所用的动态链接库路径,这样就无需使用-L参数了?
当然可以!使用LIBRARY_PATH环境变量即可!
另外,既然程序编译、运行时所有的动态链接库路径都可以用环境变量指定,那么程序编译时使用的头文件能否用环境变量指定呢?
其实也是可以的,不过不同编译器可能会使用不同的环境变量,例如GCC使用的是C_INCLUDE_PATHCPLUS_INCLUDE_PATHOBJC_INCLUDE_PATH
总结一下上面所说的几点:
  • 程序编译时所用的动态链接库路径,需要使用-L参数来指定。不过,也可以在LIBRARY_PATH环境变量中添加,从而无需使用-L参数手动指定。但是-l一直都是需要的,它用来告诉编译器该程序会调用哪个动态(静态)链接库。
  • 程序运行时所用的动态链接库路径,需要在LD_LIBRARY_PATH环境变量中添加。
  • 程序编译时所用的头文件路径,也可以在对应的环境变量中添加,而无需使用-I参数手动指定。不过不同编译器使用的环境变量可能会不一样。
最后要提一点:如果在编译时链接了so动态链接库,程序想要运行,就得使用LD_LIBRARY_PATH指定动态链接库所在目录。因为动态链接库的特性就是在运行时才载入,如果不指定它的路径,那么程序肯定就找不到相关函数和变量,没法运行。那既然只在运行时才需要它的内容,为什么编译的时候也需要链接它呢?这是为了让编译器知道它需要哪些so文件以及在其中可以找到哪些函数和变量,这样当程序运行的时候,就会将它需要的so文件载入,不然程序怎么知道它要载入哪些动态链接库文件呢?而且这样做的话如果找不到某个库,也可以提示出具体缺少哪个so文件.

No comments:

Post a Comment