I'm having a problem with the cmake Generator Expression TARGET_NAME_IF_EXISTS. With this CMakeLists.txt
:
cmake_minimum_required(VERSION 3.13.0)
option(SLIB_BUILD_STATIC "" ON)
project(slib VERSION 1.0)
add_library(slibObjects OBJECT main.c)
add_library(slib SHARED $<TARGET_OBJECTS:slibObjects>)
if (SLIB_BUILD_STATIC) # Can this if() be replaced with a GenExp?
add_library(slibStatic STATIC $<TARGET_OBJECTS:slibObjects>)
endif()
set_target_properties(
slib
$<TARGET_NAME_IF_EXISTS:slibStatic> # This GenExp doesn't get reduced
PROPERTIES
VERSION ${SLIB_VERSION}
SOVERSION ${SLIB_VERSION_MAJOR}
)
I get
CMake Error at CMakeLists.txt:12 (set_target_properties):
set_target_properties Can not find target to add properties to:
$<TARGET_NAME_IF_EXISTS:slibStatic>
I expected set_target_properties
to reduce to one of these depending on if SLIB_BUILD_STATIC
is set:
set_target_properties( slib slibStatic PROPERTIES ...)
set_target_properties( slib PROPERTIES ...)
What am I doing wrong?
if
commandGenerator expressions are usable only for some properties and some variables, so they could be evaluated at the end of configuration stage to a values, which depends from the build type. Such behavior cannot be achieved with plain if
because multi-configuration CMake generators (like Visual Studio) read a CMakeLists.txt
once but create several configurations.
Generator expressions are usable also for the commands which sets these properties and variables.
Every possible usage of generator expressions is explicitly stated in the documentation for a command/property/variable which supports them.
Documentation for the command set_target_properties doesn't describe usage of generator expressions, so this command simply doesn't support them.
Actually, one can pass to that command a generator expression as a property's value. In that case the command will just assign that value to the corresponded property. It is dependent from the property whether the generator expression will be resolved when evaluate the property after the configuration.
But neither the name of the target not the name of the property cannot be a generator expression.
For conditionally set properties for a target, use plain if
:
# Unconditionally set properties for 'slib' target.
set_target_properties(
slib
PROPERTIES
VERSION ${SLIB_VERSION}
SOVERSION ${SLIB_VERSION_MAJOR}
)
# Set properties for 'slibStatic' target only if this target exist.
if (TARGET slibStatic)
set_target_properties(
slibStatic
PROPERTIES
VERSION ${SLIB_VERSION}
SOVERSION ${SLIB_VERSION_MAJOR}
)
endif()
For avoid copy-pasting of properties' assignment, you could create a variable which contains a list of targets, and then use this variable:
# Variable which contain list of affected targets.
set(targets_for_version_set slib)
# Add target 'slibStatic' to the list only if the target exist
if (TARGET slibStatic)
list(APPEND targets_for_version_set slibStatic)
endif()
# Now assign properties for all variables in the list
set_target_properties(
${targets_for_version_set}
PROPERTIES
VERSION ${SLIB_VERSION}
SOVERSION ${SLIB_VERSION_MAJOR}
)