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

CMake基本语法大全

文章目录

    • CMake是什么
    • CMake基本用法
    • 基本语法
      • 设置编译类型
      • 定义变量
      • 设置包含的目录
      • 指定包含的源文件
      • 指定C++标准
      • 链接外部文件
      • 打印信息
    • 安装和测试
    • CMake系统变量
      • CMake配置开关
      • 配置项目版本信息
      • 组织多个项目文件
    • source_group逻辑分组

CMake是什么

CMake是一个管理源代码构建的工具。现在CMake用来生成现代的构建系统,包括Visual Studio和XCode等等。通过CMake编译可以生成Visual Studio和XCode项目文件。CMake广泛用于C/C++语言项目,但它也适用于其它语言项目。

CMake基本用法

# 指定CMake最低版本
cmake_minimum_required(VERSION 3.10)# 设置项目的名称
project(Tutorial)# 添加执行文件
add_executable(Tutorial tutorial.cxx)# 设置项目名称和版本号
project(Tutorial VERSION 1.0)# 配置一个代码文件用来记录版本号
configure_file(TutorialConfig.h.in TutorialConfig.h)

基本语法

设置编译类型

add_executable(test demo.cpp)     # 生成可执行文件
add_library(test STATIC test.cpp) # 生成静态库
add_library(test SHARED test.cpp) # 生成动态库或共享库

定义变量

set(SRC_LIST main.cpp test.cpp) #定义变量
add_executable(demo ${SRC_LIST}) #使用变量#追加变量对应的值
set(SRC_LIST main.cpp)
set(SRC_LIST ${SRC_LIST} test.cpp)
add_executable(demo ${SRC_LIST})#向list追加和删除变量的值
set(SRC_LIST main.cpp)
list(APPEND SRC_LIST test.cpp)
list(REMOVE_ITEM SRC_LIST main.cpp)
add_executable(demo ${SRC_LIST})

设置包含的目录

# CMAKE_CURRENT_SOURCE_DIR 指的是当前 CMakeLists.txt 文件所在的源代码目录。  
# CMAKE_CURRENT_BINARY_DIR 指的是当前 CMakeLists.txt 文件对应的构建目录
# 也就是CMake执行命令的目录  
# 影响全局的文件包含  
include_directories(${CMAKE_CURRENT_SOURCE_DIR}${CMAKE_CURRENT_BINARY_DIR}${CMAKE_CURRENT_SOURCE_DIR}/include
)#Linux 下还可以通过如下方式设置包含的目录
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -I${CMAKE_CURRENT_SOURCE_DIR}")# 给特定对象添加包含目录  可以指定影响范围  PUCBLIC 影响全局 PRIVATE 影响局部
target_include_directories(Tutorial PUBLIC "${PROJECT_BINARY_DIR}")# 包含其它CMake文件  
include(./common.cmake) # 指定包含文件的全路径
include(def) # 在搜索路径中搜索def.cmake文件
# 设置include的搜索路径
set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake) 

指定包含的源文件

#明确指定包含哪些源文件
add_library(demo demo.cpp test.cpp util.cpp)#发现一个目录下所有的源代码文件并将列表存储在一个变量中
aux_source_directory(dir VAR) 
aux_source_directory(. SRC_LIST) # 搜索当前目录下的所有.cpp文件
add_library(demo ${SRC_LIST})#自定义搜索规则
#@1 指定工作模式(GLOB不递归 GLOB_RECURSE递归)  @2文件路径存储变量 
#@3 CONFIGURE_DEPENDS  文件列表中的文件发生变化,CMake会重新配置项目  
#@4 指定匹配的文件   
file(GLOB SRC_LIST CONFIGURE_DEPENDS "src/*.cpp")
add_library(demo ${SRC_LIST})
# 或者
file(GLOB SRC_PROTOCOL_LIST "protocol/*")
add_library(demo ${SRC_LIST} ${SRC_PROTOCOL_LIST})# 递归查找  
file(GLOB_RECURSE SRC_LIST "*.cpp")# 相对protocol目录下搜索
FILE(GLOB SRC_PROTOCOL RELATIVE "protocol" "*.cpp") 
add_library(demo ${SRC_LIST} ${SRC_PROTOCOL_LIST})# @1目录名称  @2变量  
aux_source_directory(. SRC_LIST)
aux_source_directory(protocol SRC_PROTOCOL_LIST)
add_library(demo ${SRC_LIST} ${SRC_PROTOCOL_LIST})

指定C++标准

# specify the C++ standard
# CMAKE_CXX_SDTANDARD 声明一定要放在add_executable前面
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED True)

链接外部文件

