CMake基础:CMakeLists.txt 文件结构和语法

目录

1.CMakeLists.txt基本结构

2.核心语法规则

3.关键命令详解

4.常用预定义变量

5.变量和缓存

6.变量作用域与传递

7.注意事项


1.CMakeLists.txt基本结构

        CMakeLists.txt 是 CMake 构建系统的核心配置文件,采用命令式语法组织项目结构和编译流程。主要用于定义项目的构建规则、依赖关系、编译选项等。每个 CMake 项目通常都有一个或多个 CMakeLists.txt 文件。

        一个完整的 CMakeLists.txt 通常包含以下部分:

# 1. CMake 最低版本要求
cmake_minimum_required(VERSION 3.10)# 2. 项目信息
project(MyProject VERSION 1.0.0 LANGUAGES CXX)# 3. 全局配置(可选)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)  # 生成 compile_commands.json# 4. 查找依赖(可选)
find_package(Threads REQUIRED)
find_package(Boost 1.70 COMPONENTS system REQUIRED)# 5. 添加子目录(可选)
add_subdirectory(src)
add_subdirectory(tests)# 6. 定义目标(可执行文件或库)
add_executable(myapp main.cpp)
add_library(mylib STATIC src/lib.cpp src/utils.cpp)# 7. 配置目标属性
target_include_directories(mylib PUBLIC include)
target_link_libraries(myapp PRIVATE mylib Threads::Threads)
target_compile_definitions(myapp PRIVATE DEBUG_MODE=1)# 8. 安装规则(可选)
install(TARGETS myapp DESTINATION bin)
install(FILES include/mylib.h DESTINATION include)# 9. 测试配置(可选)
enable_testing()
add_test(NAME MyTest COMMAND myapp_test)

2.核心语法规则

1.命令格式

command(arg1 arg2 ...)  # 命令名不区分大小写,但参数区分
  • 命令和参数用空格或括号分隔。
  • 参数可用双引号括起(如包含空格时):set(NAME "My Project")

2.变量引用

set(SOURCE_FILES main.cpp src/foo.cpp)
add_executable(myapp ${SOURCE_FILES})  # 使用 ${} 引用变量
  • 变量作用域:当前目录及子目录,可用 PARENT_SCOPE 提升作用域。

3.注释

# 单行注释

4.条件语句

if(WIN32)set(PLATFORM_LIBS ws2_32)
else()set(PLATFORM_LIBS pthread)
endif()target_link_libraries(myapp PRIVATE ${PLATFORM_LIBS})
  • 条件表达式:WIN32APPLEUNIXDEFINED varNOTANDOR 等。

5.循环

foreach(file IN LISTS source_files)message("Processing file: ${file}")
endforeach()

6.函数和宏

# 函数(有独立作用域)
function(print_info name)message("Project name: ${name}")
endfunction()# 宏(直接替换)
macro(add_example name)add_executable(${name} examples/${name}.cpp)
endmacro()print_info(${PROJECT_NAME})
add_example(example1)

3.关键命令详解

1.项目设置

  • cmake_minimum_required(VERSION <version>):指定所需的最低 CMake 版本。
  • project(<name> [VERSION <ver>] [LANGUAGES <langs>]):定义项目名称、版本和支持的语言。

示例如下:

#1
cmake_minimum_required(VERSION 3.10)
#2
project(MyProject CXX)

2.目标定义

  • add_executable(<name> <sources>):创建可执行文件。
  • add_library(<name> [STATIC|SHARED|MODULE] <sources>):创建库(静态 / 共享 / 模块)。
  • add_custom_target(<name> [COMMAND <cmd>] [DEPENDS <deps>]):创建自定义目标(如构建脚本)。

示例代码:

#1
add_executable(MyExecutable main.cpp other_file.cpp)
#2
add_library(MyLibrary STATIC library.cpp)
#3
add_library(MyLibrary SHARED library.cpp)

3.依赖管理

  • find_package(<package> [REQUIRED] [VERSION <ver>]):查找并导入外部包。
  • add_subdirectory(<dir>):添加子目录中的 CMakeLists.txt。
  • target_link_libraries(<target> <PRIVATE|PUBLIC|INTERFACE> <libs>):链接库到目标。
  • include_directories(<dirs>...)

示例代码:

