CMake visual studio debug/release config

26,002

Solution 1

1:

if(CMAKE_BUILD_TYPE STREQUAL "Debug")
  add_definitions(/DYOURDEFINITION)
endif()

2: If i understood you right, you need to create an option variable

option(USE_OPENGL "Use OpenGL or DirectX")

And then check for it when you are adding new target:

if(USE_OPENGL)
add_subdirectory(OpenGL)
else()
add_subdirectory(DirectX)
endif()

Of course, you should create CMakeLists.txt in OpenGL/ and DirectX/ dirs.

Solution 2

  1. How can I set a preprocessor define for Release and another for Debug?

The proper way to do this is to set the COMPILE_DEFINITIONS property at the correct scope using generator expressions.

If you want to add definitions to all targets like add_definitions() does then use:

  set_property(DIRECTORY APPEND PROPERTY COMPILE_DEFINITIONS
    $<$<CONFIG:DebugOpenGL>:_DEBUG>
    $<$<CONFIG:ReleaseOpenGL>:NDEBUG>
    $<$<CONFIG:DebugDirectX>:_DEBUG>
    $<$<CONFIG:ReleaseDirectX>:NDEBUG>
  )

  set_property(DIRECTORY APPEND PROPERTY COMPILE_DEFINITIONS
    $<$<CONFIG:DebugOpenGL>:TE_USE_OPENGL>
    $<$<CONFIG:ReleaseOpenGL>:TE_USE_OPENGL>
    $<$<CONFIG:DebugDirectX>:TE_USE_DIRECTX>
    $<$<CONFIG:ReleaseDirectX>:TE_USE_DIRECTX>
  )

You can also set COMPILE_DEFINITIONS for just a target or a specific source file. See set_property.

In order to set other compile flags you can set the COMPILE_OPTIONS property on a directory, target, or source file just like above. However you can also use the add_compile_options() command because unlike add_definitions() it supports generator expressions. You can set COMPILE_OPTIONS for targets as well, or use target_compile_options(). For source files, as of CMake 3.3, you still have to set the COMPILE_FLAGS property.

  set(MY_DEBUG_OPTIONS /MDd /Zi /Ob0 /Od /RTC1)
  set(MY_RELEASE_OPTIONS /MD /Ob2 /O2)

  add_compile_options(
    "$<$<CONFIG:DebugOpenGL>:${MY_DEBUG_OPTIONS}>"
    "$<$<CONFIG:ReleaseOpenGL>:${MY_RELEASE_OPTIONS}>"
    "$<$<CONFIG:DebugDirectX>:${MY_DEBUG_OPTIONS}>"
    "$<$<CONFIG:ReleaseDirectX>:${MY_RELEASE_OPTIONS}>"
  )

Note that putting lists of options inside these generator expressions requires the quotes in add_compile_options().

  1. I have a project with opengl and directx so for DebugOpenGL and ReleaseOpenGL i want to exclude all directx cpp/h files from the buld. With DebugDirectX and ReleaseDirectx exclude the opengl files. How do I set this up?

This may be a problem. Although it's possible to use generator expressions to add source files to a target conditionally, I don't know of any IDEs that support per-configuration source files. Visual Studio and CMake's Visual Studio generator does not support it. Xcode and the Xcode generator also does not support this. So if you want to build with Visual Studio or another IDE you can't do this.

Generators that use a single configuration at a time such as the makefile or ninja generators should support this just fine.

Instead of having the source files differ between configurations there are several other options. Here are a couple.

You can have multiple targets and have the source differ between them:

set(OPENGL_SOURCES src/opengl/func1.cpp src/opengl/func2.cpp)
set(DIRECTX_SOURCES src/opengl/func1.cpp src/opengl/func2.cpp)

add_executable(opengl_foo ${COMMON_SOURCES} ${OPENGL_SOURCES})
add_executable(directx_foo ${COMMON_SOURCES} ${DIRECTX_SOURCES})

Note that this means you can go back to just having Debug and Release configs which will simplify the rest of your configuration as well.

Alternatively, you can keep your seperate OpenGL and DirectX configs by using some indirection in your source code. Have some 'dummy' cpp files and header files that switch between #includeing your opengl files or directx files based on a preprocessor define:

// src/func1.h
#ifdef TE_USE_OPENGL
#  include "opengl/func1.h.inc"
#elif defined(TC_USE_DIRECTX)
#  include "directx/func1.h.inc"
#endif

