CMake: Set different name for #cmakedefine variable - c++

I know you can use CMake's configure_file to make CMake variables available to your program. For example, I can use
#define ${CMAKE_BUILD_TYPE}
resulting in
#define Release
However, to keep my code more readible, I would prefer to define
#define BUILD_TYPE_RELEASE
Is there a simple way to achieve this?

Here is a fairly simple way to solve it:
In CMakesLists.txt:
if (NOT CMAKE_BUILD_TYPE)
set (CMAKE_BUILD_TYPE Release)
endif (NOT CMAKE_BUILD_TYPE)
string (TOUPPER ${CMAKE_BUILD_TYPE} BUILD_TYPE_NAME)
configure_file (config.h.in config.h)
And in config.h.in:
#define BUILD_TYPE_${BUILD_TYPE_NAME}
I am, however, still curious if there is a more elegant solution.

This is more a question of your preferred programming style (configuration files vs. compiler definitions).
In your case I would use add_definitions() or directly modify/append COMPILE_DEFINITIONS directory property (using generator expressions also supports multi-configuration environments):
set_property(
DIRECTORY
APPEND
PROPERTY
COMPILE_DEFINITIONS "BUILD_TYPE_$<UPPER_CASE:$<CONFIG>>"
)
Most simplified Debug/Release Check
You can also check what compiler definitions CMake does pre-define. Without having to modify/add something to your CMakeLists.txt files you could simply check for NDEBUG definition (set for Release builds across platforms) in you C/C++ code:
#ifdef NDEBUG
...
#endif
References
CMake: How to pass preprocessor macros
How to check if a CMake build directory build type is Debug or Release?
What predefined macro can be used to detect debug build with clang?

Related

Is there a cmake compile feature for c++17's charconv?

I have written some code that make use c++17's charconv, that I can compile just fine with g++ 9. Even though I have set the std to c++17 in my CMakeLists.txt, cmake insists on using c++ 7.5, which does not support charconv.
How do I tell cmake that I need a compiler that supports charconv ?
I see no switch in CMAKE_CXX_KNOWN_FEATURES.
Here is my CMakeLists.txt
cmake_minimum_required(VERSION 3.17)
file(GLOB CLIENT_SRC "srcs/*.cpp")
include_directories("includes")
add_executable(client ${CLIENT_SRC})
set_target_properties(client PROPERTIES OUTPUT_NAME "distff-client")
target_compile_features(client PUBLIC cxx_std_17 )
Not a cmake guy... and I don't really understand cmake's approach to compile features here. But in C++ in general, we now use feature-test macros to detect the presence of features. You're looking specifically for __cpp_lib_to_chars.
I think you want to require compilation of this program:
#if __has_include(<version>)
# include <version>
#elif __has_include(<charconv>)
# include <charconv>
#else
# error "neither <version> nor <charconv> available to test"
#endif
#ifndef __cpp_lib_to_chars
# error "tochars not implemented"
#endif
Which can probably be generalized to something you can configure_file() for an arbitrary library feature (just pull out the header name and the macro name, and probably also check for the macro having the minimum required value).
Either way, if you try_compile() the resultant source file, you could probably get the behavior you want?
Not a CMAKE expert, but the easiest would be to set the CXX environment variable. Like so:
export CXX="/usr/bin/x86_64-linux-gnu-g++-9"
see more at How to specify a compiler in CMake?

How to clear all defines from cmake?

