如何在 CMake 中指定编译器?
How to specify a compiler in CMake?
我想使用 IAR 编译器。我注意到 CMake 已经有一堆关于这个编译器的文件:
https://github.com/jevinskie/cmake/blob/master/Modules/Compiler/IAR.cmake
根据我的阅读,常见的解决方案是在我的 CMakeLists.txt
:
中手动指定所有工具链
set(CMAKE_C_COMPILER iccarm)
set(CMAKE_CPP_COMPILER iccarm)
CMake 如何 link 这些定义与 `Modules/Compiler/IAR.cmake"?
我以为我只需要做
include("Modules/Compiler/IAR.cmake")
指定 IAR 编译器的正确方法是什么?
当我做
cmake .
它仍然尝试使用 gcc
而不是我的 IAR 编译器。为什么?
如果您不想使用 PC 的标准编译器,则必须为 CMake 提供编译器的路径。您可以通过环境变量、工具链文件或 CMake 命令行中的直接定义来执行此操作(参见 )。
将编译器的 name/path 放入您的 CMakeLists.txt 会阻止您的项目跨平台。
CMake 通过编译 special C/C++ files 检查编译器 ID。因此无需手动包含 Module/Compiler
或 Module/Platform
.
这将由 CMake 根据其编译器和平台检查自动完成。
参考文献
对于select特定的编译器,您有多种解决方案,如CMake wiki中所述:
方法一:使用环境变量
对于 C 和 C++,设置 CC
和 CXX
环境变量。不保证此方法适用于所有生成器。 (具体来说,如果您尝试设置 Xcode 的 GCC_VERSION
,此方法会混淆 Xcode。)
例如:
CC=gcc-4.2 CXX=/usr/bin/g++-4.2 cmake -G "Your Generator" path/to/your/source
方法二:使用cmake -D
使用 cmake -D
在命令行上将适当的 CMAKE_FOO_COMPILER
变量设置为有效的编译器名称或完整路径。
例如:
cmake -G "Your Generator" -D CMAKE_C_COMPILER=gcc-4.2 -D CMAKE_CXX_COMPILER=g++-4.2 path/to/your/source
方法三(避免):使用set()
使用 set()
将适当的 CMAKE_FOO_COMPILER
变量设置为有效的编译器名称或列表文件中的完整路径。这必须在设置任何语言之前完成(即:在任何 project()
或 enable_language()
命令之前)。
例如:
set(CMAKE_C_COMPILER "gcc-4.2")
set(CMAKE_CXX_COMPILER "/usr/bin/g++-4.2")
project("YourProjectName")
wiki 没有提供应避免第三种方法的原因...
您可以这样调用cmake
:
cmake -DCMAKE_C_COMPILER=iccarm ...
或
cmake -DCMAKE_CXX_COMPILER=...
您需要创建一个工具链文件,并使用 CmakeForceCompiler 模块。
这是一个使用 IAR 进行裸机 ARM 开发的示例工具链文件:
include(CMakeForceCompiler)
set(CMAKE_SYSTEM_NAME Generic) # Or name of your OS if you have one
set(CMAKE_SYSTEM_PROCESSOR arm) # Or whatever
set(CMAKE_CROSSCOMPILING 1)
set(CMAKE_C_COMPILER iccarm) # Change the arm suffix if appropriate
set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY) # Required to make the previous line work for a target that requires a custom linker file
最后一行是必要的,因为 CMake 将尝试使用编译器编译测试程序以确保其正常工作并从预处理器定义中获取一些版本信息。如果没有这一行,CMake 将使用 add_executable() 作为测试程序,您将收到错误 "The C compiler "XXX" is not able to compile a simple test program."这是因为测试程序无法 link,因为它没有您的自定义 linker 文件(我假设是裸机开发,因为 IAR 通常用于此)。这一行告诉 CMake 改用 add_library() ,这使得测试在没有 linker 文件的情况下成功。此解决方法的来源:this CMake mailing list post.
然后,假设您的工具链文件名为 iar-toolchain.cmake,像这样调用 CMake:
cmake -DCMAKE_TOOLCHAIN_FILE=iar-toolchain.cmake .
我看到越来越多的人在 CMakeLists.txt
project
之后设置 CMAKE_C_COMPILER
和其他 compiler-related 变量打电话想知道为什么这种方法有时会失败。
实际发生了什么
当 CMake 执行 project()
调用时,它会查找 默认编译器可执行文件 并确定使用它的方式:默认编译器标志、默认链接器标志、compile features,等等
CMake 将默认编译器可执行文件的路径存储在 CMAKE_C_COMPILER
变量中。
当CMAKE_C_COMPILER
变量在调用project()
之后,这个只改变了编译器可执行文件:默认标志,所有功能都为默认编译器设置。
结果:构建项目时,构建系统调用project-specified编译器可执行文件 但具有 参数 适用于 默认编译器 .
正如人们所猜测的那样,这种方法只有在将默认编译器替换为 高度兼容 编译器时才有效。例如。将 gcc
替换为 clang
有时会奏效。
这种方法 永远不会工作 用 gcc
替换 cl
编译器(在 Visual Studio 中使用)。当用 cross-compiler 替换 native 编译器时,这也不起作用。
做什么
从不 在 CMakeLists.txt
中设置编译器。
如果您想使用 clang
而不是默认的 gcc
,则可以:
配置项目时将-DCMAKE_C_COMPILER=<compiler>
传递给cmake
。这样 CMake 将使用此编译器而不是默认编译器,并且在 project()
调用时它将调整指定编译器的所有标志。
设置 CC
环境变量(C++ 编译器为 CXX
)。当 select 是默认编译器时,CMake 检查此变量。
(仅在极少数情况下)在 project()
调用之前 设置 CMAKE_C_COMPILER
变量 。这种方法与第一种类似,但使项目的灵活性降低。
如果以上方法都不行
如果在命令行 CMake 中设置 CMAKE_C_COMPILER
编译器无法“编译一个简单项目”的错误,那么您的环境有问题..或者您指定了一个编译器 不兼容 用于选择 generator 或平台。
示例:
- Visual Studio 生成器可与
cl
编译器一起使用,但不能与 gcc
. 一起使用
- MinGW 编译器通常需要 MinGW Makefiles 生成器。
不兼容的生成器 无法 在 CMakeLists.txt
中修复。需要将正确的 -G
选项传递给 cmake
可执行文件(或 select CMake GUI 中的正确生成器)。
Cross-compiling
Cross-compiling通常需要设置CMAKE_SYSTEM_NAME variable, and this setting should normally be done in the toolchain file。 工具链文件也负责设置编译器。
在CMakeLists.txt
中设置CMAKE_SYSTEM_NAME
几乎总是报错。
如果您想在 cmake 中指定一个编译器,那么只需执行...
cmake_minimum_required(VERSION 3.22)
set(CMAKE_C_COMPILER "clang")
set(CMAKE_CXX_COMPILER "clang++")
选项 1 仅在您要指定要使用的编译器作为您可能在计算机上编译的所有内容的默认编译器时使用。而且我什至认为它不会在 windows.
上运行
如果您只想临时使用不同的选项,则可以使用选项 2。
如果该编译器应该用于该特定项目,则使用选项 3。选项 3 也是最兼容的。
我想使用 IAR 编译器。我注意到 CMake 已经有一堆关于这个编译器的文件:
https://github.com/jevinskie/cmake/blob/master/Modules/Compiler/IAR.cmake
根据我的阅读,常见的解决方案是在我的 CMakeLists.txt
:
set(CMAKE_C_COMPILER iccarm)
set(CMAKE_CPP_COMPILER iccarm)
CMake 如何 link 这些定义与 `Modules/Compiler/IAR.cmake"?
我以为我只需要做
include("Modules/Compiler/IAR.cmake")
指定 IAR 编译器的正确方法是什么?
当我做
cmake .
它仍然尝试使用 gcc
而不是我的 IAR 编译器。为什么?
如果您不想使用 PC 的标准编译器,则必须为 CMake 提供编译器的路径。您可以通过环境变量、工具链文件或 CMake 命令行中的直接定义来执行此操作(参见
将编译器的 name/path 放入您的 CMakeLists.txt 会阻止您的项目跨平台。
CMake 通过编译 special C/C++ files 检查编译器 ID。因此无需手动包含 Module/Compiler
或 Module/Platform
.
这将由 CMake 根据其编译器和平台检查自动完成。
参考文献
对于select特定的编译器,您有多种解决方案,如CMake wiki中所述:
方法一:使用环境变量
对于 C 和 C++,设置 CC
和 CXX
环境变量。不保证此方法适用于所有生成器。 (具体来说,如果您尝试设置 Xcode 的 GCC_VERSION
,此方法会混淆 Xcode。)
例如:
CC=gcc-4.2 CXX=/usr/bin/g++-4.2 cmake -G "Your Generator" path/to/your/source
方法二:使用cmake -D
使用 cmake -D
在命令行上将适当的 CMAKE_FOO_COMPILER
变量设置为有效的编译器名称或完整路径。
例如:
cmake -G "Your Generator" -D CMAKE_C_COMPILER=gcc-4.2 -D CMAKE_CXX_COMPILER=g++-4.2 path/to/your/source
方法三(避免):使用set()
使用 set()
将适当的 CMAKE_FOO_COMPILER
变量设置为有效的编译器名称或列表文件中的完整路径。这必须在设置任何语言之前完成(即:在任何 project()
或 enable_language()
命令之前)。
例如:
set(CMAKE_C_COMPILER "gcc-4.2")
set(CMAKE_CXX_COMPILER "/usr/bin/g++-4.2")
project("YourProjectName")
wiki 没有提供应避免第三种方法的原因...
您可以这样调用cmake
:
cmake -DCMAKE_C_COMPILER=iccarm ...
或
cmake -DCMAKE_CXX_COMPILER=...
您需要创建一个工具链文件,并使用 CmakeForceCompiler 模块。
这是一个使用 IAR 进行裸机 ARM 开发的示例工具链文件:
include(CMakeForceCompiler)
set(CMAKE_SYSTEM_NAME Generic) # Or name of your OS if you have one
set(CMAKE_SYSTEM_PROCESSOR arm) # Or whatever
set(CMAKE_CROSSCOMPILING 1)
set(CMAKE_C_COMPILER iccarm) # Change the arm suffix if appropriate
set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY) # Required to make the previous line work for a target that requires a custom linker file
最后一行是必要的,因为 CMake 将尝试使用编译器编译测试程序以确保其正常工作并从预处理器定义中获取一些版本信息。如果没有这一行,CMake 将使用 add_executable() 作为测试程序,您将收到错误 "The C compiler "XXX" is not able to compile a simple test program."这是因为测试程序无法 link,因为它没有您的自定义 linker 文件(我假设是裸机开发,因为 IAR 通常用于此)。这一行告诉 CMake 改用 add_library() ,这使得测试在没有 linker 文件的情况下成功。此解决方法的来源:this CMake mailing list post.
然后,假设您的工具链文件名为 iar-toolchain.cmake,像这样调用 CMake:
cmake -DCMAKE_TOOLCHAIN_FILE=iar-toolchain.cmake .
我看到越来越多的人在 CMakeLists.txt
project
之后设置 CMAKE_C_COMPILER
和其他 compiler-related 变量打电话想知道为什么这种方法有时会失败。
实际发生了什么
当 CMake 执行 project()
调用时,它会查找 默认编译器可执行文件 并确定使用它的方式:默认编译器标志、默认链接器标志、compile features,等等
CMake 将默认编译器可执行文件的路径存储在 CMAKE_C_COMPILER
变量中。
当CMAKE_C_COMPILER
变量在调用project()
之后,这个只改变了编译器可执行文件:默认标志,所有功能都为默认编译器设置。
结果:构建项目时,构建系统调用project-specified编译器可执行文件 但具有 参数 适用于 默认编译器 .
正如人们所猜测的那样,这种方法只有在将默认编译器替换为 高度兼容 编译器时才有效。例如。将 gcc
替换为 clang
有时会奏效。
这种方法 永远不会工作 用 gcc
替换 cl
编译器(在 Visual Studio 中使用)。当用 cross-compiler 替换 native 编译器时,这也不起作用。
做什么
从不 在 CMakeLists.txt
中设置编译器。
如果您想使用 clang
而不是默认的 gcc
,则可以:
配置项目时将
-DCMAKE_C_COMPILER=<compiler>
传递给cmake
。这样 CMake 将使用此编译器而不是默认编译器,并且在project()
调用时它将调整指定编译器的所有标志。设置
CC
环境变量(C++ 编译器为CXX
)。当 select 是默认编译器时,CMake 检查此变量。(仅在极少数情况下)在
project()
调用之前 设置CMAKE_C_COMPILER
变量 。这种方法与第一种类似,但使项目的灵活性降低。
如果以上方法都不行
如果在命令行 CMake 中设置 CMAKE_C_COMPILER
编译器无法“编译一个简单项目”的错误,那么您的环境有问题..或者您指定了一个编译器 不兼容 用于选择 generator 或平台。
示例:
- Visual Studio 生成器可与
cl
编译器一起使用,但不能与gcc
. 一起使用
- MinGW 编译器通常需要 MinGW Makefiles 生成器。
不兼容的生成器 无法 在 CMakeLists.txt
中修复。需要将正确的 -G
选项传递给 cmake
可执行文件(或 select CMake GUI 中的正确生成器)。
Cross-compiling
Cross-compiling通常需要设置CMAKE_SYSTEM_NAME variable, and this setting should normally be done in the toolchain file。 工具链文件也负责设置编译器。
在CMakeLists.txt
中设置CMAKE_SYSTEM_NAME
几乎总是报错。
如果您想在 cmake 中指定一个编译器,那么只需执行...
cmake_minimum_required(VERSION 3.22)
set(CMAKE_C_COMPILER "clang")
set(CMAKE_CXX_COMPILER "clang++")
选项 1 仅在您要指定要使用的编译器作为您可能在计算机上编译的所有内容的默认编译器时使用。而且我什至认为它不会在 windows.
上运行如果您只想临时使用不同的选项,则可以使用选项 2。
如果该编译器应该用于该特定项目,则使用选项 3。选项 3 也是最兼容的。