There is no available $<TARGET_EXISTS:...>
generator expression where you could write this:
add_libary(A a.cpp a.hpp)
target_compile_definitions(A PUBLIC $<<TARGET_EXISTS:B>:HAVE_B=1>)
Although I am proposing this to cmake, here. As a workaround, you can create shadow targets to track the targets from other directories:
# Custom property to check if target exists
define_property(TARGET PROPERTY "INTERFACE_TARGET_EXISTS"
BRIEF_DOCS "True if target exists"
FULL_DOCS "True if target exists"
)
# Create shadow target to notify that the target exists
macro(shadow_notify TARGET)
if(NOT TARGET _shadow_target_${TARGET})
add_library(_shadow_target_${TARGET} INTERFACE IMPORTED GLOBAL)
endif()
set_target_properties(_shadow_target_${TARGET} PROPERTIES INTERFACE_TARGET_EXISTS 1)
endmacro()
# Check if target exists by querying the shadow target
macro(shadow_exists OUT TARGET)
if(NOT TARGET _shadow_target_${TARGET})
add_library(_shadow_target_${TARGET} INTERFACE IMPORTED GLOBAL)
set_target_properties(_shadow_target_${TARGET} PROPERTIES INTERFACE_TARGET_EXISTS 0)
endif()
set(${OUT} "$<TARGET_PROPERTY:_shadow_target_${TARGET},INTERFACE_TARGET_EXISTS>")
endmacro()
This creates two functions, and a custom property to track if the target exists or not. The shadow_notify
will create a shadow target if it doesn't exists and then set the INTERFACE_TARGET_EXISTS
property to true if it does exists.
The shadow_exists
target will create a generator expression to query if the target exists. It does this by creating a new shadow target if doesn't exists with the INTERFACE_TARGET_EXISTS
property set to 0. Then it will create a generator expression that will query the INTERFACE_TARGET_EXISTS
property on the shadow target. The shadow target will always exists, and if the actual target exists then the property will be set to 1 by shadow_notify
.
So then you can write this in your cmake:
add_libary(A a.cpp a.hpp)
# Notify that target A exists
shadow_notify(A)
# Check if target B exists
shadow_exists(HAS_B B)
target_compile_definitions(A PUBLIC $<${HAS_B}:HAVE_B=1>)
When you create library B
you will need to call shadow_notify(B)
as well.
If you don't like these extra shadow_notify
calls, you could also override add_library
to do it for you:
macro(add_library LIB)
_add_library(${LIB} ${ARGN})
if(NOT TARGET _shadow_target_${TARGET})
_add_library(_shadow_target_${TARGET} INTERFACE IMPORTED GLOBAL)
endif()
set_target_properties(_shadow_target_${TARGET} PROPERTIES INTERFACE_TARGET_EXISTS 1)
endmacro()