5

I have a C++ CMake project that is compiled both on Linux and Windows. On Windows, this is done via Visual Studio/MSVCC.

In CMAKE and in VS, the build is set up as Debug, but it seems that no debug symbols are ever being made in the VS build - so debugging is impossible.

When looking over the Detailed output for VS, I saw this:

cl : command line warning D9002: ignoring unknown option '-g'

That suggests to me that it doesn't recognize the -g flag like GCC/Clang do.

Here is the CMake arguments:

SET(CMAKE_CXX_STANDARD 17) SET(CMAKE_CXX_STANDARD_REQUIRED ON) SET(BUILD_MODE Debug) SET(CMAKE_CXX_FLAGS "-Wall") SET(CMAKE_CXX_FLAGS_DEBUG "-g") SET(CMAKE_CXX_FLAGS_RELEASE "-O3") 

How do I make this compatible with Visual Studio? I've tried looking all over, but most related posts seem to be about C#/.net, or much older versions of VS.

The project does use the QT library if that matters.

UPDATE:

It turns out BUILD_MODE was something added by someone else so that each sub-project would not individually need to be set to release or debug, we could just set it once in the root level Cmakelists. They did all actually use CMAKE_BUILD_TYPE as intended.

Also, the answers here were correct. Setting the CMAKE_CXX_FLAGS directly was wiping away the defaults, causing the Debug build to not have options like /Zi in MSVCC, preventing debug symbols and all debugging. It also introduced an unrecognized flag "-g" which MSVCC couldn't understand.

I completely remove the SET_CXX_FLAGS from every Cmakelists.txt in the project, and everything is working perfectly.

Should I need to add to them, I will use the _INIT option as suggested.

4
  • Do you open Visual Studio in CMake mode or just generate a VS project out of the CMake configuration? Commented Sep 1, 2022 at 17:27
  • "Cmake mode"? I'm not sure what that is. I just use the CMake GUI and use "Configure", "Generate" and finally "Open Project" which opens it in VS. That does create .vcxproj files. Commented Sep 1, 2022 at 17:29
  • You can just open a folder where the CMake project is located with Visual Studio and it will work without VS-specific files. For generated part i'm not quite following how this problem happens. VS allows you to switch between debug/release configurations right from UI, you don't need to set any flags in CMakeLists.txt or CMake for that Commented Sep 1, 2022 at 17:32
  • I'm not sure. At the time, it seemed cleaner to have debug and release have completely separate build folders, which had to be configured/generated seperately, and would only show VS their relevant build type (debug or release). Commented Sep 1, 2022 at 17:37

2 Answers 2

3

You have to compile with a different mode set with CMAKE_BUILD_TYPE as in

cmake -DCMAKE_BUILD_TYPE=DEBUG <sourcedir> 

You never set those flags directly. If you want to add a new flag to a debug mode like for example a stack protector, you should use the *_INIT variables.

You can further distinguish which OS you are running with the UNIX, WIN32 and MSVC cmake boolean predefined constants:

if ( UNIX ) set( CMAKE_CXX_FLAGS_DEBUG_INIT "-fstack-protector" ) elseif( WIN32 ) set( CMAKE_CXX_FLAGS_DEBUG_INIT "/GS" ) endif() 
Sign up to request clarification or add additional context in comments.

7 Comments

I don't follow. I configure/generate the CMake using the Cmake GUI. Is the option SET(BUILD_MODE Debug) in the top-level CMakeLists.txt not equivalent to the command you listed? So "INIT" adds to the flags, rather than replacing them? Is that why this is failing, all the default flags for debug builds are getting overwritten? How do I know what the default flags will be?
It's not BUILD_MODE but CMAKE_BUILD_TYPE. And yes, you are likely overriding the flags. You can set the default flags with CMAKE_CXX_FLAGS_DEBUG.
You can query the flags with cmake -LH <source>
Would SET(CMAKE_BUILD_TYPE Debug) also work in the cmakelists.txt?
Yes but you need to set it as a cache variable BEFORE the first project() line in CMakeLists.txt. As in set(CMAKE_BUILD_TYPE "RELEASE" CACHE STRING "Sets release build by default")
|
0

There should be no need to define -O3 and -g explicitly in cmake. Setting those may prevent the code from working with other compilers, as you've seen. Those 2 options are the default anyways.

To build one of the configurations using unix makefiles you simply set the CMAKE_BUILD_TYPE cache variable during configuration:

(I'm assuming the generators mentioned are the default generators below.)

cmake -D CMAKE_BUILD_TYPE=Debug -S ... -B buildDir 

or

cmake -D CMAKE_BUILD_TYPE=Debug -S ... -B buildDir 

and to build the project you use

cmake --build buildDir 

The visual studio is differnet insofar that the generated project covers all configurations at once. You specify the configuration to work with when building (or installing) the project instead:

cmake -A x64 -S ... -B buildDir 
cmake --build buildDir --config Release cmake --build buildDir --config Debug 

Alternatively you can simply open the generated solution in the IDE.

cmake --open buildDir 

For compiler specific flags you may need to make a case distinction:

if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") add_compile_options(/Wall) elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") add_compile_options(-Wall) endif() 

4 Comments

I'm a bit confused about using the cmake commands. So far whenever I've made changes, I've done so either through the CMAKE GUI, or by directly editing the relevant cmakelists. How does those commands interact with that?
@TylerShellberg The cmake gui should simply be the equivalent of the cmake configuration step (the commands with -S and -B). There's a table occuring in the gui where you can set the cache variables (the -D CMAKE_BUILD_TYPE=... part). The commands with --build are the equivalent of the make command mentioned in many cmake examples or to the Build Solution functionality. In general you should aim at leaving as many choices to the user as possible instead of restricting the uses.
If SET(BUILD_MODE Debug) is an attempt to set the build configuration, this is incorrect and also error prone and makes the project inflexible: Setting CMAKE_BUILD_TYPE only works, if done before the first project command and hardcoding the value prevents the user from working with the same cmake sources with multiple configurations in parallel.
@TylerShellberg Here's the documentation of the cmake command line tool btw: cmake.org/cmake/help/latest/manual/cmake.1.html the uses I mentioned in the answer are "Generate a Project Buildsystem" and "Build a Project". A minimalistic usage example is available here: cmake.org/cmake/help/latest/guide/user-interaction/…

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.