如何在嵌入式(RP2040)项目结构中正确使用CMake?
TL;DR
如何以优雅的方式将 CMakeLists.txt 与包含的项目级库一起使用?
简介
亲爱的堆栈用户,
在开始使用手动创建的构建系统(之前使用预配置的 STM32CubeIDE、SW4STM32 和 MSP430 CCS)的旅程后不久,我在使用 Raspberry RP2040 时遇到了这个问题,我偶然发现了一项艰巨的(主观)任务:以更明智的方式使用 CMake。通过查看大量教程、提示和问题(以及 Pico 项目生成器),我已经成功构建了我的简单项目。但我觉得这是以相当临时的方式完成的。
环境
情况如何: 我有一个使用 RP2040 picoSDK 的项目 - 外围配置函数的集合,存储在项目目录之外的某种 HAL。将 picoSDK 视为外部库函数。使用此 picoSDK,我创建了一个使用多个外围设备的简单应用程序。我将我的项目分为以下结构: 项目结构
我的文件之间的连接如下: 文件关系,其中我的 main.c 文件使用其中一个模块,而模块使用两个外围设备。所有这些文件都需要访问全局定义,并包含来自 common.h 文件的 picoSDK。
为了清楚起见,我在 Windows 10 上使用 VS code,我使用 arm-gcc 10.3.1 进行编译,我的 CMake 版本是 3.20.6
问题和当前解决方案
现在,我一直在尝试使用该方法(在此线程中建议:CMake with subdirectories)在每个目录中使用多个 CMakeLists.txt 创建基于目录的库,然后使用顶级 CMakeLists.txt 内的 add_subdirectory() 添加它们,但没有成功。我已经按照以下方式完成了工作的 CMakeLists.txt:
cmake_minimum_required(VERSION 3.13)
# [Platfrom specific command] Pull in Raspberry Pi Pico SDK (must be before project)
include(pico_sdk_import.cmake)
project(ProjectName C CXX ASM)
# [Platfrom specific command] Initialize the Raspberry Pi Pico SDK
pico_sdk_init()
set(sources main.c
Common.h
Peripherals/PeripheralA.c
Peripherals/PeripheralA.h
Peripherals/PeripheralB.c
Peripherals/PeripheralB.h
Modules/ModuleSource.c
Modules/ModuleSource.h
Modules/ModuleConfig.h)
# Create executable with specified sources
add_executable(ProjectName ${sources})
# Add the standard library to the build (picoSDK inclusion)
target_link_libraries(ProjectName pico_stdlib)
# Add any user requested libraries (a part of picoSDK)
target_link_libraries( ProjectName
hardware_timer
)
免责声明:针对特定情况留下了平台特定行的添加,在这种情况下,这个问题落入了精通 RP2040 的人手中
现在的问题
,我'我觉得嵌入式领域有点不同,因为我的项目的每个部分(外设、模块甚至主文件)都需要访问基础:用于驱动微控制器的库(此处为 picoSDK),因此我想问:建议的方法是什么,CMakeLists.txt内容的概要是什么?我确信该项目将会增长,并且根据其他回复,不建议将所有内容保留在一个 CMakeLists.txt 文件中。
我正在寻找提示、好的建议和批评。我非常感谢花时间阅读这篇文章,或者——当然——回复它。如果这个问题涉及一些琐碎的、已经回答的或从熟练的用户角度来看毫无意义的问题 - 请接受我的歉意。
TL;DR
How to use CMakeLists.txt with included project-level libraries in elegant way?
Introduction
Dear Stack Users,
shortly after starting my journey with manually-created build systems (previously using pre-configured STM32CubeIDE, SW4STM32 and MSP430 CCS) which I've encountered by using Raspberry RP2040 I've stumbled upon a tough (subjectively) task of using CMake in a more aware way. Looking through multitude of tutorials, hints and questions (and Pico Project generator) I've managed to build my simple project. Yet I feel that it is done in rather makeshift-alike manner.
Environment
What is the situation:
I have a project that uses RP2040 picoSDK - a collection of peripheral configuration functions, a HAL of some sort stored outside of project directory. Think of picoSDK as as external library function. Using this picoSDK I've created a simple application that uses several peripherals. I've divided my project into following structure:
Project structure
Connections between my files are as follows:
File relations where my main.c file uses one of the module, and module uses two peripherals. All of those files require access to global definitions and picoSDK includes from common.h file.
For the sake of clarity I'm using VS code on Windows 10, I'm compiling with arm-gcc 10.3.1, my CMake version is 3.20.6
Problem and current solution
Now, I've been trying to use the approach (suggested among other in this thread: CMake with subdirectories) with multiple CMakeLists.txt in each directory to create o directory-based library and then add them all by using add_subdirectory() inside of top-level CMakeLists.txt but with no success. CMakeLists.txt that works I've done in following manner:
cmake_minimum_required(VERSION 3.13)
# [Platfrom specific command] Pull in Raspberry Pi Pico SDK (must be before project)
include(pico_sdk_import.cmake)
project(ProjectName C CXX ASM)
# [Platfrom specific command] Initialize the Raspberry Pi Pico SDK
pico_sdk_init()
set(sources main.c
Common.h
Peripherals/PeripheralA.c
Peripherals/PeripheralA.h
Peripherals/PeripheralB.c
Peripherals/PeripheralB.h
Modules/ModuleSource.c
Modules/ModuleSource.h
Modules/ModuleConfig.h)
# Create executable with specified sources
add_executable(ProjectName ${sources})
# Add the standard library to the build (picoSDK inclusion)
target_link_libraries(ProjectName pico_stdlib)
# Add any user requested libraries (a part of picoSDK)
target_link_libraries( ProjectName
hardware_timer
)
Disclaimer: Additions of platform specific lines were left for a particular situation where this questions fells into hands of someone proficient with RP2040
The question
Now, I'm feeling that embedded domain is a bit different due to the fact that each part of my project (Peripherals, modules and even main file) needs the access to the base: library for driving the microcontroller (picoSDK here), hence I'd like to ask: what is the suggested approach, what is the outline of CMakeLists.txt content? I know for sure that the project will grow, and keeping everything inside of one CMakeLists.txt file was - according to other replies - not suggested.
I'm looking for hints, good advises and criticism. I'm very grateful for the time spent on reading this post or - of course - on replying to it. In case if this question addresses something that is trivial, already answered or senseless from a proficient user perspective - please accept my apologies.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我能给你的最好建议是将代码组织到库中。它将解耦代码并为单元测试、模拟、代码重用等提供机会。
您绝对应该避免依赖外设和模块中的
common.h
。下面是如何创建库并将库相互链接以及与主项目链接的示例。
顶级 CMakeLists.txt
外围设备/CMakeLists.txt
模块/CMakeLists.txt
The best advice I can give you is to organise your code into libraries. It will decouple the code and open up opportunities for unit testing, simulation, code reuse etc.
You should definitely avoid dependency on
common.h
in Peripherals and Modules.Below is an example of how you can create and link libraries to each other and the main project.
Top level CMakeLists.txt
Peripherals/CMakeLists.txt
Modules/CMakeLists.txt