Debug vs Release in CMake
With CMake, it's generally recommended to do an "out of source" build. Create your CMakeLists.txt
in the root of your project. Then from the root of your project:
mkdir Release
cd Release
cmake -DCMAKE_BUILD_TYPE=Release ..
make
And for Debug
(again from the root of your project):
mkdir Debug
cd Debug
cmake -DCMAKE_BUILD_TYPE=Debug ..
make
Release
/ Debug
will add the appropriate flags for your compiler. There are also RelWithDebInfo
and MinSizeRel
build configurations.
You can modify/add to the flags by specifying a toolchain file in which you can add CMAKE_<LANG>_FLAGS_<CONFIG>_INIT
variables, e.g.:
set(CMAKE_CXX_FLAGS_DEBUG_INIT "-Wall")
set(CMAKE_CXX_FLAGS_RELEASE_INIT "-Wall")
See CMAKE_BUILD_TYPE for more details.
As for your third question, I'm not sure what you are asking exactly. CMake should automatically detect and use the compiler appropriate for your different source files.
What are CMAKE_BUILD_TYPE: Debug, Release, RelWithDebInfo and MinSizeRel?
RelWithDebInfo is the same as Release, allowing you to have symbol files for debugging.
For example in Visual Studio, you'll have .pdb
files and without them, it'll be hard to debug because all the signatures in the binary files are not going to be human readable and there's no way to map them to the source code.
MinSizeRel is the same as Release, with its optimization configuration just set to Minimize Size
instead of Maximize Speed
as illustrated in this link in Visual Studio, for example.
If I want to generate a production build, should I choose Release?
Yes, that should do the right job for you. Debug/Release are the most commonly used options.
Reading this CMAKE FAQ will actually help you a lot.
CMake conditional for Release,Debug and Etc
Variable CMAKE_BUILD_TYPE
has no sense with multiconfiguration generators, and Visual Studio is one of such generators.
Canonical way for define in CMake a pre-built library which have different locations for different configuration is to create IMPORTED library target with several properties IMPORTED_LOCATION_<CONFIG> to be set:
add_library(thirdPartyLib IMPORTED UNKNOWN)
set_target_properties(thirdPartyLib PROPERTIES
IMPORTED_LOCATION_RELEASE
${CMAKE_CURRENT_SOURCE_DIR}/external_libs/mylibalpha/win64/release/libalpha.a
IMPORTED_LOCATION_DEBUG
${CMAKE_CURRENT_SOURCE_DIR}/external_libs/mylibalpha/win64/debug/libalpha.a
)
Then you need to create a mapping between build types of the main project and build types of the IMPORTED target.
Such mapping could be created either on per-target basis, by setting properties MAP_IMPORTED_CONFIG_<CONFIG>:
set_target_properties(thirdPartyLib PROPERTIES
# For Debug version of the project use DEBUG-suffixed library location
MAP_IMPORTED_CONFIG_DEBUG DEBUG
# For Release version of the project use RELEASE-suffixed library location
MAP_IMPORTED_CONFIG_RELEASE RELEASE
# For ReleaseWithDebInfo version of the project use DEBUG-suffixed library location
MAP_IMPORTED_CONFIG_RELWITHDEBINFO DEBUG
# For MinSizeRel version of the project use RELEASE-suffixed library location
MAP_IMPORTED_CONFIG_MINSIZEREL RELEASE
)
Alternatively, the mapping could be created for all IMPORTED targets by setting variables CMAKE_MAP_IMPORTED_CONFIG_<CONFIG>. Note, that these variables should be set before creation of IMPORTED target(s).
# For Debug version of the project use DEBUG-suffixed locations of IMPORTED targets
set(CMAKE_MAP_IMPORTED_CONFIG_DEBUG DEBUG)
# For Release version of the project use RELEASE-suffixed locations of IMPORTED targets
set(CMAKE_MAP_IMPORTED_CONFIG_RELEASE RELEASE)
# For ReleaseWithDebInfo version of the project use DEBUG-suffixed locations of IMPORTED targets
set(CMAKE_MAP_IMPORTED_CONFIG_RELWITHDEBINFO DEBUG)
# For MinSizeRel version of the project use RELEASE-suffixed locations of IMPORTED targets
set(CMAKE_MAP_IMPORTED_CONFIG_MINSIZEREL RELEASE)
Having IMPORTED libraries and configurations mapping, using these libraries is quite straightforward:
target_link_libraries(my_exe PRIVATE thirdPartyLib)
Depending on the build type of the project, CMake will automatically select proper library for linking.
Detect build type (debug/release) in visual studio when using CMake
You may want to use generator expressions here. They are evaluated at build time and therefore the build type is set even for multi-configuration generators as Visual Studio or Xcode.
target_compile_definitions(OverEngine
PRIVATE
_CRT_SECURE_NO_WARNINGS
GLFW_INCLUDE_NONE
PUBLIC
$<$<CONFIG:Debug>:OE_DEBUG>
$<$<CONFIG:RelWithDebInfo>:OE_DEBUG>
$<$<CONFIG:Release>:OE_RELEASE>
$<$<CONFIG:MinSizeRel>:OE_RELEASE>
)
Cmake create a Makefile supports debug and release with different configuration
In this CMakeLists.txt
file you set up a second version of the project during the configuration of the original project that is responsible for generating another version of the project for the release version. There are several drawbacks to this approach:
- Doesn't deal with multi configuration generators(e.g. Visual Studio), properly
- It sets up the release configuration twice, if you pass
-DCMAKE_BUILD_TYPE=Release
to the original setup. - It shares the same binary directory; This could very easily mess up the project badly
My recommendation would be to use generator expressions in all places where they are allowed
target_link_libraries(my_target PRIVATE
$<$<CONFIG:Release>:libLinkedInReleaseOnly>
$<$<CONFIG:Debug>:libLinkedInDebugOnly>
)
# define preprocessor macro containg the configuration name
target_compile_definitions(my_target PRIVATE MY_CONFIG_DEFINE=\"$<CONFIG>\")
and fall back to versions of properties and variables that are configuration dependent (i.e. include <CONFIG>
in the linked lists) and setting up projects in multiple build directories with different configurations.
#bash example
for CONFIG in Debug Release
do
mkdir $CONFIG
cmake -D CMAKE_BUILD_TYPE=$CONFIG -S . -B $CONFIG
done
which allows you to do cmake --build Debug
or cmake --build Release
to build debug or release configurations of your project respectively. (You may want to set this up in a location different to the source dir btw which would require you to pass a different path as -S
parameter.)
How to build CMake Debug version using different target name for executables?
You are not missing anything. As the documentation says (emphasis mine):
When a non-executable target is created its
<CONFIG>_POSTFIX
target property is initialized with the value of this variable if it is set.
See: https://cmake.org/cmake/help/latest/variable/CMAKE_CONFIG_POSTFIX.html
By the sounds of it, though, you could manually set the property on your executable target with set_target_properties
:
set_target_properties(
target1 ... targetN
PROPERTIES
DEBUG_POSTFIX "${CMAKE_DEBUG_POSTFIX}"
)
Note, however, that it doesn't apply to executables by default because that's rarely what you want. For libraries, it's fairly common to package and deploy debug and release configurations simultaneously. On Windows, for development, it is a requirement. On the other hand, one very rarely needs to deploy debug applications and hence one very rarely wants a postfix applied.
Related Topics
Is Multiplication and Division Using Shift Operators in C Actually Faster
Should I Compile With /Md or /Mt
Stringstream, String, and Char* Conversion Confusion
Call a C Function from C++ Code
Difference Between Atan and Atan2 in C++
Can Virtual Functions Have Default Parameters
C++ Obtaining Milliseconds Time on Linux - Clock() Doesn't Seem to Work Properly
Dual Emission of Constructor Symbols
Magic Number in Boost::Hash_Combine
How to Propagate Exceptions Between Threads
How to Calculate the Week Number Given a Date
How to Deal With Mutexes in Movable Types in C++
High Resolution Timer With C++ and Linux
Why Does C++ Need a Separate Header File