0

0

c++如何使用CMake构建项目_c++ CMake跨平台构建系统入门

冰火之心

冰火之心

发布时间:2025-09-22 19:31:01

|

605人浏览过

|

来源于php中文网

原创

cmake通过cmakelists.txt文件生成跨平台构建脚本,解决c++项目在不同系统上编译配置复杂、依赖管理困难、项目结构不统一等痛点,实现“一次编写,到处构建”。

c++如何使用cmake构建项目_c++ cmake跨平台构建系统入门

CMake对于C++项目来说,本质上是一个构建系统的生成器,它本身不直接编译代码,而是根据你定义的规则,生成特定平台(如Windows上的Visual Studio项目文件、Linux上的Makefile)的构建脚本。掌握CMake,意味着你可以在任何支持的平台上,用一套统一的描述文件来构建你的C++应用,极大地简化了跨平台开发的复杂性,让项目管理变得高效且可预测。入门它的关键在于理解

CMakeLists.txt
文件的编写逻辑,以及基本的配置和构建命令。

解决方案

要使用CMake构建一个C++项目,我们通常从一个简单的

CMakeLists.txt
文件开始。这文件是CMake的“食谱”,告诉它项目有哪些源文件、需要哪些库、编译时要用什么选项等等。

首先,你需要确保你的系统上安装了CMake。如果你在Linux上,通常可以通过包管理器安装,比如

sudo apt install cmake
。Windows用户可以从CMake官网下载安装包。

以一个最简单的“Hello World”项目为例: 假设你有一个

main.cpp
文件:

// main.cpp
#include <iostream>

int main() {
    std::cout << "Hello from CMake!" << std::endl;
    return 0;
}

main.cpp
同级目录下创建一个名为
CMakeLists.txt
的文件,内容如下:

立即学习C++免费学习笔记(深入)”;

# CMakeLists.txt
cmake_minimum_required(VERSION 3.10) # 声明所需的最低CMake版本,这是个好习惯

project(HelloWorld CXX) # 定义项目名称为HelloWorld,并指定语言为C++

add_executable(HelloWorld main.cpp) # 添加一个可执行目标,名称为HelloWorld,源文件是main.cpp

然后,在终端或命令行中,进入到包含

CMakeLists.txt
main.cpp
的目录。

  1. 配置阶段 (Configure): 创建一个构建目录(通常建议在项目根目录外或内部创建一个

    build
    子目录,保持源文件整洁)。

    mkdir build
    cd build
    cmake .. # 这里的“..”告诉CMake去上一级目录寻找CMakeLists.txt

    这一步,CMake会根据你的操作系统和环境,生成相应的构建文件。比如在Linux上会生成

    Makefile
    ,在Windows上如果你有Visual Studio,可能会生成
    .sln
    .vcxproj
    文件。

  2. 构建阶段 (Build):

    cmake --build . # 使用CMake的统一构建命令来编译项目

    或者,如果你知道生成的构建系统,也可以直接使用它们。比如在Linux上:

    make
    ;在Windows上用Visual Studio打开生成的
    .sln
    文件进行编译。

  3. 运行可执行文件: 编译成功后,在

    build
    目录下(或其子目录,取决于你的CMake版本和配置),你会找到
    HelloWorld
    可执行文件。

    ./HelloWorld # Linux/macOS
    HelloWorld.exe # Windows

这就是CMake构建项目的基本流程。对我来说,最开始接触CMake时,这种“配置”和“构建”分离的思想确实需要一点时间去适应,但一旦理解,你会发现它带来的灵活性和跨平台能力是无价的。

为什么C++项目尤其需要CMake,它解决了哪些痛点?

说实话,C++项目的构建一直是个老大难问题。我个人觉得,C++的生态系统里,没有像Java的Maven或Python的pip那样一个“包罗万象”的构建和包管理工具。这导致了许多开发者在项目初期就陷入构建系统的泥潭。CMake正是在这种背景下应运而生,它主要解决了C++项目构建中的几个核心痛点:

  • 跨平台兼容性难题: 这是CMake最显著的优势。没有CMake,你可能需要为Windows编写Visual Studio项目文件,为Linux编写Makefile,为macOS编写Xcode项目文件,这些工作量巨大且容易出错。CMake通过一套抽象的
    CMakeLists.txt
    文件,生成所有这些平台特定的构建脚本,让你“一次编写,到处构建”,极大地降低了维护成本。我记得以前为了让一个项目在Windows和Linux上都能跑,光是构建配置就折腾了我好几天。
  • 复杂依赖管理: 现代C++项目很少是独立的,它们通常会依赖多个第三方库(如Boost、OpenCV、Qt等)。手动配置这些库的头文件路径、库文件路径以及链接顺序,简直是一场噩梦。CMake提供了
    find_package()
    等机制,能够智能地查找和链接系统上的库,甚至可以通过
    FetchContent
    模块直接从网络上获取和构建依赖,让依赖管理变得相对优雅。
  • 项目结构标准化: CMake鼓励一种标准化的项目结构和构建流程。当你接手一个使用CMake的项目时,你总能找到
    CMakeLists.txt
    ,并且大致知道它会如何被构建。这对于团队协作和新成员快速上手非常有帮助,避免了每个项目都有自己一套奇葩构建方式的混乱局面。
  • 自动化构建过程: 从编译、链接到安装,甚至运行测试,CMake都能通过简单的命令统一管理。它将这些繁琐的手动步骤自动化,减少了人为错误,提高了开发效率。