I have project where I need some specific preprocessor definitions. Nothing less nothing more. I tried various solutions:
set(DEFINES MY_DEFINE)
target_compile_definitions(my_target PRIVATE ${DEFINES})
and
set(DEFINES -DMY_DEFINE)
add_definitions(${DEFINES})
even
set(DEFINES MY_DEFINE)
set_property(TARGET my_target PROPERTY CACHE COMPILE_DEFINITIONS ${DEFINES})
Every time cmake still injects some other defines:
WIN32
_WINDOWS
CMAKE_INTDIR="$(CONFIG)"
My target is static library and project generator is Visual Studio 2015 if it might influence anything. How can I get cmake to set only my defines?
Since those are platform specific defines in CMake, you can only remove them "globally" for your current CMakeList.txt scope (not for an idividual taret) with something like:
string(REGEX REPLACE "(-D|/D)[^ ]* " "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
Reference
Is Cmake set variable recursive?
In CMake, you can use remove_definitions for any definitions added via add_definitions. I'm not sure if that will work here, though, because cmake may not be adding them via add_definitions.
You could also potentially #undef those definitions at the very top of your C++ files. This is a little bit dirtier, but it might work.

C++ Macro defined from outside .cpp or .hpp

I want to do something like an application that is build in debug or release mode.
Is it possible to define a macro outside the .cpp or .hpp?
I am using CMake. I have seen that add_definitions(...) is doing something like this. Shall I create two executables proj and proj_debug and for debug define a macro with add_definitions(...)? Is this a good approach? If not, how would you suggest me to do?
Use something like this:
target_compile_definitions(myproj PRIVATE $<$<CONFIG:Debug>:MY_DEBUG_MACRO>)
http://www.cmake.org/cmake/help/v3.0/manual/cmake-generator-expressions.7.html
http://www.cmake.org/cmake/help/v3.0/command/target_compile_definitions.html
http://www.cmake.org/cmake/help/v3.0/manual/cmake-buildsystem.7.html
This works with all generators and is the documented, right, supported way of doing it (and implemented by me :) ).
Man g++ http://linux.die.net/man/1/g++
Look for the -D option for defining macros
and you can configure your makefiles to set that option http://www.cmake.org/Wiki/CMake_Useful_Variables
set(CMAKE_CXX_FLAGS "-g -Wall -Dxxxx")
To define Macro in the different file can be done by following ways:
1) You can define Macro in any other .h file.
and include the file in .cpp file.
This can help you to define Macro in different file
To check the Macro for Debug and Release version use _Debug or _Release Macro.
2) Another way to do this is By using the way told by #Soren.
using set(CMAKE_CXX_FLAGS "-g -Wall -Dxxxx")
like this. Shall I create two executables proj and proj_debug and for debug
No need.
With cmake you can change the CMAKE_BUILD_TYPE variable when configuring your project. Then in your CMakeLists.txt you can do something like:
if(NOT CMAKE_BUILD_TYPE STREQUAL "Release")
add_definitions(-DMY_DEBUG_MACRO)
endif()
Then you can easily configure your project twice (in two directories): once with CMAKE_BUILD_TYPE set to Debug and once CMAKE_BUILD_TYPE set to Release.

port a variable form make to Cmake

Our Library uses Cmake while the Overall system uses Make file for build.
I want to port the value of a variable (preprocessor macro) defined in the makefile to Cmakefile and use it as preprocessor marco in source codes of my library.
How to do that?
You can define variable at CMake invocation like so:
cmake -DMY_VAR=ON <path_to_CMakeLists.txt>
Then later in your CMake file:
if (MY_VAR)
add_definitions(-DENABLE_MY_VAR)
endif()
And finally in your code:
#ifdef ENABLE_MY_VAR
// Your code
#endif

Check CMake's option in C++ source

I have the following option defined in CMake:
option(OURAPP-DEV-USE_EXTREME_DEBUGGING "Use extreme debugging features" OFF)
and I would like to check in a C++ file that this option was checked (in the CMake-GUI) or not.
I.e. writing C++ code like:
#if OURAPP-DEV-USE_EXTREME_DEBUGGING
print_extra_debugging();
#endif
Please note, that our project setup requires that there is a - between the options regarding the components (such as OURAPP and DEV and the rest ...)
Any idea how to make it happen?
Transfer the CMake option to the C++ world using a preprocessor define.
IF(OURAPP-DEV-USE_EXTREME_DEBUGGING)
ADD_DEFINITIONS(-DUSE_EXTREME_DEBUGGING)
ENDIF()
Under the hood, this adds the define to the compiler command line, and is then available to the preprocessor:
#ifdef USE_EXTREME_DEBUGGING
print_extra_debugging();
#endif
Note that a hyphen is not a valid character in a C preprocessor token, so you'll have to change the name in the define.
You can also use cmake CONFIGURE_FILE, cf. http://www.cmake.org/cmake/help/cmake2.6docs.html#command%3Aconfigure_file