C++ CMake:将条件编译器标志添加到Visual Studio项目中

C++ CMake:将条件编译器标志添加到Visual Studio项目中,c++,visual-studio,cmake,C++,Visual Studio,Cmake,VisualStudio允许选择cl编译器或clang cl编译器来构建项目-这些称为工具集。这两个编译器具有不同的标志集,特别是用于禁用警告的不同标志。一个编译器的标志在另一个编译器上产生错误 通过基于使用的工具集定义编译器标志,可以在Visual Studio中同时为两个编译器解决此问题。这方面的正式文件 我使用CMake生成Visual Studio项目。如何使CMake为生成的Visual Studio项目添加此类条件标志?基本上是对前面问题的一种更现代的方法,您可以使用if语句检查编译

VisualStudio允许选择cl编译器或clang cl编译器来构建项目-这些称为工具集。这两个编译器具有不同的标志集,特别是用于禁用警告的不同标志。一个编译器的标志在另一个编译器上产生错误

通过基于使用的工具集定义编译器标志,可以在Visual Studio中同时为两个编译器解决此问题。这方面的正式文件


我使用CMake生成Visual Studio项目。如何使CMake为生成的Visual Studio项目添加此类条件标志?

基本上是对前面问题的一种更现代的方法,您可以使用if语句检查编译器类型,并基于此设置编译标志:

if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
    # Disable a Clang warning type.
    target_compile_options(MyLib PRIVATE -Wno-unused-variable)
elseif(MSVC)
    # Disable a MSVC warning type.
    target_compile_options(MyLib PRIVATE /wd4101)
endif()
要将其放入单个表达式中,可以使用在CMake buildsystem生成阶段评估的CMake:

target_compile_options(MyLib PRIVATE 
    "$<IF:$<STREQUAL:${CMAKE_CXX_COMPILER_ID},Clang>,-Wno-unused-variable,/wd4101>"
)

以下是所有叮当警告类型的示例,以供参考。

基本上是解决前面问题的更现代方法,您可以使用if语句检查编译器类型,并基于此设置编译标志:

if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
    # Disable a Clang warning type.
    target_compile_options(MyLib PRIVATE -Wno-unused-variable)
elseif(MSVC)
    # Disable a MSVC warning type.
    target_compile_options(MyLib PRIVATE /wd4101)
endif()
要将其放入单个表达式中,可以使用在CMake buildsystem生成阶段评估的CMake:

target_compile_options(MyLib PRIVATE 
    "$<IF:$<STREQUAL:${CMAKE_CXX_COMPILER_ID},Clang>,-Wno-unused-variable,/wd4101>"
)
以下是所有叮当警告类型的参考。

您可以使用CMAKE\u CXX\u COMPILER\u ID和CMAKE\u CXX\u SIMULATE\u ID来处理编译器if else或生成器表达式

-T ClangCL Visual Studio 2019的输出:

message(STATUS ${CMAKE_CXX_COMPILER_ID}) // Clang
message(STATUS ${CMAKE_CXX_SIMULATE_ID}) // MSVC
message(STATUS ${CMAKE_CXX_COMPILER_ID}) // MSVC
message(STATUS ${CMAKE_CXX_SIMULATE_ID}) // <empty>
不带工具包的输出Visual Studio 2019:

message(STATUS ${CMAKE_CXX_COMPILER_ID}) // Clang
message(STATUS ${CMAKE_CXX_SIMULATE_ID}) // MSVC
message(STATUS ${CMAKE_CXX_COMPILER_ID}) // MSVC
message(STATUS ${CMAKE_CXX_SIMULATE_ID}) // <empty>
您可以使用CMAKE_CXX_COMPILER_ID和CMAKE_CXX_SIMULATE_ID来处理编译器if else或生成器表达式

-T ClangCL Visual Studio 2019的输出:

message(STATUS ${CMAKE_CXX_COMPILER_ID}) // Clang
message(STATUS ${CMAKE_CXX_SIMULATE_ID}) // MSVC
message(STATUS ${CMAKE_CXX_COMPILER_ID}) // MSVC
message(STATUS ${CMAKE_CXX_SIMULATE_ID}) // <empty>
不带工具包的输出Visual Studio 2019:

message(STATUS ${CMAKE_CXX_COMPILER_ID}) // Clang
message(STATUS ${CMAKE_CXX_SIMULATE_ID}) // MSVC
message(STATUS ${CMAKE_CXX_COMPILER_ID}) // MSVC
message(STATUS ${CMAKE_CXX_SIMULATE_ID}) // <empty>

我已经有了这些特定于编译器的开关。问题中的问题有点不同:在Visual Studio项目设置中切换时,生成的同一个Visual Studio项目必须能够同时适用于cl和clang cl,而无需CMake重新生成项目。@kaba如果要切换编译器/工具集,CMake确实应该重新运行。我明白了。如果MSBuild条件无法正常工作,我可以处理这个问题。@kaba我还添加了一个生成器表达式方法,该方法可能更接近您试图实现的目标。我同意重新运行CMake比依赖特殊的MSBuild功能要好。我已经有了这些编译器特定的开关。问题中的问题有点不同:在Visual Studio项目设置中切换时,生成的同一个Visual Studio项目必须能够同时适用于cl和clang cl,而无需CMake重新生成项目。@kaba如果要切换编译器/工具集,CMake确实应该重新运行。我明白了。如果MSBuild条件无法正常工作,我可以解决这个问题。@kaba我还添加了一个生成器表达式方法,该方法可能更接近您试图实现的目标。我同意重新运行CMake比依赖特殊的MSBuild功能要好。CMake_CXX_SIMULATE_ID确实有用;我不知道它的存在。我将其用于clang-cl的分支设置。一个奇怪的细节是,如果不是${CMAKE\U CXX\U SIMULATE\U ID},STREQUAL MSVC会按预期工作,但如果不是${CMAKE\U CXX\U SIMULATE\U ID}STREQUAL MSVC,则总是正确的。@kaba当CMAKE\U CXX\U SIMULATE\U ID未定义为空时,会发生这种情况。第二个条件应产生错误。如果不使用CMAKE_CXX_SIMULATE_ID,只需简单使用STREQUAL MSVC。CMAKE_CXX_SIMULATE_ID非常有用;我不知道它的存在。我将其用于clang-cl的分支设置。一个奇怪的细节是,如果不是${CMAKE\U CXX\U SIMULATE\U ID},STREQUAL MSVC会按预期工作,但如果不是${CMAKE\U CXX\U SIMULATE\U ID}STREQUAL MSVC,则总是正确的。@kaba当CMAKE\U CXX\U SIMULATE\U ID未定义为空时,会发生这种情况。第二个条件应产生错误。如果不是CMAKE_CXX_SIMULATE_ID STREQUAL MSVC,只需简单使用即可。