How to clear all defines from cmake? - c++

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.

Related

Cmake: target_compile_definitions with find_package

I have a package, libtorch, that depends on libraries that use the keyword slots for some function (e.g. in Aten). In the meantime, the project that I am using is based on Qt, which use slots as a special keyword (macro), which then interferes with torchlib.
The solution to avoid such interference is to add the QT_NO_KEYWORDS definition when importing the external library that enters in conflict with Qt: Turning the no_keyword (Qt option) ON in a cmake file to work with boost::signals
It has then to be done only on the code that depends on libtorch and not the rest, so I tried several ways to add it, like CMake Add and Remove a Macro definition to compile Shared Library/Executable and Add target properties to an existing imported library in CMake, but I can't get it to work.
target_compile_definitions seems to be available after cmake 3.11 on "IMPORTED targets"(on cmake terminology).
So why the following cmakelist extract doesn't work? (in that case, the normal QT slots code are not properly recognized as a macro):
find_package (Torch REQUIRED PATHS ${Torch_DIR})
add_executable( ${PROJECT_NAME} ${header_files} ${source_files} ${hpp_files} ${moc_list} ${generated_ui_files} ${generated_qrc_files} )
target_link_libraries(${PROJECT_NAME} ${Qt_LINK_LIBRARIES})
#add_definitions(-DQT_NO_KEYWORDS)
target_link_libraries(${PROJECT_NAME} ${TORCH_LIBRARIES})
#remove_definitions(-DQT_NO_KEYWORDS)
target_compile_definitions(torch INTERFACE QT_NO_KEYWORDS)
Possible Solutions
Option 1:
Use QT_NO_KEYWORDS and replace slots and other keywords with their equivalent uppercase macros, e.g. Q_SLOTS.
Option 2:
Don't use QT_NO_KEYWORDS and wrap the parts of your C++ code with conflicting keywords like this:
#undef slots
#include <torch/torch.h>
#define slots Q_SLOTS
Explanations
The INTERFACE keyword in target_compile_definitions() tells CMake that all targets that depend on the torch library need the QT_NO_KEYWORDS macro defined as well. This is why all sources of your executable will be compiled with -DAT_NO_KEYWORDS and the slots keyword will not be defined.
I suppose you tried to fix your problem with the commented out add_definitions()/remove_definitions() calls. Several reason why those don't work as expected:
They only affect compilation not linking. Putting them around target_link_libraries() has no effect.
They manipulate the compile flags of all targets created in the current scope (current CMakeLists.txt), no matter if they were created before or after the command gets invoked, see the docs. This means calling add_definitions() and subsequently remove_definitions() with the same arguments will result in no flags being added at all no matter at which point in your CMakeLists.txt you call them.
You should also note that commands operating on the directory level (add_*/remove_*) are considered "old style" CMake. Modern CMake aims to only operate on the target level (target_* commands). Some more "Modern CMake" suggestions:
Use target_sources() instead of variables like header_files, source_files, etc. to add sources to your targets.
Always use target_link_libraries() with a PRIVATE, PUBLIC or INTERFACE keyword. Excerpt from Craig Scotts Professional CMake book:
The target_link_libraries() command also has a few other forms, some of which have been part of CMake from well before version 2.8.11. [...] Their use is generally discouraged for new projects. The full form shown previously with PRIVATE, PUBLIC and INTERFACE sections should be preferred, as it expresses the nature of dependencies with more accuracy. [...] The above form [(without PRIVATE/PUBLIC/INTERFACE)] is generally equivalent to the items being defined as PUBLIC, but in certain situations, they may instead be treated as PRIVATE. In particular, if a project defines a chain of library dependencies with a mix of both old and new forms of the command, the old-style form will generally be treated as PRIVATE.

CMake doesn't link the actual object to the resulting dll [duplicate]

