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

CMake对于C++项目来说,本质上是一个构建系统的生成器,它本身不直接编译代码,而是根据你定义的规则,生成特定平台(如Windows上的Visual Studio项目文件、Linux上的Makefile)的构建脚本。掌握CMake,意味着你可以在任何支持的平台上,用一套统一的描述文件来构建你的C++应用,极大地简化了跨平台开发的复杂性,让项目管理变得高效且可预测。入门它的关键在于理解
CMakeLists.txt
要使用CMake构建一个C++项目,我们通常从一个简单的
CMakeLists.txt
首先,你需要确保你的系统上安装了CMake。如果你在Linux上,通常可以通过包管理器安装,比如
sudo apt install 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
配置阶段 (Configure): 创建一个构建目录(通常建议在项目根目录外或内部创建一个
build
mkdir build cd build cmake .. # 这里的“..”告诉CMake去上一级目录寻找CMakeLists.txt
这一步,CMake会根据你的操作系统和环境,生成相应的构建文件。比如在Linux上会生成
Makefile
.sln
.vcxproj
构建阶段 (Build):
cmake --build . # 使用CMake的统一构建命令来编译项目
或者,如果你知道生成的构建系统,也可以直接使用它们。比如在Linux上:
make
.sln
运行可执行文件: 编译成功后,在
build
HelloWorld
./HelloWorld # Linux/macOS HelloWorld.exe # Windows
这就是CMake构建项目的基本流程。对我来说,最开始接触CMake时,这种“配置”和“构建”分离的思想确实需要一点时间去适应,但一旦理解,你会发现它带来的灵活性和跨平台能力是无价的。
说实话,C++项目的构建一直是个老大难问题。我个人觉得,C++的生态系统里,没有像Java的Maven或Python的pip那样一个“包罗万象”的构建和包管理工具。这导致了许多开发者在项目初期就陷入构建系统的泥潭。CMake正是在这种背景下应运而生,它主要解决了C++项目构建中的几个核心痛点:
CMakeLists.txt
find_package()
FetchContent
CMakeLists.txt
在我看来,CMake就像一个翻译官,它把我们用一种高级语言(
CMakeLists.txt
CMakeLists.txt
cmake_minimum_required(VERSION <major>.<minor>)
cmake_minimum_required(VERSION 3.10)
project(<projectname> [LANGUAGES] [VERSION] [DESCRIPTION]...)
CXX
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> ...])
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...])
target_include_directories(my_app PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include)set(<variable> <value> [CACHE <type> <docstring> [FORCE]])
set(CMAKE_CXX_STANDARD 17)
add_subdirectory(source_dir [binary_dir] [EXCLUDE_FROM_ALL])
CMakeLists.txt
add_subdirectory(src/core)
这些指令构成了CMake项目的基础骨架。掌握它们,你就能开始构建各种规模的C++项目了。
处理第三方库依赖,一直是C++开发中绕不开的痛点。CMake在这方面提供了多种策略,从简单到复杂,可以应对不同的场景。我个人觉得,选择哪种策略,很大程度上取决于库的性质、你的项目需求以及团队的偏好。
find_package()
find_package()
/usr/local
/usr
<PackageName>_FOUND
<PackageName>_INCLUDE_DIRS
<PackageName>_LIBRARIES
find_package(Qt5 COMPONENTS Core Widgets REQUIRED) # 查找Qt5的Core和Widgets模块,如果找不到则报错 target_link_libraries(my_app PRIVATE Qt5::Core Qt5::Widgets)
add_subdirectory()
CMakeLists.txt
add_subdirectory()
add_subdirectory(libs/mylib) # 假设mylib库的源代码在libs/mylib目录下 target_link_libraries(my_app PRIVATE mylib)
FetchContent
原理:
FetchContent
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)
手动指定路径和链接:
原理: 这是最原始但有时也是最灵活的方式。通过
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()
以上就是c++如何使用CMake构建项目_c++ CMake跨平台构建系统入门的详细内容,更多请关注php中文网其它相关文章!
c++怎么学习?c++怎么入门?c++在哪学?c++怎么学才快?不用担心,这里为大家提供了c++速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号