在我看来,CMake就像一个翻译官,它把我们用一种高级语言(

CMakeLists.txt
)描述的构建意图,翻译成不同平台都能理解的“方言”(Makefile、VS项目文件),从而实现了构建过程的统一和简化。

CMakeLists.txt文件通常包含哪些关键指令,以及它们的作用?

CMakeLists.txt
是CMake的灵魂,它由一系列指令(commands)和变量(variables)组成。理解这些核心指令是掌握CMake的基础。我个人觉得,虽然指令很多,但有几个是无论大小项目都离不开的:

  • cmake_minimum_required(VERSION <major>.<minor>)
    :

    • 作用: 指定项目所需的最低CMake版本。这很重要,因为不同版本的CMake可能会有不同的行为或提供新的功能。声明最低版本可以确保你的项目在未来的CMake版本中也能以预期的方式工作,同时避免在过旧的CMake版本上尝试构建。
    • 示例:
      cmake_minimum_required(VERSION 3.10)
  • project(<projectname> [LANGUAGES] [VERSION] [DESCRIPTION]...)
    :

    • 作用: 定义项目的名称,这是CMake内部引用项目的主要标识符。你还可以指定项目使用的编程语言(如
      CXX
      代表C++,
      C
      代表C),以及版本、描述等元数据。
    • 示例:
      project(MyAwesomeApp VERSION 1.0 LANGUAGES CXX)
  • add_executable(<name> [source1] [source2] ...)
    :

    • 作用: 创建一个可执行目标。
      name
      是生成的可执行文件的名称,后面跟着构成这个可执行文件的所有源文件(
      .cpp
      ,
      .c
      等)。
    • 示例:
      add_executable(my_app main.cpp helper.cpp)
  • add_library(<name> [STATIC | SHARED | MODULE] [source1] [source2] ...)
    :

    • 作用: 创建一个库目标。你可以指定它是静态库(
      STATIC
      ,如
      .a
      .lib
      )、动态库(
      SHARED
      ,如
      .so
      .dll
      )还是模块库(
      MODULE
      ,用于插件)。
    • 示例:
      add_library(my_lib STATIC util.cpp math.cpp)
  • target_link_libraries(<target> [PUBLIC|PRIVATE|INTERFACE] <item1> [<item2> ...])
    :

    OneAI
    OneAI

    将生成式AI技术打包为API,整合到企业产品和服务中

    下载
    • 作用: 将库链接到指定的目标(可执行文件或另一个库)。这是告诉编译器在链接阶段需要哪些外部库的关键指令。
      PUBLIC
      ,
      PRIVATE
      ,
      INTERFACE
      关键字定义了链接的可见性,这对于构建复杂的库依赖关系非常有用。
    • 示例:
      target_link_libraries(my_app PRIVATE my_lib)
      target_link_libraries(my_app PUBLIC Qt5::Core Qt5::Widgets)
  • include_directories([AFTER|BEFORE] [SYSTEM] dir1 [dir2 ...])
    :

    • 作用: 指定编译器查找头文件的目录。这是告诉编译器去哪里找到你
      #include
      的那些文件。虽然现在更推荐使用
      target_include_directories
      ,但这个指令在一些旧项目或简单场景中仍然常见。
    • 示例:
      include_directories(include)
  • target_include_directories(<target> [PUBLIC|PRIVATE|INTERFACE] [items...])
    :

    • 作用: 为特定的目标添加头文件搜索路径。这是现代CMake推荐的方式,因为它将头文件路径与目标绑定,避免了全局污染,使得依赖关系更加清晰。
    • 示例:
      target_include_directories(my_app PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include)
  • set(<variable> <value> [CACHE <type> <docstring> [FORCE]])
    :

    • 作用: 设置一个CMake变量。变量可以存储字符串、列表等,用于配置构建选项或路径。
    • 示例:
      set(CMAKE_CXX_STANDARD 17)
      设置C++标准为C++17。
  • add_subdirectory(source_dir [binary_dir] [EXCLUDE_FROM_ALL])
    :

    • 作用: 将一个子目录添加到构建中。当项目有多个模块或组件时,每个子目录可以有自己的
      CMakeLists.txt
      ,然后通过这个指令将其包含到主构建中,这对于大型项目的模块化管理非常有效。
    • 示例:
      add_subdirectory(src/core)

