CMake基本用法与项目编译

1.简介
1.1 CMake编译项目主要是 通过编写CMakeList.txt文件项目的每个子文件夹下分别编写CMakeList.txt,通过CMake工具来根据CMakeList文件生成makefile,最后编译成可执行文件。

1.2 通过CMake可以编译不同版本的vs项目,方便在不同版本的vs之间进行项目的转移,CMake也可以在不同的平台编译项目。

2.基本语法

2.1 指定cmake的最小版本

cmake_minimum_required(VERSION 版本号)

2.2 设置项目的名称

project(项目名称)
//指定项目版本号
project(项目名称 VERSION 版本号)//配置一个头文件,将版本号传递给源代码
configure_file(xx.h.in xx.h)//xx.h.in 在源目录中创建一下内容,当 CMake 配置这个头文件时,@xx_VERSION_MAJOR@的值和 @xx_VERSION_MINOR@将被替换。
#define xx_VERSION_MAJOR @xx_VERSION_MAJOR@
#define xx_VERSION_MINOR @xx_VERSION_MINOR@//在项目中包含上述xx.h配置头文件;

2.3 添加可执行程序

add_executable(可执行程序名称,可执行程序.cpp文件)

2.4 指定C++的标准:通过CMAKE_CXX_STANDARD 和 CMAKE_CXX_STANDARD_REQUIRED来指定;

set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED True)

2.5 在源代码的根目录下创建一个build文件夹,将编译的信息全部保存到bulid中,这样方便我们对源码的管理以及二次编译;

2.6 添加编译生成的动态链接库,将动态链接库源文件放在子目录Child下,Child下包含库的头文件childxx.h和childxx.cpp文件。

//添加子文件夹
add_subdirectory(Child)//连接库文件
target_link_libraries(项目名称 PUBLIC Child)//添加包含目录,以便找到库的头文件
target_include_directories(项目名称 PUBLIC "${PROJECT_BINARY_DIR}" "${PROJECT_SOURCE_DIR}/Child")

2.7 设置某个库位可选库,在编译大型项目中很常见,在cmake-gui中可以选择性的编译某些库。

option(USE_CHILD "使用Child库" ON)

2.8 设置可选项后,添加库的构建和连接条件。

//USE_CHILD是一个用户定义的变量,使用EXTRA_LIBS变量收集任何可选库,以便链接,EXTRA_INCLUDES 变量用于可选的头文件
if(USE_CHILD)add_subdirectory(Child)list(APPEND EXTRA_LIBS Child)list(APPEND EXTRA_INCLUDES "${PROJECT_SOURCE_DIR}/Child")
endif()

对源码的更改,在需要使用库的xx.cpp中,添加如下代码:

#ifdef USE_CHILD
#  include "childxx.h"
#endif

对引用系统库函数还是自定义库中的的函数,在源码中可以采用如下方式指定。

//指定使用自定义的sqrt函数,还是库sqrt函数
#ifdef USE_CHILDconst double output = sqrt(input);
#elseconst double output = sqrt(input);
#endif

由于源码中需要使用USE_CHILD,因此需要在配置头文件xx.h.in文件中添加。

#cmakedefine USE_CHILD

2.9 库的使用要求
主要命令

  • target_compile_definitions()
  • target_compile_options()
  • target_include_directories()
  • target_link_libraries()

在Child子目录下的CMakeList.txt中添加

target_include_directories(CHILD INTERFACE ${CMAKE_CURRENT_SOURCE_DIR})

2.10 安装和测试
在Child/CMakeList.txt中添加库和头文件;

install(TARGETS Child DESTINATION lib)
install(FILES Childxx.h DESTINATION include)

在根目录下的CMakeList.txt中添加可执行文件和配置头文件

install(TARGETS 项目名 DESTINATION bin)
install(FILES "${PROJECT_BINARY_DIR}/xxConfig.h" DESTINATION include)

CMake变量 CMAKE_INSTALL_PREFIX用于确定将安装文件的根目录;

在根目录CMakeList.txt文件中,添加一些测试来验证程序是否正常。

enable_testing()
//测试程序是否正常,是否有段错误或其他方式的崩溃,并且返回值为0
add_test(NAME Runs COMMAND 项目名 25)
//PASS_REGULAR_EXPRESSION属性验证测试的输出是否包含某些字符串。在这种情况下,验证在提供的参数数量不正确时打印使用消息。
add_test(NAME Usage COMMAND 项目名)
set_tests_properties(Usage PROPERTIES PASS_REGULAR_EXPRESSION "Usage:.*number")//定义一个函数来测试
function(do_test target arg result)add_test(NAME Comp${arg} COMMAND ${target} ${arg})set_tests_properties(Comp${arg} PROPERTIES PASS_REGULAR_EXPRESSION ${result})
endfunction(do_test)//测试
do_test(项目名 参数)

2.11 在不同平台下链接不同的库。
假如Child在相应的模块下,需要使用系统的log,exp函数,如平台没有,则从m库中选择相应的函数。