#1
find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Widgets Network)
find_package(Qt${QT_VERSION_MAJOR} CONFIG REQUIRED COMPONENTS Widgets Network)#2
add_subdirectory(tutorial)#3
target_link_libraries(QSimpleUpdater PUBLIC Qt${QT_VERSION_MAJOR}::Core Qt${QT_VERSION_MAJOR}::Widgets PRIVATE Qt${QT_VERSION_MAJOR}::Network)#4
include_directories(${PROJECT_SOURCE_DIR}/include)

4.编译选项

  • target_include_directories(<target> <PRIVATE|PUBLIC|INTERFACE> <dirs>):添加头文件搜索路径。
  • target_compile_definitions(<target> <PRIVATE|PUBLIC|INTERFACE> <defs>):添加编译定义(如 -DDEBUG)。
  • target_compile_options(<target> <PRIVATE|PUBLIC|INTERFACE> <options>):添加编译选项(如 -Wall)。

示例代码:

#1
target_include_directories(QSimpleUpdater PUBLIC include)

5.安装规则

install(TARGETS target1 [target2 ...][RUNTIME DESTINATION dir][LIBRARY DESTINATION dir][ARCHIVE DESTINATION dir][INCLUDES DESTINATION [dir ...]][PRIVATE_HEADER DESTINATION dir][PUBLIC_HEADER DESTINATION dir])

示例代码:

#1
install(TARGETS <targets>RUNTIME DESTINATION binLIBRARY DESTINATION libARCHIVE DESTINATION lib/static)install(FILES <files> DESTINATION include)
install(DIRECTORY <dir> DESTINATION share)#2
install(TARGETS MyExecutable RUNTIME DESTINATION bin)

6.自定义命令 (add_custom_command 命令)

add_custom_command(TARGET targetPRE_BUILD | PRE_LINK | POST_BUILDCOMMAND command1 [ARGS] [WORKING_DIRECTORY dir][COMMAND command2 [ARGS]][DEPENDS [depend1 [depend2 ...]]][COMMENT comment][VERBATIM]
)

示例代码:

add_custom_command(TARGET MyExecutable POST_BUILDCOMMAND ${CMAKE_COMMAND} -E echo "Build completed."
)

7.测试配置

enable_testing()
add_test(NAME <test_name> COMMAND <executable> <args>)
add_test(NAME <test_name> WORKING_DIRECTORY <dir> COMMAND <cmd>)

4.常用预定义变量

1. 项目信息

变量名描述示例值
PROJECT_NAME当前项目名称MyProject
PROJECT_VERSION项目版本(通过 project() 设置)1.2.3
PROJECT_SOURCE_DIR当前项目的源目录/path/to/myproject
PROJECT_BINARY_DIR当前项目的构建目录/path/to/myproject/build

2.路径相关

变量名描述示例值
CMAKE_SOURCE_DIR顶级 CMakeLists.txt 所在目录/path/to/myproject
CMAKE_BINARY_DIR顶级构建目录/path/to/myproject/build
CMAKE_CURRENT_SOURCE_DIR当前 CMakeLists.txt 所在目录/path/to/myproject/src
CMAKE_CURRENT_BINARY_DIR当前构建目录/path/to/myproject/build/src
CMAKE_INSTALL_PREFIX安装路径前缀/usr/local(默认)
LIBRARY_OUTPUT_PATH库文件输出的默认路径库路径不设置的话,默认放在BINARY_DIR下,即构建时执行cmake命令的目录下

3.构建配置

变量名描述示例值
CMAKE_BUILD_TYPE构建类型DebugReleaseRelWithDebInfo
CMAKE_C_COMPILERC 编译器路径/usr/bin/gcc
CMAKE_CXX_COMPILERC++ 编译器路径/usr/bin/g++
CMAKE_CXX_STANDARDC++ 标准版本11141720
CMAKE_GENERATOR当前使用的生成器Unix MakefilesNinja
CMAKE_C_STANDARD_REQUIRED
  • ON:若编译器不支持指定的 C 标准,CMake 会终止配置并报错。
  • OFF(默认):若编译器不支持,CMake 会尝试降级到兼容版本(可能导致意外行为)。
set(CMAKE_C_STANDARD 11)             # 指定 C 语言标准为 C11
set(CMAKE_C_STANDARD_REQUIRED ON)    # 强制要求此标准
CMAKE_CXX_STANDARD_REQUIRED
  • ON:若编译器不支持指定的 C++ 标准,CMake 会终止配置并报错。
  • OFF(默认):若编译器不支持,CMake 会尝试降级到兼容版本(可能导致意外行为)。
