TARGET_NAME_IF_EXISTS has different scoping rules in INTERFACE_LINK_LIBRARIES than in INTERFACE_COMPILE_DEFINITIONS
Consider the following project, with a top-level CMakeLists.txt and a subdir
CMakeLists.txt. Here's the top-level build:
cmake_minimum_required(VERSION 3.26)
project(bug)
add_subdirectory(subdir)
add_library(example source.c)
target_link_libraries(example PRIVATE dependency)
The file source.c
is an empty placeholder. Here is the subdir
CMakeLists.txt.
add_library(imported::target INTERFACE IMPORTED)
target_compile_definitions(imported::target INTERFACE PROPAGATION_IS_WORKING)
add_library(dependency INTERFACE)
target_link_libraries(dependency INTERFACE $<TARGET_NAME_IF_EXISTS:imported::target>)
target_compile_definitions(dependency INTERFACE TARGET_NAME=$<TARGET_NAME_IF_EXISTS:imported::target>)
Here I create an imported target with an interface compile definition PROPAGATION_IS_WORKING
. I then create an interface library dependency
that conditionally links to imported::target
and sets the TARGET_NAME
symbol to be equal to imported::target
, if it exists, otherwise empty.
Now what happens when I compile this?
$ cmake -G Ninja -S . -B build
...
$ cmake --build build --verbose
[1/2] /usr/bin/gcc-10 -DPROPAGATION_IS_WORKING -DTARGET_NAME="" -g -MD -MT CMakeFiles/example.dir/source.c.o -MF CMakeFiles/example.dir/source.c.o.d -o CMakeFiles/example.dir/source.c.o -c /local/mnt2/workspace/areinkin/dev/cmake-bug-target_name_if_exists/source.c
[2/2] : && /local/mnt2/workspace/areinkin/.local/bin/cmake -E rm -f libexample.a && /usr/bin/ar qc libexample.a CMakeFiles/example.dir/source.c.o && /usr/bin/ranlib libexample.a && :
I get both PROPAGATION_IS_WORKING
and TARGET_NAME=""
. This is internally inconsistent! It's looking up the target in the scope of dependency
for the link libraries property, but for example
in the compile definitions property. Recall that imported::target
is not GLOBAL
.
Can we fix this somehow/policy it?