include(模块名)
check_symbol_exists(log "math.h" HAVE_LOG)
check_symbol_exists(exp "math.h" HAVE_EXP)
if(NOT (HAVE_LOG AND HAVE_EXP))unset(HAVE_LOG CACHE)unset(HAVE_EXP CACHE)set(CMAKE_REQUIRED_LIBRARIES "m")check_symbol_exists(log "math.h" HAVE_LOG)check_symbol_exists(exp "math.h" HAVE_EXP)if(HAVE_LOG AND HAVE_EXP)target_link_libraries(Child PRIVATE m)endif()
endif()

如果可用,则使用下面的命令指定HAVE_LOG和HAVE_EXP作为PRIVATE编译定义。

if(HAVE_LOG AND HAVE_EXP)target_compile_definitions(Child PRIVATE "HAVE_LOG" "HAVE_EXP")
endif()

在需要使用log和exp的源文件中添加如下代码。

#if defined(HAVE_LOG) && defined(HAVE_EXP)//使用exp,log函数
#else#enif

2.12 静态库和共享库

通过 BUILD_SHARED_LIBS变量可以用于控制add_library(),允许没有显示类型( STATIC、SHARED、MODULE、OBJECT)的库的构建方式。

在根目录下使用options() 命令添加 BUILD_SHARED_LIBS,可以通过ON或OFF控制。

//添加版cmake本
cmake_minimum_required(VERSION 3.10)//设置项目版本
project(Tutorial VERSION 1.0)//添加C++标准
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED True)//控制生成共享库
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}")
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}")
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}")//设置变量BUILD_SHARED_LIBS 
option(BUILD_SHARED_LIBS "Build using shared libraries" ON)//配置头文件
configure_file(项目名Config.h.in 项目名Config.h)//添加库目录
add_subdirectory(Child)//生成可执行程序
add_executable(项目名  项目名.cxx)
target_link_libraries(项目名 PUBLIC Child)

上面已经启用这个库,下面需要在子目录下进行设置Child/CMakeList.txt。

CMAKE案例参考:https://www.cnblogs.com/ph829/p/4759124.html

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

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

相关文章

《动手学深度学习》 第二天 (线性回归)

3.2 线性回归的从零开始实现 只利用NDArray和autograd来实现一个线性回归的训练。 首先,导入本节中实验所需的包或模块,其中的matplotlib包可用于作图,且设置成嵌入显示。 %matplotlib inline from IPython import display from matplotli…

Gartner发布2021年新兴技术成熟度曲线

来源:Gartner中国8月24日,Gartner 公司最新发布了“2021年新兴技术成熟度曲线”(Hype Cycle for Emerging Technologies,2021)。其中,建立信任,加速增长以及塑造变革将是三大主要趋势&#xff0…

Vue语法学习第一课——插值

学习关于Vue的插值语法 ① 文本值 &#xff1a; "Mustache"语法&#xff0c;即双大括号 1 <span>Message:{{msg}}</span> 注&#xff1a;双大括号中的msg值改变&#xff0c;插入的内容也会随之改变&#xff0c;可通过v-once指令限制&#xff0c;但会影响…

计算方法之方程求根、线性方程组求解、插值方法、数值积分简介

提示:本文章主要通过介绍方程求根、线性方程组求解、插值方法、数值积分等相关方法的理论知识,并运用相关方法来解决一个实际的问题,文章中简单介绍了二分法、不动点迭代,牛顿法、Scant Method等方程求根方法,Gauss-Seidel迭代,Jacobi迭代,SOR迭代,Gauss消元法等方程组…

hadoop 重新格式化 NameNode

【问题描述】 在安装配置hadoop的过程中&#xff0c;很可能发生错误导致datanode或者namenode 启动失败&#xff0c;这时我们可以选择重新格式化 namenode。 一、删除data数据和log日志 二 、使用命令 bin/dfs namenode -format 重新格式化 【注意事项】 为什么不能一直格式…

人工智能“上位”会让程序员消失吗?

大脑以及二进制代码&#xff08;图&#xff1a;Canva&#xff09;来源&#xff1a;Forbes作者&#xff1a;Nisha Talagala编译整理&#xff1a;科技行者写代码已经成了许多工作的一项关键技能。一些国家和学校甚至认为&#xff0c;编程语言是一种可以接受的外语。而在各种熙熙攘…

分类的IP地址

现有物理地址再有IP地址IP地址的表示方法为点分十进制法IP地址的设计思想&#xff1a;网络部分 主机部分 分类的IP地址 特征&#xff1a;根据不同特征的IP地址&#xff0c;事先约定好网络号所占的位数和主机号所占的位数。 A类地址 全球一共有27-2 个A类网络&#xff0c;每…

人工智能之深度优先,广度优先,贪婪最佳优先搜索,A*搜索以及爬山法与遗传算法