set(CMAKE_CXX_STANDARD 20) # 指定 C++ 标准为 C++20 set(CMAKE_CXX_STANDARD_REQUIRED ON) # 强制要求此标准
CMAKE_DEBUG_POSTFIX 
设置调试版本后缀
set(CMAKE_DEBUG_POSTFIX d)

4.系统信息

变量名描述示例值
CMAKE_SYSTEM_NAME操作系统名称LinuxWindowsDarwin
CMAKE_SYSTEM_VERSION系统版本10.0(Windows)
CMAKE_HOST_SYSTEM_PROCESSOR处理器架构x86_64arm64

5.目标属性(Target Properties)

通过 set_target_properties 或 get_target_property 操作,影响特定目标的行为。

常用属性

属性名描述设置命令
OUTPUT_NAME输出文件名set_target_properties(myapp PROPERTIES OUTPUT_NAME "custom_name")
VERSION库版本号set_target_properties(mylib PROPERTIES VERSION "1.2.3")
SOVERSION共享库 API 版本set_target_properties(mylib PROPERTIES SOVERSION "1")
COMPILE_DEFINITIONS编译定义(如 -DDEBUGtarget_compile_definitions(myapp PRIVATE DEBUG)
INCLUDE_DIRECTORIES头文件搜索路径target_include_directories(myapp PUBLIC include)
LINK_LIBRARIES链接库target_link_libraries(myapp PRIVATE pthread)
POSITION_INDEPENDENT_CODE是否生成位置无关代码(共享库必需)set_target_properties(mylib PROPERTIES POSITION_INDEPENDENT_CODE ON)

5.变量和缓存

CMake 使用变量来存储和传递信息,这些变量可以在 CMakeLists.txt 文件中定义和使用。

变量可以分为普通变量和缓存变量。

1.变量定义与使用

定义变量:

set(MY_VAR "Hello World")

使用变量:

message(STATUS "Variable MY_VAR is ${MY_VAR}")

2.缓存变量

缓存变量存储在 CMake 的缓存文件中,用户可以在 CMake 配置时修改这些值。缓存变量通常用于用户输入的设置,用户可通过命令行(-D)或 CMake GUI 修改,例如编译选项和路径。

定义缓存变量:

set(MY_CACHE_VAR "DefaultValue" CACHE STRING "A cache variable")set(BUILD_SHARED_LIBS ON CACHE BOOL "Build shared libraries")
set(CMAKE_INSTALL_PREFIX "/usr/local" CACHE PATH "Installation directory")

使用缓存变量:

message(STATUS "Cache variable MY_CACHE_VAR is ${MY_CACHE_VAR}")

3.环境变量

  • 访问方式$ENV{VARIABLE_NAME}
  • 修改方式set(ENV{VARIABLE_NAME} value)
message("PATH: $ENV{PATH}")  # 读取环境变量
set(ENV{MY_LIB_PATH} "${CMAKE_SOURCE_DIR}/libs")  # 设置环境变量

6.变量作用域与传递

  1. 默认作用域:当前目录及子目录。
  2. 提升作用域PARENT_SCOPE 参数。
# 在子目录 CMakeLists.txt 中
set(CHILD_VAR "value" PARENT_SCOPE)  # 将变量传递到父目录

7.注意事项

1.模块化结构

project/
├── CMakeLists.txt       # 顶级配置
├── src/                 # 源代码
│   └── CMakeLists.txt
├── include/             # 公共头文件
├── tests/               # 测试代码
│   └── CMakeLists.txt
├── examples/            # 示例
└── CMakeModules/        # 自定义 CMake 模块

2.使用现代 CMake 模式

  • 优先使用 target_* 命令(如 target_include_directories)而非全局设置。
  • 通过 PUBLIC/PRIVATE/INTERFACE 明确依赖范围。

3.避免硬编码路径

# 不好的做法
include_directories("/usr/local/include/mylib")# 好的做法
find_package(MyLib REQUIRED)
target_link_libraries(myapp PRIVATE MyLib::MyLib)

4.添加版本控制

project(MyProject VERSION 1.2.3)
configure_file(version.h.in version.h)
target_include_directories(myapp PRIVATE ${CMAKE_BINARY_DIR})

掌握 CMakeLists.txt 的结构和语法是高效管理 C/C++ 项目的关键,合理组织文件可大幅提升项目的可维护性和跨平台兼容性。

相关链接

  • CMake 官网 CMake - Upgrade Your Software Build System
  • CMake 官方文档:CMake Tutorial — CMake 4.0.2 Documentation
  • CMake 源码:https://github.com/Kitware/CMake
  • CMake 源码:Sign in · GitLab

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

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

相关文章

战略-2.1 -战略分析(PEST/五力模型/成功关键因素)

战略分析路径&#xff0c;先宏观&#xff08;PEST&#xff09;、再产业&#xff08;产品生命周期、五力模型、成功关键因素&#xff09;、再竞争对手分析、最后企业内部分析。 本文介绍&#xff1a;PEST、产品生命周期、五力模型、成功关键因素、产业内的战略群组 一、宏观环境…

深入理解设计模式:工厂模式、单例模式

深入理解设计模式&#xff1a;工厂模式、单例模式 设计模式是软件开发中解决常见问题的可复用方案。本文将详细介绍两种种重要的创建型设计模式&#xff1a;工厂模式、单例模式&#xff0c;并提供Java实现示例。 一、工厂模式 工厂模式是一种创建对象的设计模式&#xff0c;…

Jenkins 2.426.2配置“构建历史的显示名称,加上包名等信息“

Jenkins 2.426.2配置“构建历史的显示名称,加上包名等信息" 需求:想要在构建历史中展示,本次运行的是哪个版本或哪个包 操作步骤: 1、先安装插件Build Name and Description Setter 2、Set Build Name 3、构建历史处查看展示 插件特性说明 安装依赖:需手动安装 Build …

为何在VMware中清理CentOS虚拟机后,本地磁盘空间未减少的问题解决

文章目录 前言原因:虚拟机磁盘&#xff0c;到底是咋回事&#xff1f;为啥空间没变小&#xff1f; 解决方案 前言 在使用VMware运行CentOS虚拟机时&#xff0c;你是否曾遇到过这样的情况&#xff1a;明明在虚拟机内删除了大量文件&#xff0c;rm -rf 后发现并没什么用&#xff…

Development靶机通关笔记

一、主机发现 arp-scan -l靶机ip为192.168.55.152 二、端口扫描、目录枚举、漏洞扫描、指纹识别 2.1端口扫描 nmap --min-rate 10000 -p- 192.168.55.152发现靶机没有开放80端口&#xff0c;开放的是8080端口 UDP端口扫描 nmap -sU --min-rate 10000 -p- 192.168.55.152靶…

自然语言处理核心技术:词向量(Word Embedding)解析

自然语言处理核心技术&#xff1a;词向量&#xff08;Word Embedding&#xff09;全面解析 在自然语言处理&#xff08;NLP&#xff09;领域&#xff0c;如何让计算机理解人类语言的语义一直是核心挑战。词向量&#xff08;Word Vector&#xff09;&#xff0c;又称词嵌入&…

【Matlab】雷达图/蛛网图

文章目录 一、简介二、安装三、示例四、所有参数说明 一、简介 雷达图&#xff08;Radar Chart&#xff09;又称蛛网图&#xff08;Spider Chart&#xff09;是一种常见的多维数据可视化手段&#xff0c;能够直观地对比多个指标并揭示其整体分布特征。 雷达图以中心点为原点&…

Vue3实现轮播表(表格滚动)

在这之前,写过一篇Vue2实现该效果的博文:vue-seamless-scroll(一个简单的基于vue.js的无缝滚动) 有兴趣也可以去看下,这篇是用vue3实现,其实很简单,目的是方便后面用到直接复制既可以了。 安装: <

安卓开发用到的设计模式(1)创建型模式

安卓开发用到的设计模式&#xff08;1&#xff09;创建型模式 文章目录 安卓开发用到的设计模式&#xff08;1&#xff09;创建型模式1. 单例模式&#xff08;Singleton Pattern&#xff09;2. 工厂模式&#xff08;Factory Pattern&#xff09;3. 抽象工厂模式&#xff08;Abs…

后端开发概念

1. 后端开发概念解析 1.1. 什么是服务器&#xff0c;后端服务 1.1.1. 服务器 服务器是一种提供服务的计算机系统&#xff0c;它可以接收、处理和响应来自其他计算机系统&#xff08;客户端&#xff09;的请求。服务器主要用于存储、处理和传输数据&#xff0c;以便客户端可以…

Spring AI 源码解析:Tool Calling链路调用流程及示例

Tool工具允许模型与一组API或工具进行交互&#xff0c;增强模型功能&#xff0c;主要用于&#xff1a; 信息检索&#xff1a;从外部数据源检索信息&#xff0c;如数据库、Web服务、文件系统或Web搜索引擎等 采取行动&#xff1a;可用于在软件系统中执行特定操作&#xff0c;如…

Spyglass:跨时钟域同步(长延迟信号)

相关阅读 Spyglasshttps://blog.csdn.net/weixin_45791458/category_12828934.html?spm1001.2014.3001.5482 简介 长延迟信号方案用于控制或数据信号跨时钟域同步&#xff0c;该方案将使用quasi_static约束的跨时钟域信号视为已同步&#xff0c;如图1所示。 // test.sgdc q…

Linux云计算训练营笔记day13【CentOS 7 find、vim、vimdiff、ping、wget、curl、RPM、YUM】

Linux云计算训练营笔记day13[CentOS 7 find、vim、vimdiff、ping、wget、curl、RPM、YUM]] 目录 Linux云计算训练营笔记day13[CentOS 7 find、vim、vimdiff、ping、wget、curl、RPM、YUM]]1.find练习2.vim高级使用2.1 命令模式:2.2 插入模式:2.3 末行模式: 3. vimdiff4. ping5.…

