起手式
1
2
3
4
5
|
cmake_minimum_required(VERSION 3.21.0)
project(myproj VERSION 0.1.0 LANGUAGES C CXX)
add_executable(myapp main.cpp ...)#编译为myapp.exe
add_library(test STATIC test.hpp)#编译为静态库
add_library(math SHARED main.hpp)#编译为动态库
|
生成配置
1
2
3
4
5
6
7
8
9
|
mkdir cmake-build
cd cmake-build
cmake ..
cmake --build .
//启用多线程
cmake --build . -- -m:4
cmake --build . -- -j:4
|
build.sh
1
2
3
4
5
6
7
|
set -e
mkdir -p build
cd build
cmake ..
cmake --build . --target myapp --config Release
|
基本用法
1
2
3
4
5
|
set(BUILD_SHARED_LIBS ON) #设置bool值
message(STATUS/NOTICE/FATAL_ERROR "BUILD_SHARED_LIBS=${BUILD_SHARED_LIBS}")
#给布尔变量设置默认值。参数:变量的变量名,注释,默认值。
option(BUILD_LIBS "Compile sources into a library" OFF)
#打印变量
|
message(“This is the NOTICE message”)
This is the NOTICE message
message(STATUS “This is the STATUS message”)
– This is the STATUS message
message(FATAL_ERROR “This is the FATAL_ERROR message”)
CMake Error at CMakeLists.txt:5 (message):
This is the FATAL_ERROR message
– Configuring incomplete, errors occurred!
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
list(APPEND sources main.cpp test.hpp tes.cpp)
add_executable(myapp ${sources}) #列举
#访问环境变量
if(DEFINED ENV{TEMP})
message("TEMP=$ENV{TEMP}")
endif()
#条件变量
if(BUILD_LIBS)
...
else()
...
endif()
#布尔表达式
NOT BUILD_LIBS 取反
A AND B 且
A OR B 或
A STREQUAL B 两个字符串 A 和 B 相等
EXIST PATH 路径为 PATH 的文件或目录存在
DEFINED VAR 变量 VAR 有定义
|
添加附加依赖项
1
2
3
4
5
6
7
8
9
10
11
|
target_link_libraries(myapp PRIVATE math)
target_include_directories(myapp PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/include")
事实上:
add_executable(myapp main.cpp test.cpp)
等于
add_executable(myapp main.cpp)
target_link_libraries(myapp PRIVATE test)
如果子模块中有定义的宏
target_compile_definitions(module PRIVATE 宏名)
|
生成动态库
1
2
3
4
5
6
|
//要在需生成动态库的模块中配置
#ifdef EXPORT
#define DECL_API __declspec(dllexport)
#else
#define DECL_API __declspec(dllimport)
#endif
|
模板
导出成静态库
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
|
set(MODULE_NAME "my_static_lib" CACHE STRING "静态库模块名称")
# 收集 .c/.cpp 源文件
file(GLOB_RECURSE MODULE_SOURCES
${CMAKE_CURRENT_SOURCE_DIR}/*.c
${CMAKE_CURRENT_SOURCE_DIR}/*.cpp
)
# 收集 .h/.hpp 头文件
file(GLOB_RECURSE MODULE_HEADERS
${CMAKE_CURRENT_SOURCE_DIR}/*.h
${CMAKE_CURRENT_SOURCE_DIR}/*.hpp
)
if(NOT MODULE_SOURCES)
message(WARNING "模块 ${MODULE_NAME} 未找到任何 .c/.cpp 源文件,跳过静态库构建!")
return()
endif()
add_library(${MODULE_NAME} STATIC
${MODULE_SOURCES}
${MODULE_HEADERS}
)
# 5. 设置静态库的属性
# 5.1 设置库的输出目录
set_target_properties(${MODULE_NAME} PROPERTIES
ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib # 静态库输出到 build/lib
LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib # 动态库(此处用不到,仅预留)
RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin # 可执行文件(此处用不到,仅预留)
)
# 设置头文件搜索路径
target_include_directories(${MODULE_NAME}
PUBLIC # PUBLIC:上层可继承该头文件路径;PRIVATE:仅本模块内部使用
${CMAKE_CURRENT_SOURCE_DIR} # 当前目录作为头文件根路径
)
# target_compile_options(${MODULE_NAME} PRIVATE -Wall -Wextra -O2)
# 链接其他依赖库(如果本模块依赖其他库,如:pthread、fmt 等)
# target_link_libraries(${MODULE_NAME} PRIVATE pthread fmt)
# 打印信息
message(STATUS "模块 ${MODULE_NAME} 构建配置:")
message(STATUS " - 源文件数量:${CMAKE_ARGC}")
list(LENGTH MODULE_SOURCES SRC_COUNT)
message(STATUS " - 源文件数量:${SRC_COUNT}")
message(STATUS " - 头文件数量:${CMAKE_ARGC}")
list(LENGTH MODULE_HEADERS HDR_COUNT)
message(STATUS " - 头文件数量:${HDR_COUNT}")
message(STATUS " - 输出路径:${CMAKE_BINARY_DIR}/lib")
|
上层使用
1
2
3
4
5
6
|
# 1. 添加模块子目录(会自动执行模块内的 CMakeLists.txt)
add_subdirectory(my_module)
# 2. 链接静态库到目标(如可执行程序)
add_executable(my_app main.cpp)
target_link_libraries(my_app PRIVATE my_static_lib) # 链接模块静态库
|