0

我正在尝试为基于 Zephyr 生态系统的嵌入式设备创建一个项目。我遇到的问题是它强制执行单可执行项目。它使用 CMake。

Zephyr 建议创建 main 的方式CMakeLists.txt(来自其文档):

cmake_minimum_required(VERSION 3.16)

# This is project-dependent
set(ZEPHYR_TOOLCHAIN_VARIANT "gnuarmemb" CACHE STRING "Informs Zephyr about the toolchain used")
set(GNUARMEMB_TOOLCHAIN_PATH ${TOOLCHAIN_PATH} CACHE PATH "Informs Zephyr where the GNU toolchain is located")
set(BOARD nucleo_l432kc CACHE STRING "Board specification for Zephyr")

find_package(Zephyr 2.4.99)

project(MyProject)

# "app" is defined within the call to "find_package(Zephyr ...)".
# This is necessary - to provide at least one source file.
target_sources(app PRIVATE dummy.cpp)

我想在这个环境中拥有多个可执行文件(用于嵌入式测试目标和额外的可执行文件,如传感器的长时间运行测试等)。最重要的是我想拥有“app”目标在其他可执行目标中的所有符号。我可以为此创建多个项目,但这是一个乏味的解决方案,因为它分散了构建系统并使其在使用方面非常不方便(为 CMake 定义多个构建目录,所有手动检查过时的构建都很容易忘记)。

我遇到的其他解决方案是ExternalProject与一些 CMake 代码混合使用来定义可执行目标。那种工作,但它是非常低效的。函数看起来像这样:

function(CreateFirmwareExecutableTarget name toolchain_path)

    set(external_proj_name SubBuild_${name})
    set(src_dir ${CMAKE_SOURCE_DIR}/zephyr)
    set(install_dir ${CMAKE_CURRENT_BINARY_DIR}/zephyr_${name})

    include(ExternalProject)
    ExternalProject_Add(${external_proj_name}
        SOURCE_DIR ${src_dir}
        INSTALL_DIR ${install_dir}
        CMAKE_ARGS -DTOOLCHAIN_PATH=${toolchain_path}
                   -DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR>
        BUILD_ALWAYS YES
    )

    add_executable(${name} IMPORTED)
    set_target_properties(${name} PROPERTIES
        IMPORTED_LOCATION ${install_dir}/bin/zephyr.elf)

endfunction()

zephyr目录中,我CMakeLists.txt与第一个清单中的目录类似。那行得通,但那很笨拙。Zephyr 源代码将为每个可执行文件从头开始构建。这是非常无效的。

(在上面的清单中,没有链接到可执行文件的自定义代码(如我的项目自己的代码)。这还没有解决,但解决方案很简单,不在这个问题的范围内)。

Zephyr 没有提供任何 CMake API 来创建更多可执行文件,因此我选择了 CMake 解决方案。

理想情况下,Zephyr 应该定义静态库目标,我可以使用add_executable命令创建的目标链接到这些目标。但不幸的是,事实并非如此。

我想出的一种解决方案是从app可执行文件中抓取属性(如链接到它的静态库目标、源、链接标志等),并创建一个库目标,创建的目标add_executable将链接到该库目标。这相当于为可执行文件创建对应的库目标。

问题是我是否在这里遗漏了什么?如何使用 CMake 以非 hacky 的方式完成为该环境创建多可执行项目的任务?

4

0 回答 0