Huazuo Gao
Huazuo Gao

Reputation: 1733

How to use headers from library but do not link to it with CMake?

I have an executable and a dynamic library that both depend on a static libary. If more context helps, the executable embeds a Python interperter and the dynamic library is a Python extension module. The dynamic library should not link to the static library because the later is already linked by the executable. However, the dynamic library requires headers from the static library to compile, which is only supplied implicitly via target_link_libraries. In effect, What I need is a target_link_libraries that adds include paths and does nothing else.

Here is what I've tried:

Upvotes: 4

Views: 1575

Answers (3)

Huazuo Gao
Huazuo Gao

Reputation: 1733

The $<TARGET_PROPERTY> generator expression does the trick.

target_include_directories(
    MyDynamicLib
    PRIVATE
    $<TARGET_PROPERTY:MyStaticLib,INCLUDE_DIRECTORIES>)

get_target_property is evaluated in the configuration phase and return what is written in CMakeLists.txt. The $<TARGET_PROPERTY> generator expression is evaluated in the generation phase and returns the actual value.

Upvotes: 1

ComicSansMS
ComicSansMS

Reputation: 54589

You will need a separate target that provides only the headers.

Both the static and the dynamic library will then depend on that header-only target, but not on each other.

This is typically achieved by defining an interface library target for the headers:

target_include_directories(MyHeaders INTERFACE
  $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
  $<INSTALL_INTERFACE:include>
)

add_library(MyStaticLib STATIC a.cpp)
target_link_libraries(MyStaticLib PUBLIC MyHeaders)
add_library(MyDynamicLib SHARED b.cpp)
target_link_libraries(MySDynamicLib PUBLIC MyHeaders)

Note how for this to work you will need full control over the definition of all the library targets. If the static library is provided by a third-party build that is not under your control this will not work. In that case you should get into contact with the maintainer of the third-party library to figure out how they can support your use case.

Upvotes: 0

rustyx
rustyx

Reputation: 85276

Usually find_package(Foo) defines packages' include directories in a variable FOO_INCLUDE_DIR.

You can simply add that to your project's include path with

include_directories("${FOO_INCLUDE_DIR}")

Upvotes: 1

Related Questions