How do I define a preprocessor variable through CMake?
The equivalent code would be #define foo.
For a long time, CMake had the add_definitions command for this purpose. However, recently the command has been superseded by a more fine grained approach (separate commands for compile definitions, include directories, and compiler options).
An example using the new add_compile_definitions:
add_compile_definitions(OPENCV_VERSION=${OpenCV_VERSION})
add_compile_definitions(WITH_OPENCV2)
Or:
add_compile_definitions(OPENCV_VERSION=${OpenCV_VERSION} WITH_OPENCV2)
The good part about this is that it circumvents the shabby trickery CMake has in place for add_definitions. CMake is such a shabby system, but they are finally finding some sanity.
Find more explanation on which commands to use for compiler flags here: https://cmake.org/cmake/help/latest/command/add_definitions.html
Likewise, you can do this per-target as explained in Jim Hunziker's answer.
To do this for a specific target, you can do the following:
target_compile_definitions(my_target PRIVATE FOO=1 BAR=1)
You should do this if you have more than one target that you're building and you don't want them all to use the same flags. Also see the official documentation on target_compile_definitions.
The other solutions proposed on this page are useful for some versions of Cmake > 3.3.2. Here the solution for the version I am using (i.e., 3.3.2). Check the version of your Cmake by using $ cmake --version and pick the solution that fits your needs. The cmake documentation can be found on the official page.
With CMake version 3.3.2, in order to create
#define foo
I needed to use:
add_definitions(-Dfoo) # <--------HERE THE NEW CMAKE LINE inside CMakeLists.txt
add_executable( ....)
target_link_libraries(....)
and, in order to have a preprocessor macro definition like this other one:
#define foo=5
the line is so modified:
add_definitions(-Dfoo=5) # <--------HERE THE NEW CMAKE LINE inside CMakeLists.txt
add_executable( ....)
target_link_libraries(....)
PLEASE NOTE (as #squareskittles suggests in one of the comment): "if you are using CMake 3.3.2, you have to use add_definitions() or target_compile_definitions(). The more modern command, add_compile_definitions(), was not added until CMake 3.12."
1.) target_compile_definitions
If you are using CMake 3.X your first choice for adding a preprocessor macro should be target_compile_definitions.
The reason you should prefer this approach over any other approach is because it granularity is target based. IE the macro will only be added to your exe/library.
Here is a common example:
if (WIN32)
target_compile_definitions(my_lib PRIVATE
# Prevents Windows.h from adding unnecessary includes
WIN32_LEAN_AND_MEAN
# Prevents Windows.h from defining min/max as macros
NOMINMAX
)
endif()
2.) add_compile_definitions
New in version 3.12.
Find more explanation on which commands to use for compiler flags here: https://cmake.org/cmake/help/latest/command/add_definitions.html
add_compile_definitions applies macros to any targets that are defined after the call.
Here is the same logic as above with add_compile_definitions.
add_compile_definitions(WIN32_LEAN_AND_MEAN NOMINMAX)
add_library(my_lib)
If you use this approach be careful if you are the top level project.
Otherwise if users consume your library using add_subdirectory they may have issues.
3.) The other less recommended ways
These approaches really aren't recommended anymore. Due to not being modular, not scaling well, not supporting generator expressions, etc.
add_definitions
CMAKE_LANG_FLAGS
Why is target_compile_definitions better/preferred?
It's much more clear to readers of your CMake code how it works.
Allows usage of PRIVATE/PUBLIC/INTERFACE if needed. Which can make life easier for consumers of your library.
It's much more modular.
Applying pre-processor flags (Or any compiler flag) globally can create hidden dependencies in your build.
Essentially think of add_compile_definitions as globals in C/C++. Sometimes you need them, but be careful.
i'd like to recommend use target_*** operations instead of add_*** operations when your solution include many projects.
here is an example where you can pass values from CMAKE to C++ code. Say, you want to pass:
flag, here: BOOST ("true" or "false")
software version string (e.g.: "1.0.0")
I recommend to pass them as strings.
So, when you build software with CMAKE, you can pass parameters like for example if it was built using boost library, software version pulled from CMAKE variable (so that you change that number only in one place)
See below.
In CMakeLists.txt:
add_compile_definitions(
BOOST="${BOOST}"
Software_VERSION="${PROJECT_VERSION}"
)
In your .cpp code:
std::cout << "Software version is: " << Software_VERSION << " BOOST: " << BOOST << "\n";
Hope this helps. Regards.

CMake: Set different name for #cmakedefine variable

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?

What to use instead of `qt5_use_modules`?

The Qt 5 CMake manual states that the qt5_use_modules macro is deprecated:
This macro is obsolete. Use target_link_libraries with IMPORTED targets instead.
... But qt5_use_modules does more than simply specify link libraries: it specifies include directories, necessary compile flags, and more (see the full description in the linked documentation above).
Assuming, then, that the variable QTMODULES contains some list of Qt modules that should be used for a project, what is the "recommended" way to replace the following "deprecated" CMake line?
qt5_use_modules(${myProjectName} ${QTMODULES})
The following does NOT work, primarily because it does not add any Qt include paths:
target_link_libraries(${myProjectName} IMPORTED ${QTMODULES})
Does the QTMODULES variable need to be manually iterated over, so that include_directories can be called for each individual module name? This seems like a major step backward from qt5_use_modules, which is simple and "just works." Am I missing something?
The message about using IMPORTED targets actually refers to the generated targets that Qt5's CMake modules provide for you, not that you should be setting the IMPORTED property on the target_link_libraries macro. For example, something like:
target_link_libraries(${myProjectName} Qt5::Core Qt5::Widgets)
will take care of adding all the necessary include paths, link paths, and libraries for using the Qt5Core and Qt5Widgets modules.

Including libsimdpp in a CMake project

I decided to use libsimdpp for vectorization of my C++ code. Problem is, there is next to no documentation on how to get started.
Í assumed inclusion would be simple given that it's also CMake based like the project I'm doing, so I just tried to copy over the directory and set the include path. Well, turns out this is not enough: You need to define the appropriate flags to specify which SIMD flavor you want to compile for. libsimdpp includes a CMake macro just for that and it works wonders. I'm not sure however how to get going from here and it feels like I'm working against CMake rather than with it by copying things around and deleting stuff.
Would anyone with a firm understanding of CMake set out to explain what to do in a step-by-step fashion? Thanks!
You should check out the simdpp/test/CMakeLists.txt file where the tests of libsimdpp are compiled. The relevant parts are these:
foreach(SRC ${TEST1_ARCH_SOURCES})
simdpp_multiarch(TEST1_ARCH_GEN_SOURCES ${SRC} ${COMPILABLE_ARCHS})
endforeach()
add_executable(test1 EXCLUDE_FROM_ALL
${TEST1_SOURCES}
${TEST1_ARCH_GEN_SOURCES}
)
Basically, TEST1_ARCH_SOURCES contains the code that uses libsimdpp. simdpp_multiarch copies the sources around and sets appropriate compile flags for them, so that implementations for e.g. SSE2 and AVX2 can be linked into the same executable. Then these generated sources (TEST1_ARCH_GEN_SOURCES) are added into the executable.