Optimize in CMake by default

I have a C ++ project that uses CMake as its build system. I need the following behavior:

If cmake is called as cmake .. , then CMAKE_CXX_FLAGS is -O3 -Wall -Wextra

If cmake is called 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 call is used, then both the -O3 and -g flags are passed to the compiler. Also, if I use the second call and the first after that, CMAKE_BUILD_TYPE remains Debug , although it is not explicitly ordered so that is why I get the Debug assembly, although I want an optimized assembly.

Why? What can I do to achieve the desired behavior?

+5
source share
2 answers

First: the recommended use of CMake should always specify CMAKE_BUILD_TYPE explicitly on the command line (if and only if a generator with one configuration is used). Your use case deviates from this best practice, so consider this answer as โ€œhow you can do it,โ€ not necessarily as โ€œhow you should do it.โ€

To solve the first problem, you should be able to do this at the beginning of 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 the type of assembly at all, โ€œReleaseโ€ will be selected by default, and thus CMAKE_CXX_FLAGS_RELEASE will be used.

The second is harder to solve. Variables passed from the command line (for example, CMAKE_BUILD_TYPE=Debug ) are cached by CMake and therefore reused in subsequent calls (which is necessary since CMake can re-run itself if you change its inputs between assemblies).

The only solution is to get the user to switch the build type again using cmake .. -DCMAKE_BUILD_TYPE=Release .

Think about why this is necessary: โ€‹โ€‹as I said, CMake can rerun itself as part of the assembly if the CMake input ( CMakeLists.txt files or their dependencies) has changed since the last CMake was launched. In this case, it will also start without command line arguments such as -DCMAKE_BUILD_TYPE=whatever , and will rely on the cache to provide the same value as the last time. This scenario is indistinguishable from the fact that you manually run cmake .. with no additional arguments.

I could provide a hacker solution to always reset CMAKE_BUILD_TYPE to Release , unless explicitly indicated on the command line. However, this would also mean that the assembly generated as Debug would be regenerated as Release if automatic regeneration occurred. I am sure that is not what you want.

+11
source

For CXX flags defined for the Release target, you must set CMAKE_CXX_FLAGS_RELEASE
instead of CMAKE_CXX_FLAGS

In your case, you can use:

set (CMAKE_CXX_FLAGS "-Wall -Wextra")
set (CMAKE_CXX_FLAGS_DEBUG "-g")
set (CMAKE_CXX_FLAGS_RELEASE "-O3")

The more modern CMake approach (which I suggest if you are using CMake version 2.8.12 or later) is well described in fooobar.com/questions/46316 / ... and includes the use of target_compile_options .

+4
source

Source: https://habr.com/ru/post/1261984/


All Articles