How to set compiler options using CMake in Visual Studio 2017

Visual Studio 2017 comes with full CMake integration. To learn about this combination, I started with this basic example:

# CMakeLists.txt cmake_minimum_required(VERSION 3.8) project(foo) add_executable(foo foo.cpp) 

and

 // foo.cpp int main() {} 

This correctly generates build scripts, and also compiles and links without problems. It was easy.

The attempt to set the compiler options, on the other hand, turned out to be somewhat trivial. In my case, I tried to set the warning level to 4.

Obvious solution

 add_compile_options("/W4") 

not expected. The command line passed to the compiler now contains both /W4 (as expected) and /W3 (raised from another location), causing the following warning:

 cl : Command line warning D9025: overriding '/W3' with '/W4' 

To get around this, I will need to replace any incompatible compiler options instead of just adding. CMake does not provide immediate support for this, and the standard solution (as this Q&A suggests ) is as follows:

 if(CMAKE_CXX_FLAGS MATCHES "/W[0-4]") string(REGEX REPLACE "/W[0-4]" "/W4" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") else() set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W4") endif() 

This, however, has two problems:

  • It sets the global CMAKE_CXX_FLAGS , applicable to all C ++ goals. This may not be intended (this is not a problem for me right now).
  • It does not scale. For each compiler option, you will need to familiarize yourself with incompatible parameters and manually discard them first. This will inevitably fail 1 .

My question is double:

  • Where does CMake integration choose the default settings, and can it be controlled?
  • How do you set compiler options in general? (If this is too broad a topic, I would be glad for help in setting only the warning level.)

<h / "> 1 By the way, the replicated solution does not take into account the /Wall option, which is also incompatible with /W4 .

+4
source share
2 answers

The default settings for the compiler are selected from the standard module files located in the Modules directory of the CMake installation. The actual module file used depends on both the platform and the compiler. For example, for Visual Studio 2017, CMake will load the default settings from the Windows-MSVC.cmake and the language settings from Windows-MSVC-C.cmake or Windows-MSVC-CXX.cmake .

To check the default settings, create the CompilerOptions.cmake file in the project directory with the following contents:

 # log all *_INIT variables get_cmake_property(_varNames VARIABLES) list (REMOVE_DUPLICATES _varNames) list (SORT _varNames) foreach (_varName ${_varNames}) if (_varName MATCHES "_INIT$") message(STATUS "${_varName}=${${_varName}}") endif() endforeach() 

Then initialize the CMAKE_USER_MAKE_RULES_OVERRIDE variable in CMakeLists.txt :

 # CMakeLists.txt cmake_minimum_required(VERSION 3.8) set (CMAKE_USER_MAKE_RULES_OVERRIDE "${CMAKE_CURRENT_LIST_DIR}/CompilerOptions.cmake") project(foo) add_executable(foo foo.cpp) 

When a project is configured when opening a directory in Visual Studio 2017, the following information will be displayed in the IDE output window:

  ... -- CMAKE_CXX_FLAGS_DEBUG_INIT= /MDd /Zi /Ob0 /Od /RTC1 -- CMAKE_CXX_FLAGS_INIT= /DWIN32 /D_WINDOWS /W3 /GR /EHsc -- CMAKE_CXX_FLAGS_MINSIZEREL_INIT= /MD /O1 /Ob1 /DNDEBUG -- CMAKE_CXX_FLAGS_RELEASE_INIT= /MD /O2 /Ob2 /DNDEBUG -- CMAKE_CXX_FLAGS_RELWITHDEBINFO_INIT= /MD /Zi /O2 /Ob1 /DNDEBUG ... 

Thus, the warning option /W3 is selected from the CMake variable CMAKE_CXX_FLAGS_INIT , which is then applied to all CMake targets generated in the project.

To control the warning level on a CMake project or target level, you can change the CMAKE_CXX_FLAGS_INIT variable in CompilerOptions.cmake by adding the following lines to the file:

 if (MSVC) # remove default warning level from CMAKE_CXX_FLAGS_INIT string (REGEX REPLACE "/W[0-4]" "" CMAKE_CXX_FLAGS_INIT "${CMAKE_CXX_FLAGS_INIT}") endif() 

