I have a C++ project which uses CMake as its build system. I'd like the following behavior:
If cmake is invoked as cmake ..
, then CMAKE_CXX_FLAGS
is -O3 -Wall -Wextra
If cmake is invoked as cmake .. -DCMAKE_BUILD_TYPE=Debug
, then CMAKE_CXX_FLAGS
is -g -Wall -Wextra
I tried the following
message(STATUS "Build type: ${CMAKE_BUILD_TYPE}") set(CMAKE_CXX_FLAGS "-O3 -Wall -Wextra") set(CMAKE_CXX_FLAGS_DEBUG "-g -Wall -Wextra")
But this has a big problem. First of all, if the second invocation is used, then both -O3
and -g
flags are passed to the compiler. Besides, if I use the second invocation and the first thereafter, CMAKE_BUILD_TYPE
stays Debug
although not explicitly ordered so - so I get a Debug build although I want an optimized build.
Why? What can I do to get the desired behavior?
Build typesDebug (the default build type) Release. RelWithDebInfo (Release with debugging information) MinSizeRel (Release optimized for size)
(You can find an example Linux cross-compiling toolchain file here.) When you want to generate a build system with this toolchain, specify the CMAKE_TOOLCHAIN_FILE parameter on the command line: mkdir android-arm-build && cd android-arm-build cmake -DCMAKE_TOOLCHAIN_FILE=$(pwd)/../arm-linux-androideadi-gcc. cmake ..
CMake is a meta build system that uses scripts called CMakeLists to generate build files for a specific environment (for example, makefiles on Unix machines). When you create a new CMake project in CLion, a CMakeLists. txt file is automatically generated under the project root.
When CMake executes the project() call, it looks for a default compiler executable and determines the way for use it: default compiler flags, default linker flags, compile features, etc. And CMake stores path to that default compiler executable in the CMAKE_C_COMPILER variable.
First off: recommended usage of CMake is to always specify CMAKE_BUILD_TYPE
explicitly on the command line (if and only if using a single-configuration generator). Your use case deviates from this best practice, so treat this answer as "how you can do it," not necessarily as "how you should do it."
To address the first issue, you should be able to do this early in your CMakeList:
if(NOT CMAKE_BUILD_TYPE) set(CMAKE_BUILD_TYPE Release) endif() set(CMAKE_CXX_FLAGS "-Wall -Wextra") set(CMAKE_CXX_FLAGS_DEBUG "-g") set(CMAKE_CXX_FLAGS_RELEASE "-O3")
This will make sure that if you do not specify a build type at all, it will default to "Release" and thus CMAKE_CXX_FLAGS_RELEASE
will be used.
The second one is harder to tackle. Variables passed from the command line (such as CMAKE_BUILD_TYPE=Debug
) are cached by CMake and thus re-used in subsequent invocations (that is necessary, since CMake can re-trigger itself if you modify its inputs between builds).
The only solution is to make the user switch the build type explicitly again, using cmake .. -DCMAKE_BUILD_TYPE=Release
.
Consider why this is necessary: as I said, CMake can re-trigger itself as part of a build if CMake's input (CMakeLists.txt
files or their dependencies) has changed since last CMake ran. In such case, it will also be run without command-line arguments such as -DCMAKE_BUILD_TYPE=whatever
, and will rely on the cache to supply the same value as last time. This scenario is indistinguishable from you manually running cmake ..
without additional arguments.
I could provide a hacky solution to always reset CMAKE_BUILD_TYPE
to Release
if not specified explicitly on the command line. However, it would also mean that a buildsystem generated as Debug
would get re-generated as Release
if automatic re-generation happened. I am pretty sure that's not what you want.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With