Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to create a CMake variable that takes a default value unless explicitly overriden?

I have a C++ project that is built using CMake. I would like the build configuration in CMakeLists.txt to be such that it builds in Release mode by default, and builds in Debug mode only when explicitly specified.

Referring to this and this, to allow the build type to be specified from the command line, I have set the variable as follows:

set(CMAKE_BUILD_TYPE Release CACHE STRING "")

However, this caches the build type from the last build, so if the last build was Debug, I need to explicitly specify Release in the next build.

I tried using FORCE and also tried adding

unset(CMAKE_BUILD_TYPE CACHE)

before the set(), but both these methods fix the value to Release and override the value specified by the user.

Is there a way to achieve this? Thank you.


The following is an MCVE:

CMakeLists.txt

cmake_minimum_required(VERSION 3.10)
set(CMAKE_CXX_STANDARD 11)
project(Test LANGUAGES CXX)

set(CMAKE_BUILD_TYPE Release CACHE STRING "")
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DDEBUG")

file(GLOB SOURCES *.cpp)

add_executable(test ${SOURCES})

test.cpp

#include <iostream>

int main() {
#ifdef DEBUG
    std::cout << "Debug defined" << std::endl;
#else
    std::cout << "Debug not defined" << std::endl;
#endif
    return 0;
}

To build, I use

cmake .
make

The first step could have -DCMAKE_BUILD_TYPE=Debug for Debug mode.

like image 918
GoodDeeds Avatar asked Nov 05 '18 17:11

GoodDeeds


People also ask

How do you set a variable value in CMake?

You can use the command line to set entries in the Cache with the syntax cmake -D var:type=value , just cmake -D var=value or with cmake -C CMakeInitialCache. cmake . You can unset entries in the Cache with unset(... CACHE) .

What is cache variable in CMake?

The CMake cache may be thought of as a configuration file. The first time CMake is run on a project, it produces a CMakeCache. txt file in the top directory of the build tree. CMake uses this file to store a set of global cache variables, whose values persist across multiple runs within a project build tree.

What is ${} in CMake?

Local Variables You access a variable by using ${} , such as ${MY_VARIABLE} . 1. CMake has the concept of scope; you can access the value of the variable after you set it as long as you are in the same scope. If you leave a function or a file in a sub directory, the variable will no longer be defined.

What is PARENT_SCOPE in CMake?

You can use PARENT_SCOPE option when you set a value to the variable in the child. Here is the example. # child CMakeLists.txtset(A "Child" PARENT_SCOPE) This tells CMake to update the original A variable which is in the scope of the parent.


1 Answers

You can use something like this:

if(NOT CMAKE_BUILD_TYPE)
    set(CMAKE_BUILD_TYPE Release)
endif()

That way, if nothing is specified to CMake, it will use whatever value you set here, and the provided value otherwise.

To prevent this from being used for all the subsequent builds, add

unset(CMAKE_BUILD_TYPE CACHE)

towards the end of your script, so that it removes any cached value and rely on either the default or the provided one.

like image 152
JBL Avatar answered Sep 20 '22 07:09

JBL