# 设置链接库搜索目录  
link_directories(${CMAKE_CURRENT_SOURCE_DIR}/libs
)# 链接特定的库  
# @1目标对象   @2被链接的库                       
target_link_libraries(demo libface.a) # 链接libface.a
target_link_libraries(demo libface.so) # 链接libface.so
target_link_libraries(demo ${CMAKE_CURRENT_SOURCE_DIR}/libs/libface.a)
target_link_libraries(demo ${CMAKE_CURRENT_SOURCE_DIR}/libs/libface.so)# 查找QT5的Core模块 REQUIRED说明模块是必须得 没有就报错  
find_package(Qt5 COMPONENTS Core REQUIRED)# 查找并配置 pkg-config 工具, 用于管理和查找库的配置信息  
find_package(PkgConfig REQUIRED)# pkg-config 检查和配置 libisoburn-1 库,并将其标记为已导入目标
# @1 定义的 CMake 变量,用于存储 pkg-config 检查的结果
# @2 REQUIRED 说明这个库是必须得  @3库的名称  
# IMPORTED_TARGET 表示是一个外部库,将其配置为 CMake 中的导入目标,便于在后续的CMake脚本中使用
pkg_check_modules(isoburn REQUIRED libisoburn-1 IMPORTED_TARGET)# 导入对应的库  
target_link_libraries(${BIN_NAME}Qt5::CorePkgConfig::isoburn
)

打印信息

message(${PROJECT_SOURCE_DIR})
message("build with debug mode")
message(WARNING "this is warnning message")
# FATAL_ERROR 会导致编译失败
message(FATAL_ERROR "this build has many error") 

安装和测试

# 将生成的文件放到对应的目录中
# @1安装的文件类型(TARGETS 生成的库或可执行文件  FILES安装单个或多个文件 DIRECTORY安装整个目录 CODE 执行CMake代码)  
# @2要安装的文件地址  
# @3安装的目录 include 为系统include目录  
# @4FILES_MATCHING PATTERN "*.h" 仅安装以.h结尾的文件  
install(DIRECTORY${PROJECT_SOURCE_DIR}/include/${PROJECT_NAME}DESTINATION includeFILES_MATCHING PATTERN "*.h"
)# LIBRARY 指定安装的类型是库  
# DESTINATION${CMAKE_INSTALL_LIBDIR} 指定将库文件安装到CMAKE_INSTALL_LIBDIR变量指定的目录(通常是 lib)
install(TARGETS ${PROJECT_NAME} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR})# 用于生成pkg-config文件${PROJECT_NAME}.pc.in 是模板文件,${PROJECT_NAME}.pc是生成的文件
# pkg-config文件的作用:  1.提供编译和链接信息  2.简化构建过程  3.维护库的兼容性和配置  
configure_file(${PROJECT_SOURCE_DIR}/${PROJECT_NAME}.pc.in ${PROJECT_NAME}.pc @ONLY)# install(FILES ...)将生成的.pc文件安装到pkgconfig目录,供pkg-config使用
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.pc DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig)# 生成和安装 CMake 配置文件,使其他 CMake 项目能够找到并使用这个库  
configure_file(${PROJECT_SOURCE_DIR}/${PROJECT_NAME}Config.cmake.in ${PROJECT_NAME}Config.cmake @ONLY)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME})# 可以指定安装的根路径  
cmake --install .
cmake --install . --prefix "/home/myuser/installdir"

添加对应的cmake测试

