当前位置:网站首页>CMake库搜索函数居然不搜索LD_LIBRARY_PATH
CMake库搜索函数居然不搜索LD_LIBRARY_PATH
2022-07-30 11:48:00 【51CTO】
摘要: 本文通过编译后运行找不到库文件的问题引入,首先分析了find_package(JNI)的工作流程,而后针对cmake不搜索LD_LIBRARY_PATH的问题,提出了一种通用的解决办法。
本文分享自华为云社区《 CMake库搜索函数居然不搜索LD_LIBRARY_PATH? 由编译工具使用体验而引发的思考》,作者: 蜉蝣与海 。
最近产品要使用JNI技术,CMake编译C++代码时需要对外链接libjvm.so库。代码编译倒是正常,系统中也有libjvm.so, 然而使用时却报了如下异常:
这个报错表示,操作系统并没有找到libjvm.so, 我们的操作系统是从LD_LIBRARY_PATH中搜索这些动态链接库,很显然目前libjvm.so并不在这个目录下。
问题的解决倒是简单,直接在LD_LIBRARY_PATH里加入libjvm.so的库即可。但是这却引发了我的思考:
为什么构建时可以找到libjvm.so, 运行时却找不到呢?
这个问题的回答,既可以有简明扼要版解释,又可以刨根问底深挖。
先来看简明扼要版解释:
代码的CMakeList中使用了下列语句,在编译过程中寻找并链接libjvm.so,这个搜索方式和操作系统的搜索方式不同:
其中find_package(JNI)会搜索libjvm.so可能存在的路径,通过get_filename_component来获得libjvm.so的文件夹,并把这个文件夹设为默认搜索库路径。而后set_target_properties会进行链接工作。
这个答案只能告诉我们“是什么”,但是作为一只程序猿,还要了解“为什么”,这里引申几个问题讨论:
- find_package(JNI)的工作过程是怎样的?为什么LD_LIBRARY_PATH里没找到的依赖库,cmake可以找到
- cmake的库搜索函数find_library会搜索LD_LIBRARY_PATH吗,如果不会,可以通过设置来搜索LD_LIBRARY_PATH吗?
问题一:find_package(JNI)的工作过程是怎样的
为了方便开发者引用外部包,cmake官方预定义了许多寻找依赖包的Module, 他们存储在cmake的/share/-cmake-<version>/Modules目录下。每个以Find<LibraryName>.cmake命名的文件都可以帮我们找到一个包[1]。在本地计算机执行以下指令,即可找到find_package(JNI)使用的脚本文件。
打开自己的cmake对应的FindJNI文件,可以看到密密麻麻的注释和脚本,通过阅读这些脚本,我们得以得知FindJNI是如何工作的。
分析问题前,先看问题带来的结果,文件最上方注释有如下说明:
这段代码表明,执行find_package(JNI)之后,会有一系列变量被设置,其中包括表示JNI是否被找到的变量JNI_FOUND,以及表示libjvm.so的变量JAVA_JVM_LIBRARY。这些变量在设定之后,通过FindPackageHandleStandardArgs导出,返回调用处,FindPackageHandleStandardArgs是cmake专门用来导出变量的宏[2]:
在文件中定位JAVA_JVM_LIBRARY, 可以追踪到下述代码片段:
由此可知,JAVA_JVM_LIBRARY这个变量,是通过逐个搜索${_JNI_${search}_JVM}里的文件夹进而确定JAVA_JVM_LIBRARY的。而${_JNI_${search}_JVM}相关的定义语句如图:
其中JAVA_JVM_LIBRARY_DIRECTORIES中涉及了大量可能的libjvm.so存在的路径。
如上图所示,变量依赖顺序如下:
JAVA_JVM_LIBRARY_DIRECTORIES => JAVA_AWT_LIBRARY_DIRECTORIES => _JNI_JAVA_AWT_LIBRARY_TRIES & _JAVA_HOME => _JNI_JAVA_DIRECTORIES_BASE
最终发现JAVA_JVM_LIBRARY_DIRECTORIES变量的值,是由JAVA_HOME变量的值和_JNI_JAVA_DIRECTORIES_BASE变量的值共同决定的。而JNI_JAVA_DIRECTORY_BASE预置了大量预定义路径:
通过以上分析可以看出,JAVA_JVM_LIBRARY的搜索,依赖JAVA_HOME和大量预定义路径。
问题二:cmake库搜索函数find_library会搜索LD_LIBRARY_PATH吗
通过阅读Does CMake's find_library search LD_LIBRARY_PATH可以知道,find_library默认不搜索LD_LIBRARY_PATH, 并且网上也找不到让cmake搜索LD_LIBRARY_PATH的文章。
那cmake能搜索LD_LIBRARY_PATH吗?
答案是可以的,通过cmake获取LD_LIBRARY_PATH环境变量,并转为cmake可理解的list格式,而后注入find_library即可,代码如下:
如果希望找不到这个库时编译失败,可以将WARNING改为fatal_error, 代码如下:
小结
本文通过编译后运行找不到库文件的问题引入,首先分析了find_package(JNI)的工作流程,而后针对cmake不搜索LD_LIBRARY_PATH的问题,提出了一种通用的解决办法。
参考文献:
[1] Cmake之深入理解find_package()的用法:https://zhuanlan.zhihu.com/p/97369704?utm_source=wechat_session
[2] Cmake中find_package命令的搜索模式之模块模式(Module mode):https://www.jianshu.com/p/f983a90bcf91
[3]Does CMake's find_library search LD_LIBRARY_PATH?:https://stackoverflow.com/questions/41566316/does-cmakes-find-library-search-ld-library-path
边栏推荐
- 概率论的学习整理2:如何对随机实验的对象:“事件” 进行计数呢? 四种计数方法,不只是排列组合
- PanGu-Coder: 函数级的代码生成模型
- HJY-F931A/YJ three-phase voltage relay
- 听到'演员工作比工人辛苦,吃得也不如工人好?'我笑了
- 自定义查询--关于倒排索引的研究
- 嵌入式环境下并发控制与线程安全
- mapbox-gl开发教程(十四):画圆技巧
- 概率论的学习和整理--番外4: 关于各种平均数:算术平均数,几何平均数,调和平均数,以及加权平均数和平方平均数 (未完成)
- LeetCode_236_二叉树的最近公共祖先
- Summary of text alignment, line height, space, etc.
猜你喜欢
概率论的学习整理--番外2:和二项式,组合相关的杨辉三角
LinkedList与链表
亚洲高校首现KDD博士论文奖:清华裘捷中获Runner Up奖,WINNER奖也是位华人
Apifox 生成接口文档 教程与操作步骤
Performance testing of API Gateway APISIX on Google Cloud T2A and T2D
概率论的学习整理3: 概率的相关概念
contentDocument contentWindow, canvas, svg, iframe
超图iServer rest服务之最佳路径分析
概率论的学习和整理7:理解期望和方差还是要回到随机试验本身,期望不是平均值,方差的公式不同情况不同
Explain the problem of change exchange in simple terms - the shell of the backpack problem
随机推荐
Based on the analysis of the acoustic channel cable tunnel positioning technology
明德扬FPGA开发板XILINX-K7核心板Kintex7 XC7K325 410T工业级
Redis master-slave replication
24. 两两交换链表中的节点
2022-07-29 顾宇佳 学习笔记 异常处理
mapbox-gl开发教程(十四):画圆技巧
AlphaFold预测了几乎所有已知蛋白质!涵盖100万物种2.14亿结构,数据集开放免费用...
听到'演员工作比工人辛苦,吃得也不如工人好?'我笑了
Interviewer: Redis bloom filter and the cuckoo in the filter, how much do you know?
【MySQL系列】-B+树索引和HASH索引有什么区别
Matlab基础(4)——矩阵
Verilog grammar basics HDL Bits training 07
saltstack学习2grains&pillar
Typroa alternative tool marktext
数字量输入输出模块DAM-5088
LeetCode_235_Last Common Ancestor of Binary Search Tree
UE5 GAS Study Notes Postscript 0
亚洲高校首现KDD博士论文奖:清华裘捷中获Runner Up奖,WINNER奖也是位华人
LeetCode_235_二叉搜索树的最近公共祖先
基于加权灰色关联投影的Bagging-Blending多模型融合短期电力负荷预测