What are legal items in the INTERFACE_LINK_LIBRARIES property? - cmake

My expectations are, that the items in the target property INTERFACE_LINK_LIBRARIES are other targets. However when I use on Linux for the official Threads package.
find_package(Threads)
get_property(libs TARGET Threads::Threads PROPERTY INTERFACE_LINK_LIBRARIES)
libs ist set to -lpthread, which seems to be a linker flag, not a target.
Is this correct?

That property is populated by the command target_link_libraries(), and its documentation lists what can be specified:
A library target name
A full path to a library file
A plain library name
A link flag
Keywords debug, optimized, or general
Therefore, link flags are allowed here, even if discouraged by the CMake documentation.

Related

How to query whether a target is an INTERFACE library in CMake

In modern CMake one can specify a library as INTERFACE: it does not produce build output, but it can have properties associated to it, although not all properties can be set (for instance the FOLDER property is not supported). Say I have a generic CMake macro setting properties for a generic library target, is there a way to tell that the input target is an interface library, so that I can skip the unsupported properties only for that target?
You query the TYPE property of target....
get_target_property(type target TYPE)
if (${type} STREQUAL "INTERFACE_LIBRARY")

CMake compiler independent flags

Are there any compiler independent flags that can be set? I'd like to be able to set single variable to e.g. OPTIMIZE_MOST and get -O3 on gcc and /O2 in MS C++ compiler. Is there something I can use or should flags be set for each compiler separately?
Simply spoken: No, there is no flag to directly set the optimization level independently for every compiler.
However, CMake provides so called build types. Those are independent of the compiler in use and each comes with a predefined selection of flags, one of which is the optimization flag.
Available build types are
Debug
Release
RelWithDebInfo
MinSizeRel
For a comprehensive explanation, I refer to this answer. It also provides some code that helps to identify the flags in question when included into the CMakeLists.txt file:
message("CMAKE_C_FLAGS_DEBUG is ${CMAKE_C_FLAGS_DEBUG}")
message("CMAKE_C_FLAGS_RELEASE is ${CMAKE_C_FLAGS_RELEASE}")
message("CMAKE_C_FLAGS_RELWITHDEBINFO is ${CMAKE_C_FLAGS_RELWITHDEBINFO}")
message("CMAKE_C_FLAGS_MINSIZEREL is ${CMAKE_C_FLAGS_MINSIZEREL}")
message("CMAKE_CXX_FLAGS_DEBUG is ${CMAKE_CXX_FLAGS_DEBUG}")
message("CMAKE_CXX_FLAGS_RELEASE is ${CMAKE_CXX_FLAGS_RELEASE}")
message("CMAKE_CXX_FLAGS_RELWITHDEBINFO is ${CMAKE_CXX_FLAGS_RELWITHDEBINFO}")
message("CMAKE_CXX_FLAGS_MINSIZEREL is ${CMAKE_CXX_FLAGS_MINSIZEREL}")
To a degree. For some concepts, CMake has support for specifying them in a compiler-agnostic manner, usually by setting properties on the target in question. Unfortunately, there is no one location where all such possibilities would be listed. I went through the current list of target properties and identified the following properties as "absrtacting away build-tool option syntax":
COMPILE_PDB_NAME
INCLUDE_DIRECTORIES
INSTALL_RPATH
INTERPROCEDURAL_OPTIMIZATION
LINK_DIRECTORIES
LINK_LIBRARIES
PDB_NAME
PDB_OUTPUT_DIRECTORY
(plus the properties for setting output name, path, etc.)
There is apparently nothing for handling optimisation flags other than IPO.
To the best of my knowledge, there is also no generic process for adding these — they are added to CMake as someone finds the need for them (and the time to implement them).

Adding object-file dependencies

I have a CMake project. For some reason (that I won't say here, but which I can provide upon request), I need some object files that are part of the same library to be compiled before others. Specifically:
FILES is a list of source files
file_a.c is a member of FILES
file_d.c is a member of FILES
file_a.o MUST exist on disk before file_d.c is compiled
This is what I have now:
set_source_files_properties(
file_a.c
PROPERTIES
OBJECT_OUTPUTS file_a.o
)
set_source_files_properties(
file_d.c
PROPERTIES
OBJECT_DEPENDS file_a.o
)
This works well for Makefiles, but it doesn't appear to play nice with Ninja; I get a circular dependency error and complaints about multiple rules.
Don't try to declare dependencies between object files. If there are files that have a dependency, break them out into a separate library with add_library and then declare the dependency with add_dependencies and target_link_libraries. There is no extra cost for doing this.
Particularly, consider looking at Object Libraries.

How to tell whether a given target is a library or executable?

The built-in function install(TARGETS ...) installs library targets to another location than executable targets. I want to do something similar. Given a list of target names, I want to add all library targets among them to a list variable and all runtime targets to another variable.
I couldn't found a list of CMake's default target properties, but I guess add_library() and add_executable() add a property that can be used for this kind of distinction.
How to tell whether a given target is a library or executable (or even something else)?
According to documentation, TYPE property can be used for distinguish standard CMake target types:
It will be one of STATIC_LIBRARY, MODULE_LIBRARY, SHARED_LIBRARY, EXECUTABLE or one of the internal target types.
Example:
get_target_property(target_type <target> TYPE)
if (target_type STREQUAL "EXECUTABLE")
# Process executable target
endif ()

Is there a LINK_DIRECTORIES or equivalent property in CMake?

I have created a project with a large number of link_directories() commands. I'd now like to store the resulting string of directories into a variable. For include_directories() this is easy using
get_property( test_INCLUDE_DIRECTORIES TARGET test PROPERTY INCLUDE_DIRECTORIES )
however there seems to be no LINK_DIRECTORIES property to do
get_property( test_LINK_DIRECTORIES TARGET test PROPERTY LINK_DIRECTORIES )
Is there a way to get a list of link directories used for a target?
(Note: I realize I could manually track the link directories in a variable myself and then use a single link_directories() but it doesn't seem very clean)
Take a look at the LINK_DIRECTORIES directory property.
The point is that link_directories operates on a per-directory basis (the command affects all targets defined in the same CMakeLists, as well as targets from all of its subdirectories), unlike, for instance, target_include_directories which works on a per-target basis.
You can query the value of the property with:
get_property(test_LINK_DIRECTORIES DIRECTORY PROPERTY LINK_DIRECTORIES)
if called from the same directory as the link_directories call. Otherwise, you need to give the (full or relative) path as an additional argument after DIRECTORY. Unfortunately, I know of no way to obtain the matching directory for an existing target.
Note that in general the use of link_directories is discouraged in CMake, which is probably the main reason why it's not supported very well. Unless you have very good reasons not to, you should always stick with full library paths passed to target_link_libraries. It will save you lots of headaches in the long run.