cmake 常用方法自我总结

目录

1. 编译一个库依赖另一个库

2. 把某一个CMakeLists.txt中变量设为整个工程中任意CMakeLists.txt都可以访问

3. 枚举目录下所有匹配文件

4. 拷贝文件

5. 解决方案下分Header Files,Source Files目录

6. 依赖头文件(附加依赖项)

7. install

8. 生成库、执行文件

9. 生成debug/release版本判读

10. 编译工程命令

11. 设置默认 C++ 标准

12. 工程示例

13. 指定字符集

14. 注意

15. Cmake设置宏,VS中使用

16. 参考


1. 编译一个库依赖另一个库

最近在做C++项目时,当编译A库得时候,A依赖B库,所以要先生成B库,然后把

B库的lib设置到A库中,一旦工程新建,就要把前面操作过程都执行下,挺繁琐。

cmake里面可以通过 “target_link_libraries” 这个方法来设置,如下:

target_link_libraries(pcb debug ${OpenCV_LIBS} common)

pcb库依赖opencv,common库,当我们这样设置的时候,在pcb工程属性中就可以看到自动设置好了依赖,如下图所示:

最关键的是,当我点击生成pcb库的时候,其会先自动生成common.lib库,然后再生成pcb库,也就是说,cmake会自动判断依赖项,并根据依赖项依次生成,非常方便便捷。

生成的库,还依赖别的生成库,或者依赖别的已有库,这时使用 target_link_libraries 命令,这个命令target_link_libraries一定要放到 add_library 或 add_executable 后面,不然会有问题。

2. 把某一个CMakeLists.txt中变量设为整个工程中任意CMakeLists.txt都可以访问

set(NEED_Lib_Path /xxx/xxx/opencv.lib CACHE STRING INTERNAL)

set命令中的 CACHE STRING INTERNAL 这几个参数就是把变量 NEED_Lib_Path 设为全局都可以访问

3. 枚举目录下所有匹配文件

当想把一个文件夹下所有文件都放到一个变量时,可以通过 file 和 set 一起使用,如下:

