CMake 入门
最小 CMakeLists.txt
cmake_minimum_required(VERSION 3.16)
project(MyApp VERSION 1.0 LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
add_executable(myapp main.cpp)
构建三步:
mkdir build && cd build
cmake .. # 生成构建系统
cmake --build . # 编译
target 管理(Modern CMake 核心)
# 可执行文件
add_executable(myapp main.cpp)
# 静态库
add_library(mylib STATIC src/lib.cpp)
# 动态库
add_library(mylib SHARED src/lib.cpp)
# 头文件库(header-only)
add_library(mylib INTERFACE)
target_include_directories(mylib INTERFACE include/)
# 关键:全部用 target_* 命令,不用全局 set
target_include_directories(myapp PRIVATE include/)
target_link_libraries(myapp PRIVATE mylib)
target_compile_definitions(myapp PRIVATE VERSION="1.0")
target_compile_options(myapp PRIVATE -Wall -Wextra)
PRIVATE / PUBLIC / INTERFACE
| 关键字 | 自己用 | 依赖者也用 | 场景 |
|---|---|---|---|
PRIVATE | ✅ | ❌ | 内部实现细节 |
PUBLIC | ✅ | ✅ | 头文件也需要的 |
INTERFACE | ❌ | ✅ | header-only 库 |
# mylib 的头文件里用了 Qt::Core → 依赖者也必须能 include Qt
target_link_libraries(mylib PUBLIC Qt6::Core)
# mylib.cpp 里用了 boost → 只有 mylib 需要链接
target_link_libraries(mylib PRIVATE Boost::filesystem)
多目录项目
myapp/
├── CMakeLists.txt
├── src/
│ ├── CMakeLists.txt
│ └── main.cpp
└── lib/
├── CMakeLists.txt
└── mylib.cpp
# 根 CMakeLists.txt
cmake_minimum_required(VERSION 3.16)
project(MyApp)
add_subdirectory(lib)
add_subdirectory(src)
# lib/CMakeLists.txt
add_library(mylib mylib.cpp)
target_include_directories(mylib PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
# src/CMakeLists.txt
add_executable(myapp main.cpp)
target_link_libraries(myapp PRIVATE mylib)
find_package
# Qt
find_package(Qt6 REQUIRED COMPONENTS Core Widgets Sql)
target_link_libraries(myapp PRIVATE Qt6::Core Qt6::Widgets Qt6::Sql)
# OpenCV
find_package(OpenCV REQUIRED)
target_link_libraries(myapp PRIVATE ${OpenCV_LIBS})
# 自定义库(非标准路径)
find_package(mylib REQUIRED PATHS /opt/custom/lib/cmake)
条件编译
option(ENABLE_TESTS "Build tests" ON)
if(ENABLE_TESTS)
enable_testing()
add_subdirectory(tests)
endif()
# 平台判断
if(WIN32)
target_sources(myapp PRIVATE win_specific.cpp)
elseif(APPLE)
target_sources(myapp PRIVATE mac_specific.cpp)
else()
target_sources(myapp PRIVATE linux_specific.cpp)
endif()
Qt 集成
cmake_minimum_required(VERSION 3.16)
project(PulseQt VERSION 1.0 LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_AUTOMOC ON) # 自动处理 Q_OBJECT moc
set(CMAKE_AUTORCC ON) # 自动处理 .qrc
set(CMAKE_AUTOUIC ON) # 自动处理 .ui
find_package(Qt6 REQUIRED COMPONENTS Core Widgets Sql SerialPort)
add_executable(pulseqt
main.cpp
mainwindow.h mainwindow.cpp
)
target_link_libraries(pulseqt PRIVATE
Qt6::Core
Qt6::Widgets
Qt6::Sql
Qt6::SerialPort
)
常见变量
${CMAKE_SOURCE_DIR} # 顶层 CMakeLists.txt 所在
${CMAKE_BINARY_DIR} # build 目录
${CMAKE_CURRENT_SOURCE_DIR} # 当前 CMakeLists.txt 所在
${PROJECT_NAME} # 项目名
${PROJECT_VERSION} # 版本号
# 安装
install(TARGETS myapp DESTINATION bin)
install(FILES config.json DESTINATION etc/myapp)
调试 CMake
message(STATUS "Qt version: ${Qt6_VERSION}") # 信息
message(WARNING "Something might be wrong") # 警告
message(FATAL_ERROR "Cannot continue") # 致命错误
# 打印所有变量
get_cmake_property(_vars VARIABLES)
foreach(_var ${_vars})
message(STATUS "${_var}=${${_var}}")
endforeach()