Difference between COMPILE_FLAGS and COMPILE_OPTIONS - cmake

What is the difference between
COMPILE_FLAGS: Additional flags to use when compiling this target's sources.
and
COMPILE_OPTIONS: List of options to pass to the compiler.
In terms of resulting VS2010 solution these commands produce the same result:
target_compile_options(target PRIVATE "/option=test1")
set_target_properties(target PROPERTIES COMPILE_FLAGS "/option=test1")
set_target_properties(target PROPERTIES COMPILE_OPTIONS "/option=test1")

COMPILE_OPTIONS is a list, but COMPILE_FLAGS is a string.
set_target_properties(target PROPERTIES
COMPILE_OPTIONS "/option=test1;/option2=test2")
set_target_properties(target PROPERTIES
COMPILE_FLAGS "/option=test1 /option2=test2")
You can more-easily append to a list than to a string.
Also, COMPILE_OPTIONS is properly escaped, whereas some characters in COMPILE_FLAGS may need to be escaped manually or cause problems.

Can be used to the same end, but flags are associated with some target enviroment. So you could use different sets of flags for different enviroments.

Related

How to set compiler flags in cmakelists.txt of single file for debug or release ?

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).

set_target_properties COMPILE_FLAGS also sets assembler flags, do not want

When I do this:
set_target_properties(${TARGET_BASENAME_A} PROPERTIES COMPILE_FLAGS "--std=c99" )
It sets the flag --std=c99 in both compiler and assembler command lines.
The assembler does not recognize that flag so it fails.
I only want the flag to appear in the compiler command line, not the assembler.
How do I do this?
set_source_files_properties(${SOURCES_C} PROPERTIES COMPILE_FLAGS ${TARGET_C_FLAGS})
This appears to work, applying the flags only to those files in the SOURCES_C variable.

target_compile_definitions for multiple CMake targets?

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

Manyears 1.1.2 sources, compile cmake file

I would like to compile the cmake file from Manyears 1.1.2 sources, but I got the errors as below:
WARNING : manyears GUI will not be compiled because Qt4 not found
-- Buiding ManyEarsLib Library...
CMake Error at dsplib/CMakeLists.txt:75 (set_target_properties):
set_target_properties called with incorrect number of arguments.
-- Buiding RTAudio Library...
CMake Error at example/CMakeLists.txt:22 (set_target_properties):
set_target_properties called with illegal arguments, maybe missing a
PROPERTIES specifier?
And the original program has been written as below:
target_link_libraries(ManyEarsLib )
set_target_properties(ManyEarsLib PROPERTIES LINK_FLAGS ${MANYEARS_LINK_FLAGS} OUTPUT_NAME man-years)
add_executable(manyears_console manyears_console.c)
set_target_properties(manyears_console PROPERTIES LINK_FLAGS ${MANYEARS_LINK_FLAGS})
target_link_libraries(manyears_console ManyEarsLib -lm)
Could somebody tell me what is the problem and how to risolve it?
Thanks a lot.
Lun
Command set_target_properties may only set single-value properties.
But you attempt to set property LINK_FLAGS, which is generally multi-value (a list), but in your case it is simply empty. That is why first invocation detects incorrect number of arguments (it should be even), and the second invocation detects insufficient number of arguments (is should be 4 at least).
For set multi-value properties or for clear them use command set_property:
# Multi-value (or empty) property
set_property(TARGET ManyEarsLib PROPERTY LINK_FLAGS ${MANYEARS_LINK_FLAGS})
# Single-value property
set_target_properties(ManyEarsLib PROPERTIES OUTPUT_NAME man-years)
# Multi-value (or empty) property again
set_property(TARGET manyears_console PROPERTY LINK_FLAGS ${MANYEARS_LINK_FLAGS})
or even
# Multi-value (or empty) property for several targets
set_property(TARGET ManyEarsLib manyears_console PROPERTY LINK_FLAGS ${MANYEARS_LINK_FLAGS})
# Single-value property for single target
set_target_properties(ManyEarsLib PROPERTIES OUTPUT_NAME man-years)

Changing CMake compiler flags for multiple source files using asterisks

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)