文章目录

  • 1.LIBRARY_PATH和LD_LIBRARY_PATH区别
    • 1.1.两个环境变量的不同
    • 1.2.使用场景
  • 2.配合CMake实验测试
    • 2.0.文件结构
    • 2.1.测试1:LIBRARY_PATH包含库目录,LD_LIBRARY_PATH不包含
    • 2.2.测试2:LIBRARY_PATH不包含库目录,LD_LIBRARY_PATH包含库目录
    • 2.3.测试3:LIBRARY_PATH包含库目录,LD_LIBRARY_PATH包含库目录
    • 2.4.测试4:和LD_LIBRARY_PATH同等作用的/etc/ld.so.conf
      • 2.4.1./etc/ld.so.conf详解
      • 2.4.2./etc/ld.so.conf测试
    • 2.5.测试5:删除环境变量包含目录,使用cmake的find_library命令
    • 2.6.测试6:删除环境变量包含目录,使用cmake的link_directories命令
  • 3.总结
  • 4.问题

1.LIBRARY_PATH和LD_LIBRARY_PATH区别

参考:
LIBRARY_PATH和LD_LIBRARY_PATH的区别
LINUX中PATH,LIBRARY_PATH,LD_LIBRARY_PATH等环境变量的含义
LD_LIBRARY_PATH vs LIBRARY_PATH

1.1.两个环境变量的不同

gcc在编译链接时链接的动态库跟LIBRARY_PATH有关而跟LD_LIBRARY_PATH没关系!

LIBRARY_PATHLD_LIBRARY_PATH是Linux下的两个环境变量,二者的含义和作用分别如下:

  • LIBRARY_PATH环境变量用于在程序编译期间查找动态链接库时指定查找共享库的路径,例如,指定gcc编译需要用到的动态链接库的目录。设置方法如下(其中,LIBDIR1LIBDIR2为两个库目录):
export LIBRARY_PATH=LIBDIR1:LIBDIR2:$LIBRARY_PATH
  • LD_LIBRARY_PATH环境变量用于在程序加载运行期间查找动态链接库时指定除了系统默认路径之外的其他路径。注意,LD_LIBRARY_PATH中指定的路径会在系统默认路径之前进行查找。设置方法如下(其中,LIBDIR1LIBDIR2为两个库目录):
export LD_LIBRARY_PATH=LIBDIR1:LIBDIR2:$LD_LIBRARY_PATH

1.2.使用场景

举个例子,我们开发一个程序,经常会需要使用某个或某些动态链接库,为了保证程序的可移植性,可以先将这些编译好的动态链接库放在自己指定的目录下,然后按照上述方式将这些目录加入到LD_LIBRARY_PATH环境变量中,这样自己的程序就可以动态链接后加载库文件运行了。

区别与使用

  • 开发时(编译程序的时候):设置LIBRARY_PATH,以便gcc能够找到编译时需要的动态链接库,这样可以顺利通过编译链接生成可执行文件。但是注意:如果这个时候这个库不在LD_LIBRARY_PATH目录里,或者不在系统默认的动态库链接目录里,那么程序仍然是不能运行的,因为它运行到时候找不到链接的库,就无法链接这个库。

  • 发布时(程序编译完成,需要运行):设置LD_LIBRARY_PATH,以便程序加载运行时能够自动找到需要的动态链接库。

2.配合CMake实验测试

2.0.文件结构

在文件夹~/test下的目录结构:

2.1.测试1:LIBRARY_PATH包含库目录,LD_LIBRARY_PATH不包含

  • 首先在~/.zshrc中加入环境变量:export LIBRARY_PATH=~/test/Lib:$LIBRARY_PATH。然后重新打开一个窗口,输入printenv | grep LIBRARY查看一下是否加入了环境变量
  • 编写CMakeLists.txt文件如下
