跳转到主内容
趣航编程网 - 趣学编程,启航技术之路!

c++如何使用cmake构建项目_c++ CMakeLists.txt编写与依赖库关联【指南】

CMake是生成构建系统配置的元构建工具,非自动构建工具;其核心是通过CMakeLists.txt声明项目信息、标准与依赖,再生成Makefile或VS解决方案等实际构建文件。 直接说结论:CMake 不是“自动构建工具”,而是“生成构建系统配置的元构建工具”——你写
CMakeLists.txt
的本质,是在告诉 CMake “我有哪些源文件、想生成什么目标、依赖哪些库、用什么编译器选项”,它再据此生成
Makefile
(Linux/ mac OS)或
Visual Studio 解决方案
(Windows)等真正干活的东西。 怎么写最简可用的
CMakeLists.txt
新手常卡在第一行就报错,核心是版本声明 + 项目名 + 最低 C++ 标准这三要素缺一不可:
cmake_minimum_required(VERSION 3.10)
:低于 3.10 会丢失
target_compile_features
等关键功能;3.20+ 更推荐(支持
FetchContent
find_package(... CONFIG)
更健壮)
project(MyApp LANGUAGES CXX)
:必须显式声明
CXX
,否则
add_executable
可能默认当 C 项目处理,导致
std::string
等链接失败
set(CMAKE_CXX_STANDARD 17)
:不设的话默认可能是 C++98,现代库(如
fmt
spdlog
)直接编译不过
cmake_minimum_required(VERSION 3.10) project(MyApp LANGUAGES CXX) set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) add_executable(myapp main.cpp utils.cpp)
如何正确链接第三方库(静态 / 动态 / 头文件-only) 错误写法:
target_link_libraries(myapp /usr/lib/libjsoncpp.a)
—— 路径硬 编码 、无跨平台性、不检查是否存在。 正确做法分三类: 立即学习 “ C++免费学习笔记(深入) ”; 系统级已安装库(如
zlib
OpenSSL
) :用
find_package
+
target_link_libraries
,CMake 自动找头文件路径和库文件 头文件-only 库(如
fmt
range-v3
) :用
find_package(fmt REQUIRED)
target_link_libraries(myapp PRIVATE fmt::fmt)
,PRIVATE 表示仅本 target 使用,不传递给依赖它的其他 target 未系统安装的本地库(如自己写的
libmath.a
) :先
add_library(math STATIC IMPORTED)
,再
set_property(TARGET math PROPERTY IMPORTED_LOCATION ${CMAKE_CURRENT_SOURCE_DIR}/lib/libmath.a)
,最后
target_link_libraries(myapp PRIVATE math)
注意:
target_link_libraries
的作用域(
PUBLIC
/
PRIVATE
/
INTERFACE
)直接影响依赖传递——比如你封装了一个库
mylib
并链接了
boost_filesystem
,又希望使用者包含
mylib
就自动获得
boost_filesystem
的头文件,则需写
target_link_libraries(mylib PUBLIC boost::filesystem)
。 ChatGPT (Windows) ChatGPT Windows 版本优化了系统兼容性与响应速度,提供多任务处理和对话记录管理功能,适用于办公辅助、创意写作、学习辅导和日常问答。它能帮助用户快速生成文稿、整理资料和高效获取信息,为个人和团队提供稳定、流畅的生产力体验。 下载 常见报错与绕过陷阱 以下错误出现频率极高,且原因隐蔽:
Cannot find -lxxx
:不是库没装,而是
find_package(xxx)
成功但没用
target_link_libraries
关联;或用了
find_library
却忘了
target_link_libraries(... ${XXX_LIBRARY})
undefined reference to `xxxx' (from std::filesystem)
:Linux 下
std::filesystem
需要显式链接
-lstdc++fs
,加
target_link_libraries(myapp PRIVATE stdc++fs)
(Clang/GCC 9+)
CMake Error at CMakeLists.txt:12 (add_executable): No SOURCES given
add_executable
后没跟任何源文件,或变量为空(如
set(SRCS)
写了但没赋值),建议用
message(STATUS "SRCS = ${SRCS}")
调试 Windows 下链接
.lib
但运行时报
dll not found
:动态库路径没进
PATH
,开发期可在 CMake 中加
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
并把 DLL 拷到该目录 依赖管理进阶:用
FetchContent
嵌入子项目 不想手动下载/编译
gtest
spdlog
?CMake 3.14+ 提供
FetchContent
,直接从 Git 或 URL 拉取并作为子项目构建:
include(FetchContent) FetchContent_Declare( spdlog GIT_REPOSITORY https://github.com/gabime/spdlog.git GIT_TAG v1.12.0 ) FetchContent_MakeAvailable(spdlog) add_executable(myapp main.cpp) target_link_libraries(myapp PRIVATE spdlog::spdlog)
注意:
FetchContent_MakeAvailable
会自动调用
add_subdirectory
,所以不用再写一遍;但它会把子项目所有 target 暴露到当前作用域,命名冲突时可用
set(spdlog_SOURCE_DIR ${CMAKE_BINARY_DIR}/_deps/spdlog-src)
控制路径。 真正难的从来不是语法,而是搞清「谁负责提供头文件路径」「谁负责链接符号」「谁负责传播编译定义」——这三个问题理不清,
target_include_directories
target_compile_definitions
target_link_libraries
就永远像在碰运气。

相关文章