当前位置: 首页 > article >正文

CMake 自己写 findmodule

cmake 写 findmodule

用过 CMake 的同学应该都知道,cmake 使用 find_package() 命令查找第三方的库。find_package 实际上又是调用了一个 cmake 的脚本文件来获取库的实际信息的。比如我们要查找一个库,名字叫 。那么 find_package 是去找两种文件:

  1. Find<name>.cmake 这个文件通常是 CMake 自带的。一般在 CMake 安装目录的 Modules 子目录中。
  2. <name>Config.cmake 这个文件通常是第三方库自己带的。

如果我们使用的第三方的库没有提供<name>Config.cmake,cmake 也没提供 Find<name>.cmake ,这时我们应该怎么办呢?

比较原始的方法就是自己在 CMakeLists.txt使用 find_path() 来查找头文件的位置。用 find_library() 来查找库文件。这个说起来简单,但是如果考虑到编译目标有 x86 和 x64,还要区分 debug 和 release。把这些全都考虑清楚还是要写不少的代码的。如果每个项目都写一遍工作量还是蛮大的。所以更好的方法是写一个 findmodule 文件。以后每次都用这个文件。

下面是练手时写的一个例子,参考了 AI 给出的代码。第三方库是 海康机器人的 MVS。 MVS 是海康机器人为他们自己的工业相机配套的测试程序,同时也带有海康工业相机和图像采集卡的 SDK。这个 SDK 海康没有专门的命令,我们就姑且也叫它为 MVS 吧。 MVS 中其实是提供了两套独立的 SDK 的,一套对应他们的工业相机,我们称之为 MVS_CC,这里 CC表示Camera Control),另一套称之为 MVS_FG,其中 FG 表示 FrameGrabber。

我们的代码分为两个部分,首先先去找 MVS 的安装位置:

# 查找海康 MVS 的 SDK, MVS_CC 是相机的 SDK, MVS_FG 是采集卡的 SDK
# 用户可以设置环境变量 HIK_MVS_ROOT 为 MVS 的安装路径 

# 如果成功找到 MVS, 则会设置如下的变量
# 1. MVS_CC_INCLUDE_DIRS 
# 2. MVS_FG_INCLUDE_DIRS
# 3. MVS_CC_LIBRARIES 
# 4. MVS_FG_LIBRARIES
# 5. MVS_FOUND

# MVS_ROOT 是 MVS 的安装路径
if(NOT MVS_ROOT)
    set(MVS_ROOT "$ENV{HIK_MVS_ROOT}") # 先看有没有对应的环境变量,有的话直接用环境变量的值
endif()

if(NOT MVS_ROOT) # 如果没找到环境变量,则在一些特定路径下查找
    find_path(_MVS_ROOT 
                NAMES Development/Includes/MvCameraControl.h
                HINTS "C:/Program Files (x86)/MVS" 
                "D:/Program Files (x86)/MVS" 
                "E:/Program Files (x86)/MVS" )
else()
    set(_MVS_ROOT "${MVS_ROOT}")
endif()

以上代码很简单,MVS 安装路径有三个途径来获取:

  1. cmake -DMVS_ROOT=“path” 利用 -D 来告诉 cmake MVS 的地址。
  2. 设置环境变量 HIK_MVS_ROOT
  3. 如果上面两个都没做,那么就在一些标准位置去查找

上面执行之后,MVS的安装路径就存在 _MVS_ROOT 变量中了。

然后就是查找 头文件和 库文件。头文件和库文件的位置相对 MVS 的安装位置是固定的。但是库文件有两套,分别是 win32 和 win64 的。对于其他一些库,可能还要区分 debug 和 release。那么搭配起来就有 4 个不同的库文件。有多少种都没有关系,我们分别把他们都找到,然后放到合适的变量中。

find_path(MVS_CC_INCLUDE_DIRS 
            NAMES 
                MvCameraControl.h 
            HINTS 
                ${_MVS_ROOT}/Development/Includes
            )

