将CMake与多个编译器一起用于同一种语言

cdl*_*ary 22 c++ configuration build cmake

看起来CMake在其视图中已经相当根深蒂固,所有C++源文件应该只有一个CMAKE_CXX_COMPILER.我无法找到一种在每个目标的基础上覆盖它的方法.这使得在单个CMakeLists.txt中混合主机和交叉编译非常困难,内置的CMake工具.

所以,我的问题是:对于同一种语言(即C++)使用多个编译器的最佳方法是什么?

Com*_*sMS 14

用CMake做这个是不可能的.

CMake仅保留一组编译器属性,这些属性由CMakeLists.txt文件中的所有目标共享.如果要使用两个编译器,则需要运行两次CMake.对于例如从相同的编译器工具链构建32位和64位二进制文​​件,这甚至是正确的.

这种快速而肮脏的方法是使用自定义命令.但是你最终会得到基本上美化的shell脚本,这可能不是你想要的.

干净的解决方案是:不要将它们放在相同的CMakeLists.txt中!无论如何,您无法在不同的体系结构之间进行链接,因此不需要它们位于同一个文件中.您可以通过将CMake脚本的公共部分重构为单独的文件来减少冗余include().

这里的主要缺点是您失去了使用单个命令构建的能力,但是您可以通过使用您喜欢的脚本语言编写包装来解决这个问题,该脚本负责调用不同的CMake-makefiles.

  • 看起来像add_directory(other_build_kind_folder)也是一种可能性,而不是制作自定义包装器,因为这就是我一直在做的事情,它似乎有效.:-) (2认同)
  • @cdleary你能澄清一下它是如何工作的吗?`add_subdirectory`(或者你的意思是'add_directory`?)如何允许你切换工具链? (2认同)
  • @ComicSancMs 我强烈不同意第三段背后的推理,事实上,你不能链接不同的架构,但这并不是拥有不同 C++ 编译器的唯一原因,例如我曾经使用 [templight](https://github.com/templight)。 com/mikael-s-persson/templight)作为 clang 的包装器,而 ccache 也是一个编译器包装器,这两个项目都算作不同的编译器,但原则上您可以在任何单独的 cpp 文件中随意使用不同的工具。想 (2认同)

小智 5

正如最佳答案所暗示的那样,并非不可能。我和OP有同样的问题。我有一些用于树莓派 pico 交叉编译的源代码,然后是我在主机系统上运行的一些单元测试。

为了完成这项工作,我使用非常可耻的“设置”来覆盖我的测试文件夹的 CMakeLists.txt 中的编译器。效果很好。

if(DEFINED ENV{HOST_CXX_COMPILER})
  set(CMAKE_CXX_COMPILER $ENV{HOST_CXX_COMPILER})
else()
  set(CMAKE_CXX_COMPILER "g++")
endif()

set(CMAKE_CXX_FLAGS "")
Run Code Online (Sandbox Code Playgroud)

由于某种原因,cmake 开发者/社区似乎非常反对使用 set 来更改编译器。他们假设您需要为整个项目使用一个编译器,这对于嵌入式系统项目来说是一个错误的假设。

我上面的解决方案有效,并且符合我认为的哲学。用户仍然可以通过环境变量更改他们选择的编译器,如果没有设置,那么我确实假设g++。set 仅更改当前范围的变量,因此不会影响项目的其余部分。