enable_testing()# 判断程序能否正常执行
add_test(NAME Runs COMMAND Tutorial 25)# 判断程序能否正常使用
add_test(NAME Usage COMMAND Tutorial)# 添加对应的测试属性,验证输出的字符串中是否包含对应的字符串
set_tests_properties(UsagePROPERTIES 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 a bunch of result based tests
do_test(Tutorial 4 "4 is 2")
do_test(Tutorial 9 "9 is 3")
do_test(Tutorial 5 "5 is 2.236")
do_test(Tutorial 7 "7 is 2.645")
do_test(Tutorial 25 "25 is 5")
do_test(Tutorial -25 "-25 is [-nan|nan|0]")
do_test(Tutorial 0.0001 "0.0001 is 0.01")

CMake系统变量

### 预定义变量  # 工程的根目录  
PROJECT_SOURCE_DIR# 运行cmake命令的目录,通常是 ${PROJECT_SOURCE_DIR}/build
PROJECT_BINARY_DIR# 返回通过 project 命令定义的项目名称  
PROJECT_NAME# CMakeLists.txt 所在的路径
CMAKE_CURRENT_SOURCE_DIR# 编译目录
CMAKE_CURRENT_BINARY_DIR# CMakeLists.txt 的完整路径  
CMAKE_CURRENT_LIST_DIR# 当前所在的行  
CMAKE_CURRENT_LIST_LINE# 定义自己的 cmake 模块所在的路径,然后可以用INCLUDE命令来调用自己的模块
CMAKE_MODULE_PATH
SET(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake)# 重新定义目标二进制可执行文件的存放位置  
EXECUTABLE_OUTPUT_PATH# 重新定义目标链接库文件的存放位置   
LIBRARY_OUTPUT_PATH# 使用环境变量
$ENV{Name}
#写入环境变量
set(ENV{Name} value) # 这里没有“$”符号# 系统信息  
# cmake 主版本号,比如 3.4.1 中的 3  
CMAKE_MAJOR_VERSION
# cmake 次版本号,比如 3.4.1 中的 4
­CMAKE_MINOR_VERSION
# cmake 补丁等级,比如 3.4.1 中的 1
­CMAKE_PATCH_VERSION
# 系统名称,比如 Linux-­2.6.22  
­CMAKE_SYSTEM  
# 不包含版本的系统名,比如 Linux
­CMAKE_SYSTEM_NAME
# 系统版本,比如 2.6.22
­CMAKE_SYSTEM_VERSION
# 处理器名称,比如 i686
­CMAKE_SYSTEM_PROCESSOR# 在所有的类 UNIX 平台下该值为 TRUE,包括 OS X 和 cygwin  
­UNIX
# 在所有的 win32 平台下该值为 TRUE,包括 cygwin  
­WIN32

CMake配置开关

# 使用 add_library 又没有指定库类型的情况下 默认编译生成的库都是静态库
set(BUILD_SHARED_LIBS ON)  # 默认生成的为动态库# 设置 C 编译选项,也可以通过指令 add_definitions()添加
CMAKE_C_FLAGS
# 设置 C++ 编译选项,也可以通过指令 add_definitions()添加
CMAKE_CXX_FLAGS

配置项目版本信息

在源码目录中创建TutorialConfig.h.in文件
文件内容如下:

// the configured options and settings for Tutorial
#define Tutorial_VERSION_MAJOR @Tutorial_VERSION_MAJOR@
#define Tutorial_VERSION_MINOR @Tutorial_VERSION_MINOR@

CMake配置的时候会将 @Tutorial_VERSION_MAJOR@ 和 @Tutorial_VERSION_MINOR@ 替换掉
在代码中获取项目的版本信息

 if (argc < 2) {// report versionstd::cout << argv[0] << " Version " << Tutorial_VERSION_MAJOR << "."<< Tutorial_VERSION_MINOR << std::endl;std::cout << "Usage: " << argv[0] << " number" << std::endl;return 1;}

组织多个项目文件

将库放到子目录MathFunctions中,这个目录中存在一个头文件MathFunctions.h和源文件mysqrt.cxx。
在这个目录中添加CMakeLists.txt文件文件中只包含一行

add_library(MathFunctions mysqrt.cxx)

在顶层的CMakeLists.txt中添加子目录add_subdirectory() ,确保库文件被编译。
为了将新库引入到可执行文件中,我们需要包含对应的目录,确保对应的文件能被找到。

# 添加对应的子目录
add_subdirectory(MathFunctions)# 添加执行程序
add_executable(Tutorial tutorial.cxx)# 链接对应的库文件
target_link_libraries(Tutorial PUBLIC MathFunctions)# 添加链接搜索的文件路径
target_include_directories(Tutorial PUBLIC"${PROJECT_BINARY_DIR}""${PROJECT_SOURCE_DIR}/MathFunctions")

将MathFunctions设置为可选的,可开启可关闭
在顶层的CMakeList.txt文件中添加对应的变量开关

# 添加标志位默认为开
option(USE_MYMATH "Use tutorial provided math implementation" ON)
# 将一部分配置信息写入到配置文件中
configure_file(TutorialConfig.h.in TutorialConfig.h)

在下面的代码中使用这个开关来选择添加对应的lib库

# 开关开启的时候添加对应的库和包含目录
if(USE_MYMATH)add_subdirectory(MathFunctions)list(APPEND EXTRA_LIBS MathFunctions)list(APPEND EXTRA_INCLUDES "${PROJECT_SOURCE_DIR}/MathFunctions")
endif()# 添加执行文件
add_executable(Tutorial tutorial.cxx)target_link_libraries(Tutorial PUBLIC ${EXTRA_LIBS})# 添加搜索路径和目录
target_include_directories(Tutorial PUBLIC"${PROJECT_BINARY_DIR}"${EXTRA_INCLUDES})

在对应的调用文件中使用对应的库,通过宏来判断来添加对应的文件

#ifdef USE_MYMATH
#include "MathFunctions.h"
#endif#ifdef USE_MYMATHconst double outputValue = mysqrt(inputValue);
#elseconst double outputValue = sqrt(inputValue);
#endif

由于我们的代码现在需要USE_MYMATH,所以我们需要在TutorialConfig.h.in中添加对应的CMake宏

#cmakedefine USE_MYMATH

通过命令行来修改变量开关

cmake ../Step2 -DUSE_MYMATH=OFF  

source_group逻辑分组

source_group是一个在CMake中使用的命令,用于组织源代码文件。它通常与add_executable或add_library命令一起使用,以将源文件组织成逻辑分组,并在生成的项目文件中显示这些分组。

source_group 命令的基本语法如下:

# <group_name> 分组名称
# 如果你希望创建子分组, 可以在分组名称中使用反斜杠 \(在Windows上)或正斜杠/(跨平台)来表示路径层级  
source_group(<group_name> FILES <source1> <source2> ...)

下面是这个命令的用法示例:

# 定义源代码文件
set(SOURCES src/main.cppsrc/utils/util1.cppsrc/utils/util2.cppinclude/utils/util1.hinclude/utils/util2.h
)# 创建可执行文件并将源代码文件添加到项目中
add_executable(my_executable ${SOURCES})# 使用source_group命令将源代码文件组织成逻辑分组
# @1分组名称  @2FILES  @3文件的路径  
source_group("Source Files" FILES src/main.cpp)
source_group("Source Files\\Utils" FILES src/utils/util1.cpp src/utils/util2.cpp)
source_group("Header Files" FILES include/utils/util1.h include/utils/util2.h)

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • c++同人小游戏之斗罗大陆4
  • 书生浦语实训营-InternVL 多模态模型部署微调实践
  • (最新)华为 2024 届秋招-硬件技术工程师-单板硬件开发—机试题—(共12套)(每套四十题)
  • Unity(2022.3.41LTS) - 脚本
  • react + ts + material-ui V5版本的table封装
  • 本地部署aniportrait
  • 【unity实战】使用新版输入系统Input System+Rigidbody实现第三人称人物控制器
  • 【2024 CCF编程能力等级认证(GESP)Python 】一级大纲
  • 【图像去噪】论文精读:Multi-level Wavelet-CNN for Image Restoration(MWCNN)
  • 在Supabase创建用户登录并获取token的操作实践
  • 图像尺寸测量仪的精度概念解析
  • 掌握SQL数据分割技巧:垂直与水平分割全解析
  • 学习关系型数据库:在Ubuntu和FreeBSD下安装firebird
  • elementui图标偶尔乱码问题
  • PyCharm 自定义字体大小
  • [js高手之路]搞清楚面向对象,必须要理解对象在创建过程中的内存表示
  • ➹使用webpack配置多页面应用(MPA)
  • canvas绘制圆角头像
  • E-HPC支持多队列管理和自动伸缩
  • ES6简单总结(搭配简单的讲解和小案例)
  • GDB 调试 Mysql 实战(三)优先队列排序算法中的行记录长度统计是怎么来的(上)...
  • HTML中设置input等文本框为不可操作
  • iOS帅气加载动画、通知视图、红包助手、引导页、导航栏、朋友圈、小游戏等效果源码...
  • Java 网络编程(2):UDP 的使用
  • javascript 哈希表
  • JavaScript 无符号位移运算符 三个大于号 的使用方法
  • JS创建对象模式及其对象原型链探究(一):Object模式
  • JS正则表达式精简教程(JavaScript RegExp 对象)
  • PHP 的 SAPI 是个什么东西
  • python 学习笔记 - Queue Pipes,进程间通讯
  • Shadow DOM 内部构造及如何构建独立组件
  • Swoft 源码剖析 - 代码自动更新机制
  • Tornado学习笔记(1)
  • vue-router的history模式发布配置
  • Vue组件定义
  • 搞机器学习要哪些技能
  • 前端代码风格自动化系列(二)之Commitlint
  • 前嗅ForeSpider采集配置界面介绍
  • 设计模式 开闭原则
  • 它承受着该等级不该有的简单, leetcode 564 寻找最近的回文数
  • 一份游戏开发学习路线
  • 因为阿里,他们成了“杭漂”
  • 优秀架构师必须掌握的架构思维
  • 小白应该如何快速入门阿里云服务器,新手使用ECS的方法 ...
  • ​RecSys 2022 | 面向人岗匹配的双向选择偏好建模
  • ​ubuntu下安装kvm虚拟机
  • ​软考-高级-信息系统项目管理师教程 第四版【第14章-项目沟通管理-思维导图】​
  • ​字​节​一​面​
  • # 消息中间件 RocketMQ 高级功能和源码分析(七)
  • #define 用法
  • (09)Hive——CTE 公共表达式
  • (1)(1.13) SiK无线电高级配置(六)
  • (1)Android开发优化---------UI优化
  • (20)docke容器
  • (STM32笔记)九、RCC时钟树与时钟 第二部分