Reputation: 2696
I'm am trying to create an install target for a shared lib that uses links to a interface lib. I would like to have create a lib folder that contains the lib and an include folder that contains the necessary headers (public ones of both the shared and interface lib).
First the interface lib:
file(GLOB_RECURSE PUBLIC_HDRS include/*.h)
add_library(MyLib INTERFACE ${PUBLIC_HDRS})
target_include_directories(MyLib INTERFACE include)
Then the shared lib:
set(PUBLIC_INCLUDE include)
set(PRIVATE_INCLUDE src)
set(SRC src)
file(GLOB_RECURSE SRCS ${SRC}/*.cpp)
file(GLOB_RECURSE PUB_HDRS ${PUBLIC_INCLUDE}/*.h)
file(GLOB_RECURSE PRIV_HDRS ${PRIVATE_INCLUDE}/*.h)
add_library(MySharedLib SHARED ${SRCS} ${PUB_HDRS} ${PRIV_HDRS})
target_include_directories(MySharedLib PRIVATE ${PRIVATE_INCLUDE}
PUBLIC ${PUBLIC_INCLUDE})
target_link_libraries(MySharedLib PUBLIC MyLib)
target_sources(MySharedLib PUBLIC "${PUB_HDRS}")
get_target_property(MYLIB_PUBLIC_HEADERS MySharedLib INTERFACE_SOURCES)
set_target_properties(MySharedLib PROPERTIES PUBLIC_HEADER "${MYLIB_PUBLIC_HEADERS}")
install(TARGETS MySharedLib
LIBRARY DESTINATION lib
PUBLIC_HEADER DESTINATION include)
However the INTERFACE_SOURCES seem to only contain the headers of the shared lib and not the ones of the interface lib. Even after adding to the interface lib:
target_sources(MyLib PUBLIC "${PUBLIC_HDRS}")
How can I fix this? Is there an easier way to do this? I feels a bit strange I have to set the target_sources
since these are also specified in the target_include_directories
.
Upvotes: 0
Views: 414
Reputation: 65928
CMake's INTERFACE library target behaves like a "normal" library target in many ways. Among other things, it is allowed to specify PUBLIC_HEADER property for an INTERFACE target and even install that target:
file(GLOB_RECURSE PUBLIC_HDRS include/*.h)
add_library(MyLib INTERFACE)
target_include_directories(MyLib INTERFACE include)
set_property(TARGET MyLib PROPERTY PUBLIC_HEADER ${PUBLIC_HDRS})
install(TARGETS MyLib PUBLIC_HEADER DESTINATION include)
Installation of a target doesn't need to be specified in the same CMakeLists.txt
which creates that target. So you may install both targets MySharedLib
and MyLib
with the single command in the MySharedLib/CMakeLists.txt
:
install(TARGETS MySharedLib MyLib
LIBRARY DESTINATION lib
PUBLIC_HEADER DESTINATION include)
That way you will need to specify the layout for installed artifacts only once.
Your approach with using get_target_property
for extract properties, derived by target MySharedLib
from the target MyLib
doesn't work.
While call
target_link_libraries(MySharedLib PUBLIC MyLib)
propagates interface properties of MyLib
target to MySharedLib
, this propagation is performed only at the end of the configuration process.
But get_target_property
reads only current value of the property.
Upvotes: 1