// src/func1.cpp
#ifdef TE_USE_OPENGL
#  include "opengl/func1.cpp.inc"
#elif defined(TC_USE_DIRECTX)
#  include "directx/func1.cpp.inc"
#endif

And then simply reference these dummy files in CMake:

add_executable(foo src/func1.h src/func1.cpp)

Now building different configs will end up pulling in different code. Also if you go ahead and rename the files to end in .inc you can even reference them in add_executable() so that they show up in VS but VS won't try to build them directly.

Solution 3

if(CMAKE_BUILD_TYPE STREQUAL "Debug")
  add_definitions(/DYOURDEFINITION)
endif()

won't work within an MSVS multi-config solution context. For that you need

set(MY_DEFINITION 
    $<$<CONFIG:Debug>:definition_for_debug>
    $<$<CONFIG:RelWithDebInfo>:definition_for_rel_with_debug>
    $<$<CONFIG:Release>:definition_for_release> 
    $<$<CONFIG:MinSizeRel>:definition_for_tight_release>
    )
Share:
26,002
bitgregor
Author by

bitgregor

Updated on September 19, 2020

Comments

  • bitgregor
    bitgregor over 3 years

    I'm setting up my visual studio project to use CMake, but I got two issues I haven't been able to solve yet.

    1 How can I set a preprocessor define for Release and another for Debug?

    2 I have a project with opengl and directx so for DebugOpenGL and ReleaseOpenGL i want to exclude all directx cpp/h files from the buld. With DebugDirectX and ReleaseDirectx exclude the opengl files. How do I set this up?

    EDIT:

    Heres what I got for 1. so far:

    cmake_minimum_required(VERSION 2.8)
    
    project(TEngine)
    
    if(CMAKE_CONFIGURATION_TYPES AND MSVC)
    #DebugOpenGL flags
    set(CMAKE_CXX_FLAGS_DEBUGOPENGL "/D_DEBUG /MDd /Zi /Ob0 /Od /RTC1" CACHE STRING "Flags used by the C++ compiler during maintainer builds." FORCE)
    set(CMAKE_C_FLAGS_DEBUGOPENGL "/D_DEBUG /MDd /Zi  /Ob0 /Od /RTC1" CACHE STRING "Flags used by the C compiler during maintainer builds." FORCE)
    set(CMAKE_EXE_LINKER_FLAGS_DEBUGOPENGL "/debug /INCREMENTAL" CACHE STRING "Flags used for linking binaries during maintainer builds." FORCE )
    set(CMAKE_SHARED_LINKER_FLAGS_DEBUGOPENGL "/debug /INCREMENTAL" CACHE STRING "Flags used by the shared libraries linker during maintainer builds." FORCE )
    
    #ReleaseOpenGL flags
    set(CMAKE_CXX_FLAGS_RELEASEOPENGL "/MD /O2 /Ob2 /D NDEBUG" CACHE STRING "Flags used by the C++ compiler during maintainer builds." FORCE)
    set(CMAKE_C_FLAGS_RELEASEOPENGL "/MD /O2 /Ob2 /D NDEBUG" CACHE STRING "Flags used by the C compiler during maintainer builds." FORCE)
    set(CMAKE_EXE_LINKER_FLAGS_RELEASEOPENGL "/INCREMENTAL:NO" CACHE STRING "Flags used for linking binaries during maintainer builds." FORCE )
    set(CMAKE_SHARED_LINKER_FLAGS_RELEASEOPENGL "/INCREMENTAL:NO" CACHE STRING "Flags used by the shared libraries linker during maintainer builds." FORCE )
    
    #DebugDirectX flags
    set(CMAKE_CXX_FLAGS_DEBUGDIRECTX "/D_DEBUG /MDd /Zi /Ob0 /Od /RTC1" CACHE STRING "Flags used by the C++ compiler during maintainer builds." FORCE)
    set(CMAKE_C_FLAGS_DEBUGDIRECTX "/D_DEBUG /MDd /Zi  /Ob0 /Od /RTC1" CACHE STRING "Flags used by the C compiler during maintainer builds." FORCE)
    set(CMAKE_EXE_LINKER_FLAGS_DEBUGDIRECTX "/debug /INCREMENTAL" CACHE STRING "Flags used for linking binaries during maintainer builds." FORCE )
    set(CMAKE_SHARED_LINKER_FLAGS_DEBUGDIRECTX "/debug /INCREMENTAL" CACHE STRING "Flags used by the shared libraries linker during maintainer builds." FORCE )
    
    #ReleaseDirectx flags
    set(CMAKE_CXX_FLAGS_RELEASEDIRECTX "/MD /O2 /Ob2 /D NDEBUG" CACHE STRING "Flags used by the C++ compiler during maintainer builds." FORCE)
    set(CMAKE_C_FLAGS_RELEASEDIRECTX "/MD /O2 /Ob2 /D NDEBUG" CACHE STRING "Flags used by the C compiler during maintainer builds." FORCE)
    set(CMAKE_EXE_LINKER_FLAGS_RELEASEDIRECTX "/INCREMENTAL:NO" CACHE STRING "Flags used for linking binaries during maintainer builds." FORCE )
    set(CMAKE_SHARED_LINKER_FLAGS_RELEASEDIRECTX "/INCREMENTAL:NO" CACHE STRING "Flags used by the shared libraries linker during maintainer builds." FORCE )
    
    set(CMAKE_CONFIGURATION_TYPES "DebugOpenGL;ReleaseOpenGL;DebugDirectX;ReleaseDirectX")
    set(CMAKE_CONFIGURATION_TYPES "${CMAKE_CONFIGURATION_TYPES}" CACHE STRING
    "Reset the configurations to what we need"
    FORCE)
    
    if(CMAKE_BUILD_TYPE STREQUAL "DebugOpenGL")
        add_definitions(/DTE_USE_OPENGL)
    endif()
    if(CMAKE_BUILD_TYPE STREQUAL "ReleaseOpenGL")
        add_definitions(/DTE_USE_OPENGL)
    endif()
    if(CMAKE_BUILD_TYPE STREQUAL "DebugDirectX")
        add_definitions(/DTE_USE_OPENGL)
    endif()
    if(CMAKE_BUILD_TYPE STREQUAL "ReleaseDirectX")
        add_definitions(/DTE_USE_OPENGL)
    endif()
    endif()
    
    set(Boost_ADDITIONAL_VERSIONS "1.47" "1.47.0")
    set(BOOST_ROOT "${TEngine_SOURCE_DIR}/Externals/boost_1_47_0")
    
    if(WIN32)
        add_definitions(-DTEWINDOWS)
    elseif(LINUX)
        add_definitions(-DTELINUX -DTE_USE_OPENGL)
    endif()
    
    subdirs(TEEngineTest TECore TEGraphics TEPhysics TEngine)
    
  • bitgregor
    bitgregor over 12 years
    I dont have the files in different sub folders though.. and I want the files in the project, but for the opengl configurations I want to exclude the directx cpp/h files.. and for directx configurations I want to exclude the opengl files.. In visual studio you can right click on a file and select exclude from build.. 1. answers the first question thanks :)
  • arrowd
    arrowd over 12 years
    No problem, just substitute add_subdirectory() call from my answer with set(SOURCES Opengl1.cpp Opengl2.cpp etc). In else branch do set(SOURCES DirectX1.cpp DirectX2.cpp etc). Finally, outside of if clause create your build target by passing ${SRCS} to it.
  • André
    André over 12 years
    Great answer arrowdodger... Just a little addition: If you use set( SOURCES ) with some if-else clause in CMake, the "deselected" source files will not show up in Visual Studio.
  • André
    André over 12 years
    And another addition: when running cmake from commandline, CMAKE_BUILD_TYPE is NOT defined, hence the check in 1) will likely fail. Perhaps a better approach would be to use the COMPILE_DEFINITIONS property where you can distinguish the Configuration... Although I must admit that it is not the most elegant solution
  • bitgregor
    bitgregor over 12 years
    I'm trying with 1. now.. I'm building with the gui version for windows.. the configurations are set up but the configurations does not have the preprocessor defines set.. I've edited the initial post with what I got
  • bitgregor
    bitgregor over 12 years
    Don't I have to loop through the configurations somehow? I would think CMAKE_BUILD_TYPE is always set to the same there?
  • ulatekh
    ulatekh over 2 years
    "Although it's possible to use generator expressions to add source files to a target conditionally, I don't know of any IDEs that support per-configuration source files." Visual Studio allows that, either by putting a condition on the <ItemGroup> tag, or an <ExcludedFromBuild> element (with a condition) under the item's entry itself.