Then the warning flags can be controlled by setting the target compilation options in CMakeLists.txt :

 ... add_executable(foo foo.cpp) target_compile_options(foo PRIVATE "/W4") 

For most CMake projects, it makes sense to control the default compiler settings in the override file instead of manually setting variables such as CMAKE_CXX_FLAGS .

When making changes to the CompilerOptions.cmake file, you must recreate the build folder. When using Visual Studio 2017 in Open Folder mode, select the Cache ... -> Delete Cache Folders command in the CMake menu, and then Cache ... -> Generate in the CMake menu to recreate the build folder.

+7
source

Turn my comment into a response

CMake has some compiler presets. For a visual studio, these are mainly standard link libraries, warning levels, optimization levels, exception handling, debugging information, and platform-specific definitions.

What you now need to distinguish when you want to change the settings of the CMake compiler are the following use cases:

  • Additional Compiler Flags CMake Does Not Detect or Modify CMake Preset Settings
  • Project default settings or parameters defined by the project user

So, let's discuss common solutions for these cases.


User Modifies / Adds Project / CMake Default Compiler Flags

The standard way is to change the flag variables of cached compilers using the tools provided with CMake, such as cmake-gui and ccmake .

To achieve this in Visual Studio, you need to:

  • CMake / Cache / View CMakeCache
  • Manually change, for example. CMAKE_CXX_FLAGS before /Wall

    CMakeCache.txt

     //Flags used by the compiler during all build types. CMAKE_CXX_FLAGS:STRING= /DWIN32 /D_WINDOWS /Wall /GR /EHsc 
  • CMake / Cache / Generate


Or you set the CMAKE_CXX_FLAGS cache CMAKE_CXX_FLAGS through the CMakeSettings.json file:

  • CMake / Change CMake Settings

    Insert a cache entry with -DCMAKE_CXX_FLAGS:STRING=... in cmakeCommandArgs

    CMakeSettings.json

     { // See https://go.microsoft.com//fwlink//?linkid=834763 for more information about this file. "configurations": [ { "name": "x86-Debug (all warnings)", "generator": "Visual Studio 15 2017", "configurationType": "Debug", "buildRoot": "${env.LOCALAPPDATA}\\CMakeBuild\\${workspaceHash}\\build\\${name}", "cmakeCommandArgs": "-DCMAKE_CXX_FLAGS:STRING=\"/DWIN32 /D_WINDOWS /Wall /GR /EHsc\"", "buildCommandArgs": "-m -v:minimal" } ] } 
  • If you deliver this CMakeSettings.json file with your CMake project, it becomes permanent


Project changes in the default CMake compiler flags

If you want to keep most of the CMake compiler flags, the answer to @sakra is definitely suitable.

For my VS projects, I put the CXX flag settings in the tool binding file that comes with the project itself. Basically, to freeze these settings and not depend on the version of CMake or any environment variables.

Taking an example from above, it will look like this:

VS2017Toolchain.cmake

 set(CMAKE_CXX_FLAGS "/DWIN32 /D_WINDOWS /Wall /GR /EHsc" CACHE INTERNAL "") 

CMakeSettings.json

  { // See https://go.microsoft.com//fwlink//?linkid=834763 for more information about this file. "configurations": [ { "name": "x86-Debug (all warnings)", "generator": "Visual Studio 15 2017", "configurationType": "Debug", "buildRoot": "${env.LOCALAPPDATA}\\CMakeBuild\\${workspaceHash}\\build\\${name}", "cmakeCommandArgs": "-DCMAKE_TOOLCHAIN_FILE:FILEPATH=\"${projectDir}\\VS2017Toolchain.cmake\"", "buildCommandArgs": "-m -v:minimal" } ] } 

References

+2
source

Source: https://habr.com/ru/post/1272613/


All Articles