Reputation: 642
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)
Upvotes: 1
Views: 1691
Reputation: 281
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
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:
target_link_libraries()
has no effect.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:
header_files
, source_files
, etc. to add sources to your targets.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.
Upvotes: 1