3

Visual Studio allows to select either the cl compiler or the clang-cl compiler to build projects -- these are called toolsets. These two compilers have different sets of flags, and in particular different flags for disabling warnings. Flags for one compiler produces errors on the other.

This problem can be solved in Visual Studio for both compilers at the same time by defining compiler flags conditionally based on the used toolset. Official documentation for that here.

I use CMake to generate the Visual Studio projects. How can I make CMake add such conditional flags for the generated Visual Studio projects?

kaba
  • 703
  • 6
  • 17

2 Answers2

3

Essentially a more modern approach to the earlier question here, you can use an if-statement to check the compiler type, and set compile flags based on that:

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()

For putting this into a single expression, you can use CMake generator expressions (which are evaluated at the CMake buildsystem generation stage):

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

For reference, here is a list of all of the clang warnings types.

Kevin
  • 16,549
  • 8
  • 60
  • 74
  • I have these kind of compiler-specific switches already. The problem in the question is a bit different: the same generated Visual Studio project has to be able to work for both cl and clang-cl when switched in the Visual Studio project settings without regenerating the project by CMake. – kaba Jun 23 '20 at 00:02
  • 1
    @kaba If you are switching the compiler/toolset, the CMake really should be re-run. – Kevin Jun 23 '20 at 00:05
  • I see. I could deal with that if the MSBuild conditions cannot be made to work. – kaba Jun 23 '20 at 00:09
  • @kaba I also added a generator expression approach which might be closer to what you're try to achieve. – Kevin Jun 23 '20 at 00:14
  • 1
    I concur that rerunning CMake is better than relying on special MSBuild features. – kaba Jun 23 '20 at 00:33
3

You can use CMAKE_CXX_COMPILER_ID and CMAKE_CXX_SIMULATE_ID with your favourite way of handling compilers (if-else or generator expressions)

Output for -T ClangCL (Visual Studio 2019):

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

Output with no toolkit (Visual Studio 2019):

message(STATUS ${CMAKE_CXX_COMPILER_ID}) // MSVC
message(STATUS ${CMAKE_CXX_SIMULATE_ID}) // <empty>
local-ninja
  • 1,198
  • 4
  • 11
  • `CMAKE_CXX_SIMULATE_ID` is really useful; I did not know that existed. I used that to branch settings for clang-cl. A strange detail is that `if (NOT ("${CMAKE_CXX_SIMULATE_ID}" STREQUAL "MSVC"))` works as expected but `if (NOT (${CMAKE_CXX_SIMULATE_ID} STREQUAL "MSVC"))` does not (it is always true). – kaba Jun 23 '20 at 01:05
  • 2
    @kaba this happens when `CMAKE_CXX_SIMULATE_ID` not defined (empty). the second condition should yield an error. simply use `if (NOT (CMAKE_CXX_SIMULATE_ID STREQUAL "MSVC"))`. – local-ninja Jun 23 '20 at 01:21