我看到越来越多的人在CMakeLists.txt 在 project 调用之后设置CMAKE_C_COMPILER 和其他编译器相关变量,我想知道为什么这种方法有时会失效。
实际发生了什么
当 CMake 执行 project() 调用时,它会寻找一个默认编译器可执行文件并确定使用它的方式:默认编译器标志、默认链接器标志、compile features 等。
CMake 将默认编译器可执行文件的路径存储在 CMAKE_C_COMPILER 变量中。
当设置CMAKE_C_COMPILER 变量在project() 调用后,此仅 更改编译器可执行文件:默认标志,所有功能默认编译器保持设置。
AS RESULT:构建项目时,构建系统调用项目指定的编译器可执行文件,但带有参数 适用于默认编译器。
正如人们可能猜到的那样,这种方法只有在将默认编译器替换为高度兼容的编译器时才有效。例如。有时用clang 替换gcc 可能会起作用。
这种方法永远行不通,无法用 gcc 替换 cl 编译器(在 Visual Studio 中使用)。当用 cross-compiler 替换 native 编译器时,这也不起作用。
做什么
从不在 CMakeLists.txt 中设置编译器。
如果您想要,例如,使用 clang 而不是默认的 gcc,那么:
-
在配置项目时将-DCMAKE_C_COMPILER=<compiler> 传递给cmake。这样,CMake 将使用此编译器而不是默认编译器,并且在 project() 调用中它将调整指定编译器的所有标志。
-
设置CC 环境变量(CXX 用于 C++ 编译器)。 CMake 在选择默认编译器时会检查此变量。
-
(仅在极少数情况下)在project() 调用之前设置CMAKE_C_COMPILER 变量。这种方法与第一种方法类似,但会使项目的灵活性降低。
如果上述方法不起作用
如果在命令行 CMake 中设置 CMAKE_C_COMPILER 时出现编译器无法“编译简单项目”的错误,那么您的环境中有问题.. 或者您为所选的 @ 指定了编译器 incompatible 987654322@或平台。
例子:
- Visual Studio 生成器可与
cl 编译器一起使用,但不能与gcc 一起使用。
- MinGW 编译器通常需要MinGW Makefiles 生成器。
不兼容的生成器无法在CMakeLists.txt 中修复。需要将正确的-G 选项传递给cmake 可执行文件(或在CMake GUI 中选择正确的生成器)。
交叉编译
交叉编译通常需要设置CMAKE_SYSTEM_NAME变量,这个设置一般应该在toolchain file中完成。那个工具链文件还负责设置一个编译器。
在CMakeLists.txt 中设置CMAKE_SYSTEM_NAME 几乎总是错误。