Here is snippet from make CMakeLists.txt:
add_library(foo-object OBJECT src/foo.cpp)
target_include_directories(foo-object PUBLIC include)
add_library(foo SHARED $<TARGET_OBJECTS:${PROJECT_NAME}-object>)
add_library(foo_static STATIC $<TARGET_OBJECTS:${PROJECT_NAME}-object>)
Now, this all works fine, both libraries are generated. However I have a problem when I try to use it:
add_executable(bar src/main.cpp)
target_link_libraries(bar foo)
Target bar
doesn't compile, because include directories from foo-object are not propagated. If I add target_include_directories
directly on foo
as well, everything will compile fine.
How can I make both foo
and foo_static
automatically use (and forward to stuff depending on them) include directories from foo-object
?
Hm, at the moment I came up with following:
but come on, there must be better way :/
On CMake <3.12, use the following:
On CMake >=3.12, take a look at this answer (thanks @ian5v for the suggestion)
How it works:
Therefore
${PROJECT_NAME}-object
hasINTERFACE_INCLUDE_DIRECTORIES
set on it. We need to fetch this property and insert it into our own include path.This looks like a job for "generator expressions"!. In particular,
$<TARGET_PROPERTY:tgt,prop>
looks like it will come in handy here.Our
tgt
will be${PROJECT_NAME}-object
, and we're trying to extract all of the values ofINTERFACE_INCLUDE_DIRECTORIES
, soINTERFACE_INCLUDE_DIRECTORIES
will beprop
.This comes out to
$<TARGET_PROPERTY:${PROJECT_NAME}-object,INTERFACE_INCLUDE_DIRECTORIES>
, which is exactly what we've used in the code above.It seems that transitive properties only work when targets are linked through a chain of
target_link_library
calls. In your case, you do not have such a link betweenfoo-object
andfoo
.If you add a source file to
foo
, that one should also not be able to see the include directory fromfoo-object
.This might be an oversight in the design of
OBJECT
libraries, as it essentially breaks the transitive properties for those.