这些指令构成了CMake项目的基础骨架。掌握它们,你就能开始构建各种规模的C++项目了。

面对复杂的第三方库依赖,CMake有哪些高效的管理策略?

处理第三方库依赖,一直是C++开发中绕不开的痛点。CMake在这方面提供了多种策略,从简单到复杂,可以应对不同的场景。我个人觉得,选择哪种策略,很大程度上取决于库的性质、你的项目需求以及团队的偏好。

  1. find_package()
    :查找系统已安装的库

    • 原理: 这是CMake最常用且推荐的方式。
      find_package()
      指令会尝试在系统预定义的路径(如
      /usr/local
      ,
      /usr
      )或由环境变量指定的路径中查找特定的库。如果找到,它会设置一系列变量(如
      <PackageName>_FOUND
      <PackageName>_INCLUDE_DIRS
      <PackageName>_LIBRARIES
      ),供你的项目使用。许多流行的库(如Qt、Boost、OpenCV)都提供了CMake查找模块。
    • 优点: 简洁高效,如果库已安装在系统上,配置非常简单。
    • 缺点: 依赖于用户手动安装库,且不同系统或版本可能导致查找失败。
    • 示例:
      find_package(Qt5 COMPONENTS Core Widgets REQUIRED) # 查找Qt5的Core和Widgets模块,如果找不到则报错
      target_link_libraries(my_app PRIVATE Qt5::Core Qt5::Widgets)
  2. add_subdirectory()
    :将依赖作为子项目构建

    • 原理: 如果第三方库的源代码在你项目的一个子目录中,并且它也有自己的
      CMakeLists.txt
      ,你就可以使用
      add_subdirectory()
      将其作为你项目的一部分来构建。
    • 优点: 确保了依赖库和你的项目使用相同的编译器和构建选项,版本控制也更方便(直接把库源码放在你的仓库里)。
    • 缺点: 增加了项目仓库的大小,且如果库很大,每次构建都会编译它,耗时。
    • 示例:
      add_subdirectory(libs/mylib) # 假设mylib库的源代码在libs/mylib目录下
      target_link_libraries(my_app PRIVATE mylib)
  3. FetchContent
    (现代CMake推荐):运行时获取并构建依赖

    • 原理:

      FetchContent
      是CMake 3.11+引入的强大模块,它允许CMake在配置阶段自动从Git仓库、URL等位置下载第三方库的源代码,然后将其作为子项目添加到你的构建中。它结合了
      find_package
      的便利性和
      add_subdirectory
      的可靠性。

    • 优点: 自动化程度高,无需用户预先安装,版本控制精确(通过Git commit hash),解决了跨平台和环境差异问题。

    • 缺点: 需要网络连接,初次配置可能稍显复杂,且下载和构建时间会增加。

    • 示例: (以一个简单的fmt库为例)

      include(FetchContent)
      FetchContent_Declare(
        fmt_lib
        GIT_REPOSITORY https://github.com/fmtlib/fmt.git
        GIT_TAG        10.1.1 # 或一个具体的commit hash
      )
      FetchContent_MakeAvailable(fmt_lib)
      
      # 现在fmt库已经作为子项目被添加,可以直接链接它的目标
      add_executable(my_app main.cpp)
      target_link_libraries(my_app PRIVATE fmt::fmt)
  4. 手动指定路径和链接:

    • 原理: 这是最原始但有时也是最灵活的方式。通过

      find_library()
      find_path()
      指令手动查找库文件和头文件,然后通过
      target_include_directories()
      target_link_libraries()
      手动链接。

    • 优点: 适用于那些没有提供CMake查找模块的冷门库,或者你对库的安装路径有特殊要求时。

    • 缺点: 繁琐,容易出错,且不具备跨平台通用性。

    • 示例:

      find_path(MYLIB_INCLUDE_DIR NAMES mylib.h HINTS /opt/mylib/include /usr/local/include)
      find_library(MYLIB_LIBRARY NAMES mylib HINTS /opt/mylib/lib /usr/local/lib)
      
      if(MYLIB_INCLUDE_DIR AND MYLIB_LIBRARY)
          target_include_directories(my_app PRIVATE ${MYLIB_INCLUDE_DIR})
          target_link_libraries(my_app PRIVATE ${MYLIB_LIBRARY})
      else()
          message(FATAL_ERROR "MyLib not found!")
      endif()

