CMake库搜索函数居然不搜索LD_LIBRARY_PATH

摘要:本文通过编译后运行找不到库文件的问题引入,首先分析了find_package(JNI)的工作流程,而后针对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)的工作过程是怎样的

为了方便开发者引用外部包,cmake官方预定义了许多寻找依赖包的Module, 他们存储在cmake的/share/-cmake-

打开自己的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可理解的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

Original: https://www.cnblogs.com/huaweiyun/p/16534610.html
Author: 华为云开发者联盟
Title: CMake库搜索函数居然不搜索LD_LIBRARY_PATH

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/548946/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • 【CompletableFuture】CompletableFuture中join()和get()方法的区别

    一.相同点: join()和get()方法都是用来获取CompletableFuture异步之后的返回值 二.区别: 1.join()方法抛出的是uncheck异常(即未经检查的异…

    技术杂谈 2023年6月1日
    091
  • Flink如何处理update数据

    问题 Flink实时统计GMV,如果订单金额下午变了该怎么处理 具体描述 实时统计每天的GMV,但是订单金额是会修改的。 订单存储在mysql,通过binlog解析工具实时同步到k…

    技术杂谈 2023年7月11日
    0111
  • 搭建Rust开发环境

    介绍 Rust是一门系统编程语言,专注于安全,尤其是并发安全,支持函数式和命令式以及泛型等编程范式的多范式语言。 和Ruby,Python等脚本语言程序不同,Rust 是一种预编译…

    技术杂谈 2023年5月31日
    0101
  • 安徽京准:北斗卫星同步时钟|北斗同步时钟|NTP网络时钟服务器

    安徽京准:北斗卫星同步时钟|北斗同步时钟|NTP网络时钟服务器 安徽京准:北斗卫星同步时钟|北斗同步时钟|NTP网络时钟服务器 京准电子科技官微——ahjzsz 安徽京准公司提供了…

    技术杂谈 2023年6月21日
    0118
  • 古传拳经拳法秘要

    《古传拳经拳法秘要》(手抄本) 国术馆 2022-05-05 18:33 更多珍贵拳谱资料 关注公众号”老拳谱” 勿使前辈之遗珍失于我手 点击图片了解与报名…

    技术杂谈 2023年5月31日
    076
  • 进程调度算法

    操作系统有三大调度机制,分别是进程调度、内存页面置换和磁盘调度算法。 进程调度算法 定义 进程调度算法也称 CPU 调度算法,毕竟进程是由 CPU 调度的,当 CPU 空闲时,操作…

    技术杂谈 2023年6月21日
    084
  • mybatis整合springboot 以及需要注意的细节

    具体怎么整合的网上有很多优秀的博客介绍,这里就直接引用一篇个人觉得非常详细的教程: https://blog.csdn.net/winter_chen001/article/det…

    技术杂谈 2023年7月11日
    077
  • 不止面试—jvm类加载面试题详解

    面试题 带着问题学习是最高效的,本次我们将尝试回答以下问题: 什么是类的加载? 哪些情况会触发类的加载? 讲一下JVM加载一个类的过程 什么时候会为变量分配内存? JVM的类加载机…

    技术杂谈 2023年7月11日
    089
  • 树莓派远程连接工具SSH使用教程

    树莓派远程连接工具SSH使用教程 树莓派 背景故事 树莓派作为一款迷你小主机,大部分的使用场景都会用到远程调试,远程调试用到最多的方式一般就是VNC和SSH,SSH就是命令行型的远…

    技术杂谈 2023年7月23日
    088
  • 源码级别的广播与监听实现

    原创:微信公众号 【阿Q说代码】,欢迎分享,转载请保留出处。 近期疫情形势严峻,情形不容乐观,周末也不敢出去浪了,躲在家里”葛优躺”。闲来无事,又翻了遍 S…

    技术杂谈 2023年7月11日
    086
  • 一键搭建博客:如何使用WordPress插件搭建专属博客

    体验简介 阿里云云起实验室提供相关实验资源,点击前往 场景将提供一台基础环境为 CentOS 的 ECS(云服务器)实例,这台服务器上已经内置 LAMP 环境。我们将会在这台服务器…

    技术杂谈 2023年7月11日
    097
  • web性能检测工具lighthouse

    About Automated auditing, performance metrics, and best practices for the web. Lighthouse …

    技术杂谈 2023年5月31日
    0116
  • maven-排查包冲突

    原因:A系统 引用B系统的功能,但是B系统有一个redis需要排除,在已经排除的情况下,还是无效,出现redis存在问题。 解决方法: 需要用到maven查询结构树 去排查 到底j…

    技术杂谈 2023年7月24日
    089
  • SpringMVC学习笔记

    javaSE -> JavaWeb -> SSM(SpringMVC、Spring、MyBatis) -> JavaEE -> SpringBoot、Spr…

    技术杂谈 2023年7月11日
    065
  • unity luaFramework

    1 AppConst: DebugMode: 调试模式,true:lua脚本直接读取自AssetDir,false:开始会将AssetDir内的lua脚本复制到Util.DataP…

    技术杂谈 2023年5月31日
    086
  • Jedis连接池和Jedis连接池工具类

    Jedis连接池对象: @Test public void MyTest06() { //创建配置对象 JedisPoolConfig jedisPoolConfig = new …

    技术杂谈 2023年6月21日
    0114
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球