Transitive include directories

I’ve lost something in translation when reading this bit of documentation on Transitive Usage Requirements in cmake-buildsystem(7):

Usage requirements are propagated by reading the INTERFACE_ variants of target properties from dependencies and appending the values to the non-INTERFACE_ variants of the operand. For example, theINTERFACE_INCLUDE_DIRECTORIES of dependencies is read and appended to the INCLUDE_DIRECTORIES of the operand.

From this, I would expect that if I had 2 targets, libA and libB, and libA specified a PUBLIC or INTERFACE include dir using target_include_directory(libA PUBLIC includeA), if I were to specify

add_library(libB b.c)
target_link_libraries(libB INTERFACE libA)

that the source file b.c would get compiled with -I/path/to/includeA.

I don’t observe this and I don’t understand why. Please explain?


PS - as an aside, I’m trying to use INTERFACE for just the headers, as I would want libB to dlsym lookup the symbols from libA (or any other libA equivalent interface library).

You would need to use PUBLIC libA. INTERFACE libA only applies to consumers of libB, not parts of libB itself.

I don’t know if it’s conventional, but I found a solution that fit my needs (and your answer makes perfect sense now).

I created a separate INTERFACE library for libA that would communicate the include directory but not attempt to link against libA.

add_library(libA SHARED a.c)
add_library(libAInterface INTERFACE)
target_include_directories(libAInterface INTERFACE includeA)
#### elsewhere
target_link_libraries(libB PRIVATE libAInterface)

I now get it that target_link_libraries(foo INTERFACE bar) commutes the INTERFACE properties of bar ot the INTERFACE properties of foo. It doesn’t do anything to foo’s compilation.

I had a post somewhere about a $<COMPILE_ONLY:> genex that would do this, but yes, this is the best solution that I know of available today.