cmake_minimum_required(VERSION 3.0)
project(main)add_executable(main main.cpp)
target_link_libraries(main libmyLog.so )
  • cmake … , make测试结果:可以正常编译链接得到可执行文件,但是运行时报错error while loading shared libraries: libmyLog.so: cannot open shared object file: No such file or directory

以上测试说明,LIBRARY_PATH包含库目录但LD_LIBRARY_PATH不包含的情况,可以正常编译链接到库,但是运行的时候链接不到库。

2.2.测试2:LIBRARY_PATH不包含库目录,LD_LIBRARY_PATH包含库目录

测试步骤仍然同上,注意编译之前重开窗口,然后printenv | grep LIBRARY查看一下是否真正满足 “LIBRARY_PATH不包含库目录但LD_LIBRARY_PATH包含库目录” 的要求。

测试结果是编译链接的时候就失败,报错/usr/bin/ld: 找不到 -lmyLog,也就是编译的时候就找不到库目录。

2.3.测试3:LIBRARY_PATH包含库目录,LD_LIBRARY_PATH包含库目录

测试步骤仍然同上,注意编译之前重开窗口,然后printenv | grep LIBRARY查看一下是否真正满足 “LIBRARY_PATH包含库目录且LD_LIBRARY_PATH也包含库目录” 的要求。

测试结果是编译链接通过,程序也可以正常运行。

2.4.测试4:和LD_LIBRARY_PATH同等作用的/etc/ld.so.conf

2.4.1./etc/ld.so.conf详解

参考:/etc/ld.so.conf详解

/etc/ld.so.confLD_LIBRARY_PATH具有同等的作用,都是负责存储程序运行时链接的动态库目录,而不是程序编译时链接的动态库目录。他们不同的地方在于前者是系统目录下的,属于默认路径(超级用户也可以更改);而后者是环境变量,用户可以在其中增加路径。因此程序运行时链接库的时候,优先链接后者,即环境变量LD_LIBRARY_PATH目录下的库。如果不能满足一些共享库相关性要求,则转回到 /etc/ld.so.conf 中指定的库。

