[CMake] How to specify debug version of CRT library for Visual Studio generator?

Eric Dönges doenges at mvtec.com
Tue Jun 18 10:06:50 EDT 2019


On 18.06.19 12:53, David Aldrich wrote:
> I have a simple CMake project that builds an executable using Visual
> Studio 2017:


> 
> ################ Files ################
> #   --   Add files to project.   --   #
> #######################################
> 
> file(GLOB SRC_FILES
>     ${CPP_DIR_1}/*.cpp
>     ${CPP_DIR_2}/*.cpp
>     ${CPP_DIR_3}/*.cpp
>     ${CPP_DIR_4}/*.cpp
>     ${HEADER_DIR_1}/*.h
> )
> 
> # Add executable to build.
> add_executable(${PROJECT_NAME}
>    ${SRC_FILES}
> )
> 
> if(MSVC)
>    target_link_libraries(${PROJECT_NAME} ws2_32.lib )
> endif(MSVC)
> 
> #=====================================
> 
> The Release build succeeds but the Debug build fails with linker errors
> such as:
> 
> [build] CPlaneTest.obj : error LNK2001: unresolved external symbol
> __imp___CrtDbgReport
> 
> I think this is because the linker is not using the debug version of CRT
> (C Run-time Library).  
> 
> Should CMake select the debug build of CRT automatically or do I need to
> specify it manually? If so, should I do so using CMAKE_EXE_LINKER_FLAGS?
> 

CMake will select the correct CRT automatically if you let it (unless
you want the static CRT, in which case you have to override CMake's
default settings). You are setting your CMAKE_CXX_FLAGS_DEBUG incorrectly:

> if(MSVC)
>    #set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /D _DEBUG /W3
> /MD /Od /Zi /EHsc")
>    set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /W3 /GL /Od
> /Oi /Gy /Zi /EHsc")
>    set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_RELEASE} /D _DEBUG /W3
> /GL /Od /Oi /Gy /Zi /EHsc")
> endif(MSVC)

In case of the setting you've commented out, you are explicitly telling
CMake to use /MD. CMAKE_CXX_FLAGS_DEBUG should already contain /MDd, but
since you append the /MD, that is what the compiler will actually use.

For the setting that is not commented out, you set CMAKE_CXX_FLAGS_DEBUG
to the contents of CMAKE_CXX_FLAGS_RELEASE - which is certainly not what
you want (and also specifies /MD).

I would suggest looking at what flags CMake sets by default (look at the
Windows-MSVC.cmake file in CMake's 'Modules/Platform' directory) and
only setting those flags that CMake doesn't already. For version 3.14,
CMake should be setting the following flags for CMAKE_CXX_FLAGS_DEBUG by
default (assuming you are using MVSC >= 1310, no Clang toolset):

	/MDd /Zi /Ob0 /Od /GR /EHSC

So in your case, it would probably be enough to

	string(APPEND CMAKE_CXX_FLAGS_DEBUG " /D_DEBUG /W3")

As a final recommendation, use string(APPEND <var> ...) (or list(APPEND
<list> ...), if the variable is interpreted as a list) when appending
values to existing variables. This makes your intent clearer.


 - when appending compiler flags, use the "string(APPEND ...)" command
to make is clearer what you are doing).


More information about the CMake mailing list