网络流量分析工具ntopng的安装与基本使用

网络流量分析工具ntopng的安装与基本使用 一、ntopng基本介绍1.1 ntopng简介1.2 主要特点1.3 使用场景 二、本地环境介绍2.1 本地环境规划2.2 本次实践介绍 三、安装ntopng工具3.1 官网地址3.2 配置软件源3.3 添加软件源3.4 安装ntopng 四、ntopng的基本配置4.1 修改配置文件4.…

数据的获取与读取篇---常见的数据格式JSON

文件格式 假如你有一份想分析的数据文件,获得文件后下一步就是用代码读取它。不同的文件格式有不同的读取方法。所以读取前了解文件格式也很重要。你可能见过非常多的文件格式,例如TXT、MP3、PDF、JPEG等等。 一般可以通过文件的后缀来分辨文件的格式,例如TXT格式,一般保存…

人工智能发展

探秘人工智能领域的热门编程语言与关键知识 在当今科技飞速发展的时代&#xff0c;人工智能已渗透到生活的各个角落&#xff0c;从智能语音助手到精准的推荐系统&#xff0c;从自动驾驶汽车到医疗影像诊断&#xff0c;人工智能正以前所未有的速度改变着世界。而在这背后&#x…

超全GPT-4o 风格提示词案例,持续更新中,附使用方式

