CMake - 编译本地和交叉编译相同的代码

4
我们正在为一个嵌入式ARM/Linux设备编写应用程序。开发在Windows PC上进行,使用交叉编译器、Eclipse和Ninja。CMake目前可以创建适用于预期目的的构建脚本。
一旦项目通过Git推送到服务器上,我们就可以在连接到网络的嵌入式设备上运行单元测试。
我们试图实现在PC上运行单元测试,然后再尝试在设备上运行它们。这意味着需要使用MinGW GCC本地构建,当然不能在PC上启动ARM Linux可执行文件。
即使我们切换工具链,启动CMake重新构建Ninja的规则集,或者创建两个构建目录,一个用于PC,一个用于ARM,问题仍然存在,即CMake将尝试运行一个测试可执行文件,并在构建期间尝试在ARM构建上运行单元测试。
如何通过CMake配置构建以创建两个版本,并且不尝试在PC上运行交叉编译的版本?

您可以检查 CMAKE_CROSSCOMPILING。例如,请参阅 如何指示 CMake 使用构建架构编译器? - Florian
请问您能否添加一个CMake代码示例,展示您如何运行测试可执行文件?您是使用add_custom_command(TARGET ... POST_BUILD ...)还是add_test()来添加的呢?我认为在这两种情况下,只需在特定命令周围加上if (NOT CMAKE_CROSSCOMPILING)|endif()即可解决问题。 - Florian
@Florian:在顶层的CMakeLists.txt文件中只有ADD_SUBDIRECTORY(UnitTests)。然后在该目录中,有ExternalProject_Add(GMockDownload GIT_REPOSITORY "https://github.com/google/googletest.git" ... 它完成了其余的工作。是的,if (NOT CMAKE_CROSSCOMPILING) 在这里很有帮助。看起来两个单独的构建目录并且两次启动cmake是正确的方法。虽然不是最优的,因为我得到了两个Eclipse项目而不仅仅是两个构建配置。 - SF.
1个回答

3

我在我的项目中有一个类似的设置(从相同的源代码构建模拟器、单元测试和目标二进制文件),您可以检查CMAKE_CROSSCOMPILING来区分您的两个用例。只需放置即可。

if (NOT CMAKE_CROSSCOMPILING)
    ....
endif()

在特定的命令周围应该就可以解决问题了。

并且您需要拥有两个二进制输出目录。CMake 不允许在一个目录中混合使用工具链。

但是您不需要拥有两个 IDE 项目。在我的项目中:

  • 我将所有源代码(包括“仅用于交叉编译”的文件)添加到库/可执行文件目标中
    • 对于 PC 版本,我标记它们为“从构建中排除”
    • 因此,所有源代码将在一个 IDE 项目中显示(例如,用于搜索代码)
  • 我将交叉编译调用添加为自定义目标
    • 我已将其从默认构建中删除,但您可以从 IDE 显式启动它
    • 在我的情况下,它是一个外部脚本,但您也可以直接在 COMMAND 参数中传递必要的调用
    • 您甚至可以使用另一个 ExternalProject_Add() 来包含您自己的项目以进行交叉编译

以下是这种方法的一些代码片段:

if (NOT CMAKE_CROSSCOMPILING)
    set(PC "ON" CACHE INTERNAL "hw-platform PC")
    unset(MCU CACHE)
else()
    set(MCU "ON" CACHE INTERNAL "hw-platform MCU")
    unset(PC CACHE)
endif()

...

if (PC)
    # Exclude files that only compile/work on MCU
    set_source_files_properties(... PROPERTIES HEADER_FILE_ONLY 1)
endif()

...

if (PC)
    add_test(...)
endif()

...

if (PC AND EXISTS "${CMAKE_SOURCE_DIR}/buildMcu.cmd")
    add_custom_target(
        BUILD_MCU
        COMMAND buildMcu.cmd
        WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
    )
    set_target_properties(BUILD_MCU PROPERTIES EXCLUDE_FROM_DEFAULT_BUILD 1)
endif()

参考文献


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接