首先查看/etc/ld.so*相关的文件如下图所示。

  • ld.so.conf文件和ld.so.conf.d文件夹下的文件是用户使用的。ld.so.conf是文件,它里面默认只有一句话是include /etc/ld.so.conf.d/*.conf。即ld.so.conf.d是一个文件夹,它里面还有很多.conf文件,真正的库包含目录就在这些文件中。然后顶层的ld.so.conf文件包含ld.so.conf.d下的所有文件,也就是统计了这些文件中的库目录。

  • ld.so.cache是真正和链接器打交道的。这个文件中的内容是系统生成的缓存文件,链接器到这个文件中读取链接的库。这个文件需要调用ldconfig命令来生成,或者刷新缓存。

因此,添加把库文件的路径加入到 /etc/ld.so.conf 的方法很简单,有两种方法:

  • 将库文件的绝对路径直接写进 /etc/ld.so.conf ,一行一个,例如:
include /etc/ld.so.conf.d/*.conf   # 系统默认路径
/home/cc/test/Lib  # 用户新增库路劲
  • /etc/ld.so.conf .d文件夹下新建一个自己的.conf文件,在里面写库目录,也是一行一个,例如/etc/ld.so.conf .d/mylib.conf文件内容:
/home/cc/test/Lib  # 用户新增库路劲

如下图可以看到,除了mylib.conf是我们自己新建的,其他都是安装软件的时候或者系统默认就有的。其中有x86_64-linux-gnu.conf,这个就是系统默认库包含目录中有/usr/lib/x86_64_linux-gnu文件夹下的库的根本所在!

库增加结束,调用sudo ldconfig命令更新缓存,当 ldconfig 操作结束时,会有一个最新的 /etc/ld.so.cache 文件,它反映对 /etc/ld.so.conf 所做的更改。从这一刻起,动态装入器在寻找共享库时会查看在 /etc/ld.so.conf 中指定的所有新目录。

最后查看我们增加的库, 要查看 ldconfig 可以“看到”的所有共享库,请输入ldconfig -p | less。这里用管道查找特定的路,输入ldconfig -p | grep libmyLog

2.4.2./etc/ld.so.conf测试

ld.so.conf添加自己的库,LIBRARY_PATH中没有库目录,此时编译链接不通过,报错同2.2。

ld.so.conf不添加自己的库,LIBRARY_PATH中有库目录,此时编译链接通过,但运行链接错误,报错同2.1。

ld.so.conf添加自己的库,LIBRARY_PATH中有库目录,此时编译链接通过,运行链接也无错误。

2.5.测试5:删除环境变量包含目录,使用cmake的find_library命令

CMakeLists.txt文件如下:

cmake_minimum_required(VERSION 3.0)
project(main)find_library(MYLOG libmyLog.so "~/test/Lib")if( MYLOG)   message(STATUS "MYLOG library DIR =  ${MYLOG} ")
else()message(FATAL_ERROR "MYLOG library not found")
endif()add_executable(main main.cpp)
target_link_libraries(main $[MYLOG} )   # 一定注意LOG是变量,所以要用${}引用!

测试步骤仍然同上,注意编译之前重开窗口,然后printenv | grep LIBRARY查看一下是否真正满足 “LIBRARY_PATH不包含库目录且LD_LIBRARY_PATH也不包含库目录” 的要求。

测试结果是编译链接通过,程序也可以正常运行。

2.6.测试6:删除环境变量包含目录,使用cmake的link_directories命令

CMakeLists.txt文件如下:

cmake_minimum_required(VERSION 3.0)
project(main)link_directories("~/test/Lib")
add_executable(main main.cpp)
target_link_libraries(main libmyLog.so )

测试步骤仍然同上,注意编译之前重开窗口,然后printenv | grep LIBRARY查看一下是否真正满足 “LIBRARY_PATH不包含库目录且LD_LIBRARY_PATH也不包含库目录” 的要求。

测试结果是编译链接通过,程序也可以正常运行。

问题:之前一个工程遇到了使用link_directories加入库目录,但是编译链接的时候就是通过不了。最后在target_link_libraries中指定这个库的绝对路径才能编译链接上。很奇怪!

3.总结

如果链接到一个非系统默认或环境变量中的库,该如何写?

使用find_library,这样会编译时链接库的目录和运行时链接库的目录。否则就需要在LIBRARY_PATHLD_LIBRARY_PATH都加入库目录,这样才能保证编译链接成功、运行链接成功。

关于link_directories命令,之前使用遇到奇怪的问题,另外CMake官方也建议不要使用link_directories,而应该使用find_library

4.问题

  1. 既然ld.so.conf里的库等效于LD_LIBRARY_PATH,也就是程序运行时链接的库。那么程序编译时默认链接的库,即等效于LIBRARY_PATH的库路径是在哪里定义的呢?并没有找到!

  2. 关于link_directories命令,之前使用遇到奇怪的问题,另外CMake官方也建议不要使用link_directories,而应该使用find_library

linux环境变量LIBRARY_PATH和LD_LIBRARY_PATH相关推荐

  1. PATH linux环境变量 LD_LIBRARY_PATH详解

    LD_LIBRARY_PATH详解 LD_LIBRARY_PATH是Linux环境变量名,该环境变量主要用于指定查找共享库(动态链接库)时除了默认路径之外的其他路径. 非常多的软件没有root权限安装 ...

  2. linux环境变量 LD_LIBRARY_PATH 使用

    对linux不是很熟,之前只是听说过可以设置程序共享库位置也就是 使用 "export LD_LIBRARY_PATH" 今天用了用,感觉还挺不错,也很常用. 比如你编译了一个so ...

  3. 【Linux】19.Linux环境变量名LD_LIBRARY_PATH 和 ldd命令详解

    Linux环境变量名LD_LIBRARY_PATH 和 ldd命令详解 参考链接: https://www.jianshu.com/p/a62e1d327023 LD_LIBRARY_PATH中的LD ...

  4. linux环境变量设置方法总结(PATH/LD_LIBRARY_PATH)

    linux环境变量设置方法总结(PATH/LD_LIBRARY_PATH) 2012-11-09 11:17:25     我来说两句       作者:wangeen 收藏  我要投稿 linux环 ...

  5. linux+查看系统环境路径,Linux环境变量设置方法总结 PATH、LD_LIBRARY_PATH

    Linux环境变量设置方法总结 PATH.LD_LIBRARY_PATH PATH:  可执行程序的查找路径 查看当前环境变量: echo $PATH 设置: 方法一:export PATH=PATH ...

  6. Linux环境变量详解

    Linux环境变量详解 环境变量是操作系统环境设置的变量,适用于整个系统的用户进程. 环境变量分类 按照权限分类 系统级:系统级的环境变量是每个登录到系统的用户都要读取的系统变量 用户级:用户级的环境 ...

  7. linux环境变量配置的方法,Linux环境变量配置方法

    Linux上环境变量配置分为设置永久变量和临时变量两种.环境变量设置方法同时要考虑环境Shell类型,不同类型的SHELL设置临时变量方法和设置永久变量对应的配置文件不同.Linux环境变量本身配置过 ...

  8. linux 环境变量详解,Linux 环境变量详解及实例

    Linux环境变量 ~/.bash_profile && ~/.bashrc 用户登陆Linux操作系统的时候,"/etc/profile", "~/.b ...

  9. linux怎么设置永久变量,Linux环境变量永久设置方法(zsh)

    1.之前一直使用:export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:./home/46005/cuda-9.0/lib64/来设置cuda库路径变量 -----临时的,当 ...

最新文章

  1. SAP ABAP maintanence view的数据校验机制
  2. 请对比html与css的异同,css2与css3的区别是什么?
  3. 我是一个CPU:这个世界慢!死!了!
  4. 【Redis】Redis Bitmaps
  5. 分享Silverlight/WPF/Windows Phone一周学习导读(4月18日-4月23日)
  6. SIMULATE 受力分析简单教程
  7. java基础习题_JAVA基础练习题
  8. 网页视频播放器代码大全 + 21个为您的网站和博客提供的免费视频播放器
  9. 走进龙芯3A3000(一)安装Loongnix
  10. 流媒体弱网优化之路(FEC+mediasoup)——mediasoup的Nack优化以及FEC引入
  11. Epub 转 txt
  12. 小强统一认证中心-部署实例
  13. 支付宝支付-java-sdk
  14. DINO:自监督ViT的新特性
  15. Win11如何开启移动热点?Win11开启移动热点的方法
  16. usb-OTG-ADP-HNP-SRP
  17. Unhandled JS Exception: Unexpected identifier ‘_classCallCheck‘. import call expects exactly one arg
  18. 第8章 中医证型关联规则挖掘代码调整
  19. 项目风险应对策略总结
  20. v2.error: C:\projects\opencv-python\opencv\modules\imgproc\src\imgwarp.cpp:5594: error: (-215) (M0.t

热门文章

  1. SYSTEM大法好!!!
  2. python绘图 -- 小猪佩奇源码分享
  3. 树莓派安装ubuntu 20.04后配置wifi固定ip地址
  4. 面了一个4年经验的测试工程师,自动化都不会也要15k,我真是醉了...
  5. css超出两行省略号没效果,Css 设置超过再两行显示省略号
  6. ubuntu20下使用微信开发者工具
  7. Possible missing firmware /lib/firmware/rtl_nic/rtl8168fp-3.fw for module r8169
  8. style 标签中动态设置颜色
  9. 雷神加速器无限更新失败️️️
  10. (转载)HCIA-GaussDB 华为认证数据库工程师