cmake在复杂项目的应用-实战

  • ~5.99K 字
  1. 1. cmake 创建静态library
  2. 2. cmake 项目解析:stm32cubemx
  3. 3. vscode 配置cmake为代码提示和include
  4. 4. cmake options 的使用,以及vscode里配置
    1. 4.1. 更改options的值

cmake使用指南,.cmake文件编写与使用,CMakeLists.txt文件编写与实践

cmake 创建静态library

创建一个嵌入式静态lib库,uart_device库为例,实现外部配置平台,内部自动链接平台c文件。目前库以及对应的此文档待更新

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
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
cmake_minimum_required(VERSION 3.10)
project(uart_device_library VERSION 1.0.0 LANGUAGES C)

# 设置C标准
set(CMAKE_C_STANDARD 11)
set(CMAKE_C_STANDARD_REQUIRED ON)
set(CMAKE_C_EXTENSIONS OFF)

# 项目选项
option(BUILD_EXAMPLES "Build examples" OFF)

# 平台选择
set(PLATFORM "" CACHE STRING "Target platform (linux, freertos, stm32_hal, windows)")
set_property(CACHE PLATFORM PROPERTY STRINGS linux freertos stm32_hal windows)

## 顶层cmakelists配置该选项请用:set(PLATFORM "stm32_hal" CACHE STRING "Target platform" FORCE)

if(NOT PLATFORM)
message(FATAL_ERROR "Please specify platform with -DPLATFORM=<platform>")
endif()

# 平台特定的配置
if(PLATFORM STREQUAL "linux")
set(PLATFORM_DIR "linux")
set(PLATFORM_DEFINES "UART_PLATFORM_LINUX")

# Linux特定依赖
find_package(Threads REQUIRED)
find_library(RT_LIB rt)

elseif(PLATFORM STREQUAL "freertos")
set(PLATFORM_DIR "freertos")
set(PLATFORM_DEFINES "UART_PLATFORM_FREERTOS")

# FreeRTOS配置 - 需要用户提供路径
set(FREERTOS_PATH "" CACHE PATH "Path to FreeRTOS source")
if(NOT FREERTOS_PATH)
message(WARNING "FREERTOS_PATH not set. You may need to set include directories manually")
endif()

elseif(PLATFORM STREQUAL "stm32_hal")
set(PLATFORM_DIR "stm32_hal")
set(PLATFORM_DEFINES "UART_PLATFORM_STM32_HAL")

elseif(PLATFORM STREQUAL "windows")
set(PLATFORM_DIR "windows")
set(PLATFORM_DEFINES "UART_PLATFORM_WINDOWS")

# Windows特定配置
add_definitions(-D_WIN32_WINNT=0x0601) # Windows 7 or later
else()
message(FATAL_ERROR "Unsupported platform: ${PLATFORM}")
endif()

message(STATUS "Building for platform: ${PLATFORM}")

# 库源文件
set(LIB_SOURCES
src/uart_device.c
src/uart_queue.c
platform/${PLATFORM_DIR}/${PLATFORM_DIR}_uart.c
)

# 添加同步实现(如果存在)
if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/platform/${PLATFORM_DIR}/${PLATFORM_DIR}_sync.c")
list(APPEND LIB_SOURCES
platform/${PLATFORM_DIR}/${PLATFORM_DIR}_sync.c
)
endif()

# 添加库
add_library(uart_device STATIC ${LIB_SOURCES})

# 设置目标属性
target_include_directories(uart_device PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:include>
)

target_include_directories(uart_device PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/include
${CMAKE_CURRENT_SOURCE_DIR}/src
${CMAKE_CURRENT_SOURCE_DIR}/platform/${PLATFORM_DIR}
)

# 编译定义
target_compile_definitions(uart_device PRIVATE ${PLATFORM_DEFINES})
if(ENABLE_DEBUG_LOG)
target_compile_definitions(uart_device PRIVATE UART_DEBUG_LOG)
endif()

# 平台特定链接库
if(PLATFORM STREQUAL "linux")
target_link_libraries(uart_device PRIVATE Threads::Threads)
if(RT_LIB)
target_link_libraries(uart_device PRIVATE ${RT_LIB})
endif()

elseif(PLATFORM STREQUAL "windows")
target_link_libraries(uart_device PRIVATE setupapi)

elseif(PLATFORM STREQUAL "freertos")
# 添加FreeRTOS包含目录
if(FREERTOS_PATH)
target_include_directories(uart_device PRIVATE
${FREERTOS_PATH}/include
)
else()
find_library(freertos_kernel ${CMAKE_SOURCE_DIR})
target_link_libraries(uart_device PRIVATE freertos_kernel)
endif()

elseif(PLATFORM STREQUAL "stm32_hal")
find_library(stm32cubemx ${CMAKE_SOURCE_DIR})
target_link_libraries(uart_device PRIVATE
stm32cubemx
)
endif()

# 添加示例程序
if(BUILD_EXAMPLES)
file(GLOB EXAMPLE_SOURCES "examples/*.c")

foreach(example_src ${EXAMPLE_SOURCES})
get_filename_component(example_name ${example_src} NAME_WE)

add_executable(${example_name} ${example_src})
target_link_libraries(${example_name} uart_device)

# 为示例程序添加包含目录
target_include_directories(${example_name} PRIVATE include)

# 复制平台定义到示例程序
target_compile_definitions(${example_name} PRIVATE ${PLATFORM_DEFINES})

message(STATUS "Building example: ${example_name}")
endforeach()
endif()

以上示例文件配置了项目的版本信息,项目信息,添加了option,

cmake 项目解析:stm32cubemx

vscode 配置cmake为代码提示和include

大部分情况下,不会默认为ms-vscode.cmake-tools为vscode的代码提示器,需要在settings.json里设置才行

1
2
3
4
// settings.json
{
"C_Cpp.default.configurationProvider": "ms-vscode.cmake-tools"
}

cmake options 的使用,以及vscode里配置

语法为:

1
option(<variable> "<help_text>" [value])

可以当作开关使用,value只能为ON或者OFF,非ON皆为OFF。

示例:

1
2
3
4
5
6
7
8
option(BUILD_TESTS "Build test programs" ON)

if(BUILD_TESTS)
message(STATUS "Building tests")
add_subdirectory(tests)
else()
message(STATUS "Skipping tests")
endif()

更改options的值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
## 定义option选项
## 方式一:通过cache变量方式修改(正确方式,力推荐)
set(${ PROJECT_NAME }_BUILD_EXAMPLE ON CACHE BOOL "构建示例模块" FORCE)
message(STATUS "KAIZEN_BUILD_EXAMPLE_3: ${KAIZEN_BUILD_EXAMPLE}")#out: KAIZEN_BUILD_EXAMPLE_3 : ON

## 方式二:通过命令行 -D参数覆盖
## cmake.exe -DOPTIONS=ON

## vscode 方式可以使用settings.json
## {
## "cmake.configureArgs": [
## "-DPython3_EXECUTABLE=/path/to/conda/env/python",
## "-DEXAMPLE_BOARD=ON"
## ]
## }
打赏
打赏提示信息
分享
分享提示信息