Genex: `$<COMPILE_LANGUAGE:...>` breaks `$<TARGET_PROPERTY:...,INCLUDE_DIRECTORIES>`
Using the $<COMPILE_LANGUAGE>
generator expression in a target_include_directories
upstream of SWIG breaks USE_TARGET_INCLUDE_DIRECTORIES
because that option calls $<TARGET_PROPERTY>
to invoke add_custom_command
. This presumably is an issue for any other bit of genex code that also uses TARGET_PROPERTY
for include directories.
This is related to #17542 (closed) which (thank google) helped me identify the error message.
Error message
The error occurs after Configuring done
and repeats 6 times for some odd reason, and furthermore it points to the point where the $<COMPILE_LANGUAGE>
is connected to the $<TARGET_PROPERTY>
code, which makes it very hard to debug:
CMake Error at CMakeLists.txt:22 (target_link_libraries):
Error evaluating generator expression:
$<COMPILE_LANGUAGE:CXX>
$<COMPILE_LANGUAGE:...> may only be used to specify include directories,
compile definitions, compile options, and to evaluate components of the
file(GENERATE) command.
Toy example
See this test repo with the following cmake:
cmake_minimum_required(VERSION 3.16)
project(swigtest LANGUAGES CXX)
### Create a library with language-dependent includes ###
add_library(foo foo.cc)
target_include_directories(foo PUBLIC
$<$<COMPILE_LANGUAGE:CXX>:$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/foodir>>
)
### Add a SWIG module that uses those includes ###
find_package(SWIG REQUIRED)
find_package(Python COMPONENTS Development)
include(UseSWIG)
set_source_files_properties(pyfoo.i PROPERTIES
CPLUSPLUS ON
USE_TARGET_INCLUDE_DIRECTORIES ON
)
swig_add_library(pyfoo LANGUAGE python
SOURCES pyfoo.i)
target_link_libraries(pyfoo PUBLIC foo PRIVATE Python::Python)
A workaround is to add the include directory regardless of the compile language, but that feels dirty and probably doesn't cover all use cases.
Real-life motivation
In a modern cmake update of our code, we use
target_include_directories(${target} INTERFACE
$<BUILD_INTERFACE:$<$<COMPILE_LANGUAGE:Fortran>:${CMAKE_Fortran_MODULE_DIRECTORY}>>
)
to allow our Fortran modules to all save .mod
files to a single directory (helpful for reducing the number of -I
on the build line as well as for ensuring modules in different source directories don't share a name).
Downstream of a library that uses the above include
logic, we have SWIG modules that use the USE_TARGET_INCLUDE_DIRECTORIES
UseSWIG magic to construct the SWIG include line. This leads to a barrage of the same errors detailed above.