linux环境变量LIBRARY_PATH和LD_LIBRARY_PATH-程序员宅基地

技术标签: Linux工具操作笔记  linux  

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

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq_42731705/article/details/123937127

智能推荐

大数据Hadoop之——任务调度器Azkaban(Azkaban环境部署)_azkaban任务调度-程序员宅基地

文章浏览阅读7.6k次,点赞7次,收藏54次。文章目录一、概述1)什么是任务调度?2)常见任务调度工具3)什么是Azkaban二、Azkaban 与 Oozie 对比三、Azkaban 运行模式及架构1)Azkaban Web Server2)Azkaban Executor Server3)关系型元数据库(MySQL)四、Azkaban安装部署1)solo server mode安装1、下载2、构建Azkaban安装包3、把编译好的包copy到其它目录3、启动服务4、web访问验证5、配置https并重启服务2)multiple executor m_azkaban任务调度

安卓TextView中改变部分文字颜色的几种方式_android textview 部分文字加颜色-程序员宅基地

文章浏览阅读1w次,点赞7次,收藏12次。安卓TextView中改变部分文字颜色_android textview 部分文字加颜色

如何批量OCR识别各类票据关键信息,导出为结构化格式数据_铭牌有结构的ocr字符提取-程序员宅基地

文章浏览阅读1.7k次。扫描工厂在处理大量银行票据,合同、工程图纸过程中。现在的OCR识别全部的文字,这样不但产生大量的无用数据,而且速度慢效率底。如何批量识别票据的有效机构化数据供其他系统使用,或者生成JSON数据、文本数据,可以搜索的双层PDF是用户关注的问题。现在给大家推荐一款免费的模板OCR识别软件,用户可以自己定义编辑模板,用鼠标选出有效的数据区间。模板操作完全使用鼠标,简单拖拽缩放,非常方便。然后批量导入同样格式的图片、PDF文件、或者批量扫描票据,套用模板,批量识别有效数据。软件识别的结果都可以二_铭牌有结构的ocr字符提取

web 打印,web打印控件的三种实现方法 _web 端 打印回调-程序员宅基地

文章浏览阅读3.2k次。http://www.blogjava.net/midstr/archive/2010/06/18/256597.html?opt=adminweb 打印,web打印控件的三种实现方法 zz做管理系统的时候,打印一直是个棘手的问题,做B/S的系统这个问题就更加突出了!下面举出三种常用的web打印处理方式1、利用word或者excel来实现web打印(如果不修改ie设置,可以在web服务器端生成xls文件,然后通过xlBook = xls.Workbooks.Open(remotePa_web 端 打印回调

mininet安装过程(ubantu、git、mininet源码安装)以及POX安装_安装mininet有几种方法-程序员宅基地

文章浏览阅读2k次。小白一只,由于毕设题目跟SDN有关,就开始踢软件定义网络的大门,当然第一步就是熟悉网络工具,从mininet开始。对于从没接触过mininet、Linux的人来说,安装过程还是挺艰难的,我在安装过程中参考了一些很好的博客,在此做一个总结。 本人是在虚拟机VirtualBox中安装ubuntu-16.04.6-desktop-amd64.iso,然后在ubantu系统中..._安装mininet有几种方法

C# 入门教程Subject发布和订阅_iobserver-程序员宅基地

文章浏览阅读1.6k次。Reactive Extensions for .Net 为开发人员提供了一组功能,用于为 .Net 开发人员实现反应式编程模型,使用声明性操作使事件处理更简单、更具表现力。虽然反应式扩展的关键基石是 IObserver 和 IObservable 接口,但作为开发人员,您通常不需要自己实现这些接口。该库支持内置类型Subject<T>,它实现了两个接口并支持许多功能。主题是库中不同可用主题的基础,还有其他主题 -ReplaySubject<T>、BehaviorSubje..._iobserver

随便推点

短信验证码服务_验证码通过服务-程序员宅基地

文章浏览阅读360次,点赞10次,收藏8次。如果嫌麻烦,可以把短信验证码功能关掉(sms.enable=false),此时会开启密码登录模式(登录密码就是验证码),直接使用手机号作为验证码即可登录,因为在注册功能中,默认会把手机号作为登录密码保存到数据库中。访问路径:http://localhost:56085/sailing / verify?​ 由于统一账户服务(wanxinp2p-account-service)需要使用短信验证码功能,因此需要使用sailing服务,接入很方便,只需在Apollo上进行相关配置即可。_验证码通过服务

不能用了 重装系统git_重装系统后Git恢复-程序员宅基地

文章浏览阅读877次。解决问题的操作步骤设置git:设置git的user name和email:git config --global user.name "xxx"git config --global user.email "[email protected]"生成密钥:ssh-keygen -t rsa -C "[email protected]"按3个回车,密码为空这里一般不使用密钥。最后得到了两个文件:id_rsa和id_rsa.p..._系统重置后git和小乌龟怎么恢复、

详细介绍AUTOSAR各个模块作用PART3(CRYPTO)_mcal crypto-程序员宅基地

文章浏览阅读4.8k次,点赞6次,收藏38次。12、CSM_mcal crypto

[说明] 关于我,以及联系方式_作者: ryu邮箱-程序员宅基地

文章浏览阅读9.2k次,点赞10次,收藏8次。写在前面:鉴于评论、私信等方式很难有时间查看,因此提供我的邮箱:[email protected]。1. 关于我:教育经历:2018年本科毕业于某985,推免至中科院某所,目前研二在读(2018-2021)。专业:计算机科学与技术(计算机应用技术)研究兴趣:Computer Graphics、Machine Learning、Computer Vision主力编程语言:C,......_作者: ryu邮箱

【LAMMPS系列】MD模拟数据后处理程序ISAACS_lammps计算聚合物自由体积-程序员宅基地

文章浏览阅读2.6k次。大家好,我是粥粥。分子动力模拟再好,没有方便的数据分析,就画不出有用又漂亮的图。对于MD模拟数据后处理,LAMMPS内的compute command可以进行简单的RDF、配位数、ADF和MSD等的计算,更多的分析可以借助别人造好的轮子(开源程序)进行计算,对于个性化的分析就要自己去编程了。此系列收集整理后处理程序的用途,以备不时之需。ISAACS可对由LAMMPS模拟得出的分子构型(data文件或轨迹文件)进行后处理分析的程序,包括径向分布函数、原子配位数、模型自由体积和密度、键角分布、环统计量、球面谐波_lammps计算聚合物自由体积

求PI的近似值(近似算法)-程序员宅基地

文章浏览阅读4.9k次,点赞2次,收藏8次。题目求PI的近似值 (30 分)用正多边形逼近法求π的近似值。 用圆内接正多边形的边长和半径之间的关系,不断将边数翻倍并求出边长,重复这一过程,正多边形的边长就逐渐逼近圆的周长,只要圆内接正多边形的边数足够多,就可以求得所需精度的π值。 从正六边形开始。简单起见,设单位圆的半径是1,则单位圆的圆周长是2×π,设单位圆内接正i边形的边长为2b,边数加倍后正2i边形的边长为x,则:输入格式:输入1-10的数k(圆正接多边形边数n=6*2^(k-1))输出格式:圆内接正多边形的边数n和PI值,PI的_求pi的近似值

推荐文章

热门文章

相关标签