file(GLOB  NEED_Lib_Dir  xxx/xxx/lib/Release/*.lib)
set(NEED_Lib_Path ${NEED_Lib_Dir } CACHE STRING INTERNAL)

file命令通过GLOB参数,把xxx/xxx/lib/Release目录下所有后缀为 .lib 的文件全部以绝对路径放到变量 NEED_Lib_Dir 中。

接着通过set命令中的 CACHE STRING INTERNAL 这几个参数,把 NEED_Lib_Path 设为了全局,在整个工程中的CMakeLists.txt都可以访问整个参数。

4. 拷贝文件

file(COPY ${Debug_OpenCV_Bin} DESTINATION Debug)

这个命令是把变量 Debug_OpenCV_Bin 拷贝到此工程的 Debug 目录下

5. 解决方案下分Header Files,Source Files目录

为了更好的显示文件,需要对.h和.cpp进行分目录,如下图所示:

通过如下命令:

file(GLOB HEADERS  ${CMAKE_CURRENT_SOURCE_DIR}/include/*.h ${CPP_H_CRYPTOPP_PATH}/*.h)
source_group("Header Files" FILES ${HEADERS})
aux_source_directory(src/ SOURCES)

1.先通过file的GLOB把所有文件放到变量HEADERS中

2.通过 source_group 把 HEADERS 变量中的内容放到 “Header Files” 目录中

3.那 aux_source_directory 这是 cmake 命令自动把 .cpp全部放到 “Source Files” 中,这个不需要我们再创建这个目录

6. 依赖头文件(附加依赖项)

通过如下命令,可以把好多不同路径下include都加到工程里,下面加了4个路径的include到工程中

include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include/ ${COMMON_LIB_PATH} ${DEBUG_NCNN_INCLUDE_PATH} ${DEBUG_CRYPTOPP_INCLUDE_PATH})

7. install

当我们点击install,会自动把需要提供给别人的库和头文件,lib都生成好,且自动输出一个目录下,效果如下图所示:

我当前是需要pcb这个库导出,所以 install 命令是写在 pcb 这个目录下的 CMakeLists.txt 中,命令如下:

set(CMAKE_INSTALL_PREFIX "${CMAKE_BINARY_DIR}/install" CACHE STRING "The path to use for make install" FORCE)
set(PCB_OUT_PUT_INCULDE ${CMAKE_CURRENT_SOURCE_DIR}/include/pcb.h)

install(FILES ${PCB_OUT_PUT_INCULDE} DESTINATION include)
install(TARGETS pcb LIBRARY DESTINATION CMAKE_INSTALL_PREFIX)

1.第一行的 set 以及里面内容是通用的,应该就默认这么写

2.第二行中是设置了PCB_OUT_PUT_INCULDE 为需要导出的 .h 文件

3.第三行通过 install 和 参数 FILES 把 .h 文件导出到 DESTINATION 路径下,这个 DESTINATION 参数也是默认的

4.通过 install 和 参数 TARGETS 把 pcb 的 lib 和 dll 导出到 DESTINATION 路径下。这里会把 pcb.lib 导出到 lib 目录,pcb.dll 导出到 bin 目录。pcb 后面跟的参数 “LIBRARY” 也是默认的

8. 生成库、执行文件

1.生成库

通过如下命令可以生成库,这里的 SHARED 是动态库,即 .dll,也可以改为 STATIC 生成 静态库,即 .lib。后面跟的  ${SOURCES}  ${HEADERS} 是生成pcb库对应的源文件和头文件

add_library(pcb SHARED ${SOURCES} ${HEADERS})

2.生成执行文件,即 .exe

add_executable命令第一个参数是生成的执行文件名,后面是 ${DIR_LIB_SRCS} 源文件,这里依赖的头文件通过命令 include_directories 设置

add_executable(test ${DIR_LIB_SRCS})

9. 生成debug/release版本判读

通过如下命令可以判断生成debug版本,还是release版本

if(CMAKE_CONFIGURATION_TYPES AND (CMAKE_CONFIGURATION_TYPES STREQUAL "Debug"))
	include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include/ ${COMMON_LIB_PATH} ${DEBUG_NCNN_INCLUDE_PATH} ${DEBUG_CRYPTOPP_INCLUDE_PATH})
	target_link_libraries(pcb debug ${OpenCV_LIBS} ${DEBUG_NCNN_LIB_PATH} ${DEBUG_CRYPTOPP_LIB_PATH} common)
else()
	include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include/ ${COMMON_LIB_PATH} ${RELEASE_NCNN_INCLUDE_PATH} ${RELEASE_CRYPTOPP_INCLUDE_PATH})
	target_link_libraries(pcb optimized ${OpenCV_LIBS} ${RELEASE_NCNN_LIB_PATH} ${RELEASE_CRYPTOPP_LIB_PATH} common)
endif()

在生成cmake的时候可以在命令行输入:-D CMAKE_CONFIGURATION_TYPES:STRING=Debug 这样CMakeLists.txt 中就会自动判断是debug,还是release

10. 编译工程命令

cmake ..  -A x64 -D CMAKE_CONFIGURATION_TYPES:STRING=Debug

11. 设置默认 C++ 标准

通过在顶级目录的CMakeLists.txt中设置,就可以达到下图效果

set(CMAKE_CXX_STANDARD 17)

12. 工程示例

1. 下图是我的工程示例,顶级必须设置的是下图右边红色框内容,顶级目录我基本设置一些路径,这样别人只需要修改这个 CMakeLists.txt 就可以了。这里我就把source加到工程中,因为代码都在source文件夹下

2. source目录下的内容如下:

3. 构建好的工程如下图所示:

4. 附一张 test 的 CMakeLists.txt 内容图以及命令

project(test)

set(OpenCV_DIR ${OpenCV_PATH})
#opencv
find_package(OpenCV REQUIRED)
include_directories(${OpenCV_INCLUDE_DIRS})

set(COMMON_INCLUDE ${CMAKE_CURRENT_SOURCE_DIR}/../common/include/)
# this is add C/C++ -> COMMON -> ADD INCLUDE
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include/ ${COMMON_INCLUDE})
# 将当前目录下所有源码文件添加到变量DIR_LIB_SRCS
file(GLOB DIR_LIB_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp)
# 递归
# file(GLOB_RECURSE DIR_LIB_HEADERS  ${CMAKE_CURRENT_SOURCE_DIR}/include/*.h )
file(GLOB DIR_LIB_HEADERS  ${CMAKE_CURRENT_SOURCE_DIR}/include/*.h)
source_group("Header Files" FILES ${DIR_LIB_HEADERS})

message("Debug_OpenCV_Bin: ${Debug_OpenCV_Bin}")

file(COPY ${Debug_OpenCV_Bin} DESTINATION Debug)
file(COPY ${Release_OpenCV_Bin} DESTINATION Release)

file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/../pcb/include/pcb.h DESTINATION ${CMAKE_CURRENT_SOURCE_DIR}/include)

link_directories(${JIANJU_OUT_PUT_INCULDE})

add_executable(test ${DIR_LIB_SRCS})

target_link_libraries(test ${OpenCV_LIBS} pcb)

13. 指定字符集

默认Visual Studio是使用 “使用多字节字符集”, 当某个工程需要使用 “使用 Unicode 字符集”,则在此CMakeLists.txt中加入如下,就可以指定设置 “使用 Unicode 字符集”,如下及下图所示:

add_definitions(-DUNICODE -D_UNICODE)

14. 注意

1. 有时候明明方法对,就是执行不对,比如message也显示不对变量,这个时候需要把之前生成的工程目录下所有文件全部删了,重新生成,这个时候就对了。

2. 生成的库,还依赖别的生成库,或者依赖别的已有库,这时使用 target_link_libraries 命令,这个命令target_link_libraries一定要放到 add_library 或 add_executable 后面,不然会有问题。

15. Cmake设置宏,VS中使用

有时需要通过宏定义来判断是否执行某个方法,这时候可以在cmake中传参数,然后在CMakeLists.txt中判断,并把参数设置到 visual studio 工程中

如下,我需要在 VS 代码中判断是否定义了宏 “SAVEXML”,顶层 CMakeLists.txt 中添加如下代码

if (SAVE STREQUAL XML)
    add_definitions(-DSAVEXML)
endif()

cmake在编译的时候,传入参数:

cmake ..  -A x64 -D CMAKE_CONFIGURATION_TYPES:STRING=Debug -DSAVE=XML

-DSAVE=XML 则为传入 CMakeLists.txt  的参数,接着在 VS 代码中添加如下判断:

#ifdef SAVEXML
	std::cout << "save xml" << std::endl;
#else
	std::cout << "not save xml" << std::endl;
#endif // SAVEXML

效果展示,如下是添加了-DSAVE=XML

如下是没有添加-DSAVE=XML,效果展示:

 

同时在项目属性中也可以看到,有 SAVEXML 宏定义,如下图所示:

 

仔细对比添加和没有添加对VS代码中影响,可以发现,添加了,则 #ifdef SAVEXML 代码高亮,没有添加的则灰色

16. 参考

1. cmake:在 CMake 生成的 VS2015 工程中保持源码文件的目录组织_cmake source_group_OceanStar的学习笔记的博客-CSDN博客

2.CMake定义宏的方式_cmake 宏定义_风闲1217的博客-CSDN博客

3.CMake通过外部传参执行不同逻辑的方案比如瑞芯微(1126)地平线(horizon)-CSDN博客

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

通过阿里云函数计算解决ChatGPT API的调用问题

ChatGPT系列文章 与其被ChatGPT取代&#xff0c;不如征服ChatGPT&#xff0c;做它的主人&#xff01; 文章目录ChatGPT系列文章前言命令行部署准备工作两行命令实现部署应用中心部署使用代理访问API总结前言 自2022年11月30日 OpenAI 发布 ChatGPT 以来&#xff0c;虽然时有唱…

算法训练第四十九天 | 121.买卖股票的最佳时机、122.买卖股票的最佳时机II

动态规划part10121.买卖股票的最佳时机题目描述思路暴力贪心动态规划122.买卖股票的最佳时机II题目描述思路121.买卖股票的最佳时机 题目链接&#xff1a;121.买卖股票的最佳时机 参考&#xff1a;https://programmercarl.com/0121.%E4%B9%B0%E5%8D%96%E8%82%A1%E7%A5%A8%E7%9…

entos7系统部署网站项目教程【超详细教程】

CentOS 7 系统部署项目教程 本文将介绍如何在 CentOS 7 系统上部署项目。在本教程中&#xff0c;我们将使用 Apache、PHP 和 MySQL 作为我们的主要开发工具。对于初学者来说&#xff0c;这是一个入门级的教程&#xff0c;旨在提供一些基本的概念和工具&#xff0c;以帮助您更好…

实践分享:如何在自己的App 中引入AI 画图

最近AIGC 简直是杀疯了&#xff0c;领导动不动就让我们在APP 里引入大语言模型&#xff0c;引入AI画图……说搞就搞&#xff01;本期基于最近在app 里引入AI画图小程序的操作&#xff0c;给大家做一波实践分享。 Scribble Diffusion 是一个简单的在线服务&#xff0c;它使用 A…

Kotlin 面向对象(二)

【文字内容源于《疯狂Kotlin讲义》&#xff0c;代码内容原创】 Kotlin 面向对象&#xff08;一&#xff09;_桃子不出的博客-CSDN博客 目录 四、隐藏和封装 1、包和导包 2、Kotlin的默认导入 3、使用访问控制符 五、深入构造器 1、主构造器和初始化块 2、次构造器和构…

Redis —缓存常见异常

文章目录缓存雪崩解决办法缓存击穿解决办法缓存穿透缓存穿透的两种常见情况解决办法布隆过滤器工作原理缓存雪崩 大量缓存数据在同一时间过期&#xff08;失效&#xff09;或者 Redis 故障宕机时&#xff0c;如果此时有大量的用户请求&#xff0c;都无法在 Redis 中处理&#…

父子组件传值问题

文章目录前言一、问题描述二、问题解决前言 在写毕业设计&#xff0c;涉及了一些前端Vue.js的组件传值知识并出现了相关问题&#xff0c;因此进行记录。 问题 Vue.js的使用不熟练&#xff0c;相关组件、props等掌握不清晰前端代码书写不规范 望指正&#xff01; 一、问题描述 …

php企业公司员工考勤加班系统

1、系统管理员 负责员工的基本信息管理&#xff08;包括姓名、工号、所在部门信息的添加、修改和删除&#xff09;和员工的上下班时间的添加。 公司考勤记录方式为刷上下班卡&#xff0c;卡机自动记录员工上下班时间。我直接跳过这一步&#xff0c;系统管理员每天在员工下班后直…

面试被问到:测试计划和测试方案有什么区别?

面试的时候&#xff0c;很多小伙伴都被面试官问过这个问题 “测试计划和测试方案有什么区别”&#xff1f; 到底有什么区别呢&#xff1f;我们先好好了解下这两个文档。 一、测试计划 1、测试计划是什么&#xff1f; 测试计划是组织管理层面的文件&#xff0c;从组织管理的…

派盘为您的个人数据安家

现如今,我们的生活中有着各种各样的数据。在工作中会有各种文件、邮件;在生活中则有照片和视频等。数据的来源多,时间点不一致且混乱。 数据是否能安全、稳定、长久的存储以及便捷高效的使用对我们来说相当重要。你是否经常出差需要带上电脑或者移动硬盘,想存网盘又怕丢失或…

一篇文章,弄懂蓝牙协议怎么看,进军物联网!

做过物联网相关项目的小伙伴都知道&#xff0c;避免不了和蓝牙&#xff0c;串口通信打交道。所以了解怎么看蓝牙协议基本上可以说是进军物联网的一大助力。很多新人小伙伴刚进入这个行业都是一脸懵逼的&#xff0c;特别是接入的时候&#xff0c;对方直接给了一个文档&#xff0…

【WCH】基于Keil环境CH32F203 GPIO点灯实验

【WCH】基于Keil环境CH32F203 GPIO点灯实验&#x1f4cc;相关篇《关于CH32F203程序下载方式说明》 ✨如果是首次入门使用&#xff0c;请先看上面的相关篇内容&#xff0c;了解其下载相关事宜后&#xff0c;再进来学习。 GPIO模式介绍 &#x1f33f;在应用手册的第十章介绍GPIO…

1mm³大小,世界首个功率破KW的单芯片激光模组诞生

近年来随着技术不断发展&#xff0c;激光雷达的体积、成本也在不断降低&#xff0c;成为了一种受到各行业关注的关键技术。它的用途越发广泛&#xff0c;可用于自动驾驶汽车、大气观测使用的LiDAR传感器&#xff0c;还可以用于医疗保健&#xff08;治疗和检查分析&#xff09;、…

给boss直聘的搜索结果加上hr活跃状态,少看点半年活跃的岗位

背景&#xff1a;这段时间找工作&#xff0c;无奈大环境不好&#xff0c;所在城市大部分公司都投了。就是没几个回复的&#xff0c;要么送达&#xff0c;要么已读不回&#xff0c;要么拿了简历没见邀约。然后boss为了争取我们多浏览网站&#xff0c;把一些陈年老醋也拿上台面&a…

阿里巴巴春招的后端面经来啦~

操作系统 一个操作系统&#xff0c;我们在衡量它的内存占用的时候&#xff0c;它一般会有哪些内存的部分&#xff1f; 读者答&#xff1a;堆和栈 补充&#xff1a; 这个其实是问你对free命令的理解。 主机的内存做一些清理的动作。你知道这里面会涉及到对哪些内存区域进行操…

yolov5-v7.0实例分割快速体验

简介 &#x1f680;yolov5-v7.0版本正式发布&#xff0c;本次更新的v7.0则是全面的大版本升级&#xff0c;最主要的功能就是全面集成支持了实例分割&#xff0c;yolov5已经集成检测、分类、分割任务。 前面几篇文章已经介绍过关于Yolov5的一些方面 yolov5目标检测:https://bl…

CIE (PCI Express) 1x, 4x, 8x, 16x总线端子说明

1、概述 PCI Express作为一种高带宽、低引脚数、串行、互连技术。它是为了取代旧的PCI和AGBus标准而设计的。PCIe比旧标准有许多改进&#xff0c;包括更高的最大系统总线吞吐量、更低的I/O引脚数和更小的物理占地面积、更好的总线设备性能扩展、更详细的错误检测和报告机制&am…

4.7--计算机网络之TCP篇之socket编程--(复习+深入)---好好沉淀,加油呀

1.针对 TCP 应该如何 Socket 编程&#xff1f; 1.服务端和客户端初始化 socket&#xff0c;得到文件描述符&#xff1b; 2.服务端调用 bind&#xff0c;将 socket 绑定在指定的 IP 地址和端口; 3.服务端调用 listen&#xff0c;进行监听&#xff1b; 4.服务端调用 accept&#…

版本控制工具Git的常见命令与使用方法

目录概述基础命令提交代码把代码提交到暂存区把代码提交到版本库同一笔提交想追加修改回退代码对代码进行了修改&#xff0c;想回退工作区的修改执行了add操作&#xff0c;想回退到工作区执行了commit操作&#xff0c;想撤销修改执行了commit操作&#xff0c;想回退到暂存区挑代…

二、Java 并发编程(1)

本章概要 常见的 Java 线程创建方式 继承 Thread 类实现 Runnable 接口通过 ExecutorService 和 Callable 接口实现有返回值的线程基于线程池 Java 线程池的原理 线程复用线程池的核心组件和核心类Java 线程池的工作流程线程池的拒绝策略 相对于传统的单线程&#xff0c;多线…
最新文章