find_path(MVS_FG_INCLUDE_DIRS 
            NAMES 
                MVFGControl.h 
            HINTS 
                ${_MVS_ROOT}/Development/MVFG/Includes
            )


find_library(MVS_CC_LIBRARIES_win32
            NAMES
                MvCameraControl.lib
            PATHS
                "${_MVS_ROOT}/Development/Libraries/win32/"
            )

find_library(MVS_CC_LIBRARIES_win64
            NAMES
                MvCameraControl.lib
            PATHS
                "${_MVS_ROOT}/Development/Libraries/win64/"
            )

find_library(MVS_FG_LIBRARIES_win32
            NAMES
                MVFGControl.lib
            PATHS
                "${_MVS_ROOT}/Development/MVFG/Libraries/win32/"
            )

find_library(MVS_FG_LIBRARIES_win64
            NAMES
                MVFGControl.lib
            PATHS
                "${_MVS_ROOT}/Development/MVFG/Libraries/win64/"
            )            

上面的代码很直白,就不过多解释了。下面到了重点内容。我们需要知道当前配置编译出的代码时 x86还是 x64 的,这样我们才能知道我们链接时该链接到哪个库。cmake 的标准做法是检测 CMAKE_SIZEOF_VOID_P 的值,如果这个指针是 8 bytes,难么编译出的代码就是 x64 的。

if(CMAKE_SIZEOF_VOID_P EQUAL 8)
    set(MVS_FG_LIBRARIES ${MVS_FG_LIBRARIES_win64})
    set(MVS_CC_LIBRARIES ${MVS_CC_LIBRARIES_win64})
    message(STATUS "Target is 64 bits")
else()
    set(MVS_FG_LIBRARIES ${MVS_FG_LIBRARIES_win32})
    set(MVS_CC_LIBRARIES ${MVS_CC_LIBRARIES_win32})
    message(STATUS "Target is 32 bits")
endif()

MVS 没有提供 debug 版的库,但是我们还是要讲讲该如何区分 debug 和 release。

if(CMAKE_BUILD_TYPE STREQUAL "Debug")
	set(...)
	message(STATUS "Target is in debug mode")
else()
	set(...)
	message(STATUS "Target is in release mode")
endif()

最后再设置一下 MVS_FOUND 变量就大功告成了。

find_package_handle_standard_args(MVS
    FOUND_VAR
        MVS_FOUND
    REQUIRED_VARS
        MVS_CC_INCLUDE_DIRS
        MVS_FG_INCLUDE_DIRS
        MVS_CC_LIBRARIES
        MVS_FG_LIBRARIES
        )

http://www.kler.cn/a/612804.html

相关文章:

  • 阿里云国际站代理商:如何通过并行文件系统提升IO性能?
  • 【安全运营】关于攻击面管理相关概念的梳理(二)
  • 论文发表科普知识:什么是南核、北核、CSCD、科技核心、AMI人文核心期刊?
  • JDK 17 + Spring Boot 3 全栈升级实战指南--从语法革新到云原生,解锁企业级开发新范式
  • 笔试专题(四)
  • C++代码脚本实现STM32启动
  • 基于springboot+vue的游戏账号交易系统的设计与实现
  • Android 开发 Gradle 相关问题
  • IIS (Internet Information Services) 基本配置指南
  • 计算机二级WPS Office第四套电子表格
  • 快速排序不啦不啦
  • 工作记录 2017-03-10
  • Success is the sum of small efforts repeated day in and day out.
  • VLAN 聚合
  • skynet.socket.limit 使用详解
  • Ubuntu里安装Jenkins
  • 整理和记录前端常见问题
  • 科技快讯 | 谷歌发布新一代推理模型;我国成功发射天链二号04星;Manus:将举行线下活动 正努力让更多人用上Manus
  • 如何查看 SQL Server 的兼容性级别
  • MySQL 表连接(内连接与外连接)