本文汇集了各类4o风格提示词的精选案例&#xff0c;从基础指令到复杂任务&#xff0c;从创意写作到专业领域&#xff0c;为您提供全方位的参考和灵感。我们将持续更新这份案例集&#xff0c;确保您始终能够获取最新、最有效的提示词技巧。 让我们一起探索如何通过精心设计的提…

Vue3响应式数据: 深入分析Ref与Reactive

Vue3响应式数据: 深入分析Ref与Reactive 介绍 作为一个流行的前端框架&#xff0c;其响应式数据系统是其核心特性之一。在Vue3中&#xff0c;我们可以使用Ref和Reactive两种方式来创建响应式数据。本文将深入分析Ref与Reactive&#xff0c;帮助读者更好地理解Vue3的响应式数据系…

云计算,大数据,人工智能

1. 云计算&#xff1a;弹性资源与分布式计算 案例&#xff1a;基于AWS EC2的动态资源扩展 场景&#xff1a;电商网站在“双十一”期间流量激增&#xff0c;需要临时扩容服务器资源。 代码&#xff1a;使用AWS Boto3库动态启动EC2实例 import boto3# 创建EC2客户端 ec2 boto…

Linux(7)——进程(概念篇)

一、基本概念 书本上的概念&#xff1a;程序的一个执行实例&#xff0c;正在执行的程序等 基于内核的观点&#xff1a;担当分配系统资源(CPU时间&#xff0c;内存)的实体。 我们知道&#xff0c;我们在写代码的时候&#xff0c;你的代码进行编译链接后生成可执行文件&#xff…