项目场景: 1. 分别用宽度优先、深度优先、贪婪算法和A*算法求解“罗马利亚度假问题”。 2. 分别用爬山法和GA算法求解n皇后问题。 文章目录 项目场景:一、度假场景1.1 问题描述2.1 问题分析:1.3 解决方案:1.4 运行结果二、N皇后问题2.1 问题描述2.2 数据存储结构2.3 算法思…

操作系统之多级队列调度算法,银行家算法,动态分区式存储区管理

题目描述: 1.对于多级队列调度算法,主要介绍轮转法,短进程优先算法;银行家算法主要介绍进程的资源分配策略; 2.对于动态分区式存储区管理,主要介绍首先适应法,最佳适应法,最坏适应法等调度算法。 文章目录 题目描述:程序功能及设计思路1. 多级队列调度算法函数设计2. …

卫星对于物联网来说是一个非常好的选择

ALAMY来源&#xff1a;IEEE电气电子工程师对许多人来说&#xff0c;“物联网”一词可能会让人想起智能城市的努力&#xff0c;比如配备交通摄像头和空气质量传感器的路灯&#xff0c;或者在自己家里连接设备。一个很自然的问题是&#xff0c;为什么你从没想使用卫星连接任何这些…

利用子网掩码划分子网

分类IP地址的弊端 一个物理网络不能过大&#xff0c;否则网络性能很差&#xff0c;某个B类或A类IP网络无法全部用于单个物理网络分类IP地址分配不合理&#xff0c;利用率低分类IP地址设计的弊端 —— 不灵活&#xff0c;IP地址利用率不高 划分子网的思路 网络管理员将本应属于…

springcloud流程图

自己画的&#xff1a; 别人画的 别人画的2 转载于:https://www.cnblogs.com/dzhou/p/10504215.html

编译原理之LR语法分析器,自动机

本博客主要介绍LR语法分析器的代码实现,包含完整的测试数据与源代码。 文章目录 1. 主要内容:2.实验过程2.1 实验数据2.2 源代码1. 主要内容: LR语法分析器理论:https://blog.csdn.net/qq_40294512/article/details/92621241 2.实验过程 2.1 实验数据 G.txt数据文件 E-&…

java 搭建 web服务器 socket实现

【写在前面】 云计算的第n个java作业&#xff0c;开始一直不懂为什么老师一直让我们写java web的小demo&#xff0c;不应该是hadoop啥的直接上框架嘛。后来慢慢了解到&#xff0c;其实java web 的一些内容确实是云计算的基础。这个demo是用java socket 来搭建一个web服务器&…

【趋势】未来十年计算机体系结构的历史和趋势

来源&#xff1a;机器之心先分享我对这篇文章的总结&#xff0c;或者我得到的启发&#xff1a;1、DSA&#xff08;Domain-Specific Architectures&#xff0c;特定领域的体系结构&#xff09;将成为未来十年甚至更长时间&#xff0c;计算机体系结构的趋势。登纳德缩放定律结束、…

BZOJ3064 CPU监控

题目链接&#xff1a;戳我 比较神仙的一个题&#xff08;至少对于我这个小蒟蒻来说。。。&#xff09;下面尽可能详细地解释一下吧。。。学习来源&#xff1a;这位神仙的题解 其实就是对于操作的转换。我们设(x,y)为操作的参数&#xff0c;设当前数为a&#xff0c;操作为max(ax…

java socket 实现增删改查 + 在线答题小案例

实现效果 &#xff08;1&#xff09; 在client端可以实现对数据库的操作&#xff08;Select&#xff0c;Insert&#xff0c;Update&#xff0c;Delete&#xff09; &#xff08;2&#xff09;数据库中创建一个考试表和学生表&#xff0c;考试表中问题是四项选择题&#xff08;…

90后斯坦福博士论文登Science封面!AI算法准确预测RNA三维结构

来源&#xff1a;Science编辑&#xff1a;yaxin、su「我们对大部分RNA的结构几乎一无所知。」半个世纪以来&#xff0c;确定生物分子的三维结构一直困惑着科学家&#xff0c;也是生物学的重大挑战之一。难就难在&#xff0c;RNA折叠成复杂三维结构的形状很难通过实验或计算来确…

Event Recommendation Engine Challenge分步解析第五步

一、请知晓 本文是基于&#xff1a; Event Recommendation Engine Challenge分步解析第一步 Event Recommendation Engine Challenge分步解析第二步 Event Recommendation Engine Challenge分步解析第三步 Event Recommendation Engine Challenge分步解析第四步 需要读者先阅读…

计算机网络之RIP协议与OSPF协议模拟、UDP与TCP编程,Wireshark抓包分析

通过Python模拟RIP协议,OSPF协议,并模拟UDP和TCP编程,并通过Wireshark抓包工具,对所发送的报文进行捕获分析。 文章目录 一、RIP协议的模拟与编程二、OSPF协议的模拟与编程三、UDP编程四、TCP套接字编程五、Wireshark 数据分析六、总结一、RIP协议的模拟与编程 1.1 题目 …