I'm trying to set multiple compile definitions for one of the executables I'm trying to compile in CMake (in order to activate macros used for debugging). Here's what I tried:
add_executable (trie_io_test trie_io_test.c trie.c word_list.c)
set_target_properties(
trie_io_test
PROPERTIES
COMPILE_DEFINITIONS UNIT_TESTING=1)
set_target_properties(
trie_io_test
PROPERTIES
COMPILE_DEFINITIONS IO_TEST=1)
Unfortunately this causes only the IO_TEST to be defined.
I also tried the following:
add_executable (trie_io_test trie_io_test.c trie.c word_list.c)
set_target_properties(
trie_io_test
PROPERTIES
COMPILE_DEFINITIONS UNIT_TESTING=1 IO_TEST=1)
But this, on the other hand, causes CMake error.
How to set both of these definitions for the executable I'm trying to build?
You want target_compile_definitions instead of set_target_properties:
target_compile_definitions(trie_io_test PRIVATE UNIT_TESTING=1 IO_TEST=1)
I find this can work for you:
add_executable (trie_io_test trie_io_test.c trie.c word_list.c)
set_target_properties(
trie_io_test
PROPERTIES
COMPILE_DEFINITIONS UNIT_TESTING=1
COMPILE_DEFINITIONS IO_TEST=1
)
Just by adding another COMPILE_DEFINITIONS :P
Related
I have found the way to configure according to Andre's comment in How to change a compiler flag for just one executable in CMake? .
For example, I add a flag for bubble.c:
set_source_files_properties( ${ProjDirPath}/../bubble.c PROPERTIES COMPILE_FLAGS "-O2")
It worked.But I can't specify the flag for debug or release.
Dose anyone know how to configure it? Thank you!
IF(CMAKE_BUILD_TYPE MATCHES DEBUG)
set_source_files_properties( ${ProjDirPath}/../bubble.c PROPERTIES COMPILE_FLAGS "-O2")
ENDIF(CMAKE_BUILD_TYPE MATCHES DEBUG)
Use special syntax like this:
set_source_files_properties(myfile.cpp PROPERTIES
COMPILE_FLAGS $<$<CONFIG:RelDebug>:/O2>
SKIP_PRECOMPILE_HEADERS $<$<CONFIG:RelDebug>:ON>
)
Sets specific compilation option only to specific configuration (in this case for RelDebug).
I've been told it's bad practice to do things like seting CFLAGS directly in CMake, and that, instead, I should use the target_compile_definitions() command.
Ok, but - what if I want to use similar/identical definitions for multiple (independent) targets? I don't want to repeat myself over and over again.
I see three possible ways:
The preferred one using target_compile_definitions(... INTERFACE/PUBLIC ...) which would self-propagate the compiler definitions to targets depending on it via target_link_libraries() command.
Using the set_property(TARGET target1 target2 ... APPEND PROPERTY COMPILE_DEFINITIONS ...) to set the same definitions to multiple targets.
You may still use the "old commands" of add_definitions() and remove_definitions() to modify COMPILE_DEFINITIONS directory property (which would pre-set all COMPILE_DEFINITIONS target properties in this directories scope).
References
Is Cmake set variable recursive?
CMake: Is there a difference between set_property(TARGET ...) and set_target_properties?
tl;dr: You can iterate the targets in a loop.
If you have a bunch of targets with some common/similar features, you may want to simply manipulate them all in a loop! Remember - CMake is not like GNU Make, it's a full-fledged scripting language (well, sort of). So you could write:
set(my_targets
foo
bar
baz)
foreach(TARGET ${my_targets})
add_executable(${TARGET} "${TARGET}.cu")
target_compile_options(${TARGET} PRIVATE "--some_option=some_value")
target_link_libraries(${TARGET} PRIVATE some_lib)
# and so on
set_target_properties(
${TARGET}
PROPERTIES
C_STANDARD 99
C_STANDARD_REQUIRED YES
C_EXTENSIONS NO )
endforeach(TARGET)
And you could also initialize an empty list of targets, then add to it here-and-there, and only finally apply your common options and settings to all of them, centrally.
Note: In this example I added PRIVATE compile options, but if you need some of them to propagate to targets using your targets, you can make them PUBLIC).
another neat solution is to define an interface library target (a fake target that does not produce any binaries) with all required properties and compiler definitions, then link the other existing targets against it
example:
add_library(myfakelib INTERFACE)
target_compile_definitions(myfakelib INTERFACE MY_NEEDED_DEFINITION)
add_executable(actualtarget1 main1.cpp)
add_executable(actualtarget2 main2.cpp)
set_property(
TARGET actualtarget1 actualtarget2
APPEND PROPERTY LINK_LIBRARIES myfakelib
)
refs:
https://cmake.org/cmake/help/latest/command/add_library.html#interface-libraries
I've written a cmake module for finding QCustomPlot. However, to use the shared library, one needs to #define QCUSTOMPLOT_USE_LIBRARY. I'd like to provide this define through cmake, automatically adding the definition to any project that uses QCustomPlot.
Here is a snippet of my cmake module and my current attempted solution:
SET(QCP_FOUND "NO")
IF(QCP_LIBRARY AND QCP_INCLUDE_DIR)
SET(QCP_FOUND "YES")
SET_PROPERTY(
GLOBAL
APPEND
PROPERTY COMPILE_DEFINITIONS QCUSTOMPLOT_USE_LIBRARY
)
ENDIF(QCP_LIBRARY AND QCP_INCLUDE_DIR)
However, no linkers append the -DQCUSTOMPLOT_USE_LIBRARY flag in my compilations. What's the right way to approach this problem?
There is no global property COMPILE_DEFINITIONS. But there are such properties for directory, target and source file (see documentation). So probably the closest commands for you are:
set(QCP_FOUND "NO")
if(QCP_LIBRARY AND QCP_INCLUDE_DIR)
set(QCP_FOUND "YES")
set_directory_properties(
PROPERTIES COMPILE_DEFINITIONS QCUSTOMPLOT_USE_LIBRARY
)
endif()
But I think that this kind of job is for imported targets:
add_library(QCP::qcp UNKNOWN IMPORTED)
set_target_properties(
QCP::qcp
PROPERTIES
IMPORTED_LOCATION "${QCP_LIBRARY}"
INTERFACE_INCLUDE_DIRECTORIES "${QCP_INCLUDE_DIR}"
INTERFACE_COMPILE_DEFINITIONS QCUSTOMPLOT_USE_LIBRARY
)
and usage:
add_executable(foo ...)
target_link_libraries(foo PUBLIC QCP::qcp)
I'm trying to debug a problem related to compiler optimisation (no issue with -O2 or below, segfault with -O3) and I'd like to be able to switch the compiler flags for a chunk of my source so I can try to narrow down where the segfault is coming from.
I can do this setting the global optimisation level to -O2, and altering the PROPERTIES for single files like so:
SET_SOURCE_FILES_PROPERTIES(file1.f90 PROPERTIES COMPILE_FLAGS -O3)
However, when I try to do this for multiple files using *.f90 for example, it seems to not work:
SET_SOURCE_FILES_PROPERTIES(*.f90 PROPERTIES COMPILE_FLAGS -O3)
Is there any way to do this for multiple files without specifying every file by name?
You can glob for a list of files:
file(GLOB MyFiles *.f90)
set_property(SOURCE ${MyFiles} PROPERTY COMPILE_FLAGS -O3)
Alternatively, you could set the COMPILE_FLAGS target property of the respective target instead. Usually, it does not make much sense to compile certain source files with different compile flags than others within the same target. So unless you have good reason to do this on a per-file basis, you should always use the target properties instead.
Just adding to #ComicSansMS correct answer.
You could also use SET_SOURCE_FILES_PROPERTIES this way:
file(GLOB MyFiles *.f90)
SET_SOURCE_FILES_PROPERTIES(${MyFiles} PROPERTIES COMPILE_FLAGS -O3)
This code will have the same effect as
file(GLOB MyFiles *.f90)
set_property(SOURCE ${MyFiles} PROPERTY COMPILE_FLAGS -O3)
I am writing a CMakeLists.txt for a project, and encounter a problem with set_source_files_properties.
The original working expression is:
set_source_files_properties (a.cpp PROPERTIES COMPILE_DEFINITIONS
DIR1="/home/xxx/b.i")
Then I try to add more COMPILE_DEFINITIONSs, but get failure.
try 1:
set_source_files_properties (a.cpp PROPERTIES COMPILE_DEFINITIONS
DIR1="/home/xxx/b.i" DIR2="/home/xxx/c.i" DIR3="/home/xxx/d.i")
try 2:
set_source_files_properties (a.cpp PROPERTIES COMPILE_DEFINITIONS
DIR1="/home/xxx/b.i")
set_source_files_properties (a.cpp PROPERTIES COMPILE_DEFINITIONS
DIR2="/home/xxx/c.i")
set_source_files_properties (a.cpp PROPERTIES COMPILE_DEFINITIONS
DIR3="/home/xxx/d.i")
result:
only last define DIR3 can be recognized in a.cpp when compiling by make, first two are reported undefined in make phase.
Any suggestions?
Thank you!
The set_*_properties() functions are shorthands for basic usage. For "advanced" cases, it's better to use the full power of set_property():
set_property(
SOURCE a.cpp
APPEND
PROPERTY COMPILE_DEFINITIONS
DIR1="/home/xxx/b.i" DIR2="/home/xxx/c.i" DIR3="/home/xxx/d.i"
)
I manage to provide several COMPILE_DEFINITIONS using set_source_files_properties with the following command:
set_source_files_properties (a.cpp PROPERTIES COMPILE_DEFINITIONS
"DIR1=\"/home/xxx/b.i\";DIR2=\"/home/xxx/c.i\";DIR3=\"/home/xxx/d.i\")"
source: https://cmake.org/cmake/help/v3.5/prop_sf/COMPILE_DEFINITIONS.html
Here is a code worked for me:
SET_SOURCE_FILES_PROPERTIES("source1.cpp" "source2.cpp" PROPERTIES
COMPILE_FLAGS "-IDir1
-IDir2 ")
the problem has been resolved by:
add_definitions (-DDIR1="/home/xxx/b.i")
add_definitions (-DDIR2="/home/xxx/C.i")
add_definitions (-DDIR3="/home/xxx/D.i")