我个人在项目中,会优先考虑

find_package()
,如果不行,并且库比较小或者我需要精确控制其版本,会倾向于使用
FetchContent
。对于大型且需要独立构建的库,
add_subdirectory()
也是个不错的选择。手动指定路径通常是最后的手段,只在实在没办法时才会用。关键是根据项目的实际情况,灵活选择最适合的策略。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
视频后缀名都有哪些
视频后缀名都有哪些

视频后缀名都有avi、mpg、mpeg、rm、rmvb、flv、wmv、mov、mkv、ASF、M1V、M2V、MPE、QT、VOB、RA、RMJ、RMS、RAM、等等。更多关于视频后缀名的相关知识,详情请看本专题下面的文章,php中文网欢迎大家前来学习。

3830

2023.10.31

C++ Qt图形开发
C++ Qt图形开发

本专题专注于 C++ Qt框架在图形界面开发中的应用,系统讲解窗口设计、信号与槽机制、界面布局、事件处理、数据库连接与跨平台打包等核心技能,通过多个桌面应用项目实战,帮助学员快速掌握 Qt 框架并独立完成跨平台GUI软件的开发。

75

2025.08.15

C++ 图形界面开发基础(Qt方向)
C++ 图形界面开发基础(Qt方向)

本专题系统讲解 使用 C++ 与 Qt 进行图形界面(GUI)开发的核心技能,内容涵盖 Qt 项目结构、窗口组件、信号与槽机制、事件处理、布局管理、资源管理,以及跨平台编译与打包流程。通过多个小型桌面应用实战案例,帮助学习者掌握从界面设计到功能实现的完整 GUI 开发能力。

100

2025.12.05

pip安装使用方法
pip安装使用方法

安装步骤:1、确保Python已经正确安装在您的计算机上;2、下载“get-pip.py”脚本;3、按下Win + R键,然后输入cmd并按下Enter键来打开命令行窗口;4、在命令行窗口中,使用cd命令切换到“get-pip.py”所在的目录;5、执行安装命令;6、验证安装结果即可。大家可以访问本专题下的文章,了解pip安装使用方法的更多内容。

372

2023.10.09

更新pip版本
更新pip版本

更新pip版本方法有使用pip自身更新、使用操作系统自带的包管理工具、使用python包管理工具、手动安装最新版本。想了解更多相关的内容,请阅读专题下面的文章。

430

2024.12.20

pip设置清华源
pip设置清华源

设置方法:1、打开终端或命令提示符窗口;2、运行“touch ~/.pip/pip.conf”命令创建一个名为pip的配置文件;3、打开pip.conf文件,然后添加“[global];index-url = https://pypi.tuna.tsinghua.edu.cn/simple”内容,这将把pip的镜像源设置为清华大学的镜像源;4、保存并关闭文件即可。

793

2024.12.23

python升级pip
python升级pip

本专题整合了python升级pip相关教程,阅读下面的文章了解更多详细内容。

369

2025.07.23

Java Maven专题
Java Maven专题

本专题聚焦 Java 主流构建工具 Maven 的学习与应用,系统讲解项目结构、依赖管理、插件使用、生命周期与多模块项目配置。通过企业管理系统、Web 应用与微服务项目实战,帮助学员全面掌握 Maven 在 Java 项目构建与团队协作中的核心技能。

0

2025.09.15

Golang 测试体系与代码质量保障:工程级可靠性建设
Golang 测试体系与代码质量保障:工程级可靠性建设

Go语言测试体系与代码质量保障聚焦于构建工程级可靠性系统。本专题深入解析Go的测试工具链(如go test)、单元测试、集成测试及端到端测试实践,结合代码覆盖率分析、静态代码扫描(如go vet)和动态分析工具,建立全链路质量监控机制。通过自动化测试框架、持续集成(CI)流水线配置及代码审查规范,实现测试用例管理、缺陷追踪与质量门禁控制,确保代码健壮性与可维护性,为高可靠性工程系统提供质量保障。

48

2026.02.28

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
PostgreSQL 教程
PostgreSQL 教程

共48课时 | 10万人学习

Git 教程
Git 教程

共21课时 | 4万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号