OBJECT库上的传递target_include_directories

时间:2016-08-08 14:59:38

标签: cmake

以下是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>)

现在,这一切都正常,两个库都生成了。但是当我尝试使用它时遇到问题:

add_executable(bar src/main.cpp)
target_link_libraries(bar foo)

目标bar无法编译,因为不会传播来自foo-object的包含目录。如果我在target_include_directories上直接添加foo,一切都会正常编译。

如何让foofoo_static自动使用(并根据它们转发内容)包含来自foo-object的目录?

4 个答案:

答案 0 :(得分:7)

嗯,此刻我想出了以下内容:

add_library(foo-object OBJECT src/foo.cpp)
target_include_directories(foo-object PUBLIC include)

get_property(object_include_dirs TARGET foo-object PROPERTY INCLUDE_DIRECTORIES)
get_property(object_link_libs TARGET foo-object PROPERTY LINK_LIBRARIES)

add_library(foo SHARED $<TARGET_OBJECTS:${PROJECT_NAME}-object>)
target_include_directories(foo PUBLIC ${object_include_dirs})
target_link_libraries(foo PUBLIC ${object_link_libs})

add_library(foo_static STATIC $<TARGET_OBJECTS:${PROJECT_NAME}-object>)
target_include_directories(foo_static PUBLIC ${object_include_dirs})
target_link_libraries(foo_static PUBLIC ${object_link_libs})

但是来吧,必须有更好的方法:/

答案 1 :(得分:4)

传递属性似乎只有在通过一系列target_link_library调用链接目标时才有效。在您的情况下,foo-objectfoo之间没有这样的链接。

如果您将源文件添加到foo,那么该文件也应该无法从foo-object看到包含目录。

这可能是OBJECT库设计的疏忽,因为它基本上打破了那些库的传递属性。

答案 2 :(得分:0)

在CMake <3.12上,使用以下命令:

add_library(foo SHARED $<TARGET_OBJECTS:${PROJECT_NAME}-object>)
target_include_directories(foo
    PRIVATE
    $<TARGET_PROPERTY:${PROJECT_NAME}-object,INTERFACE_INCLUDE_DIRECTORIES>)

在CMake> = 3.12上,看看at this answer(感谢@ian5v的建议)


工作原理:

  

target_include_directories(...)

     

...

     

PUBLICINTERFACE项将填充INTERFACE_INCLUDE_DIRECTORIES的{​​{1}}属性。

因此,<target>上已设置${PROJECT_NAME}-object。我们需要获取此属性并将其插入我们自己的包含路径。

这似乎是"generator expressions"的工作!特别是INTERFACE_INCLUDE_DIRECTORIES似乎在这里很方便。

我们的$<TARGET_PROPERTY:tgt,prop>将是tgt,并且我们正在尝试提取${PROJECT_NAME}-object的所有值,因此INTERFACE_INCLUDE_DIRECTORIES将是INTERFACE_INCLUDE_DIRECTORIES。 / p>

这出现在prop上,这正是我们在上面的代码中所使用的。

答案 3 :(得分:0)

对我来说,类似以下的内容似乎有效:

add_library(foo_objects OBJECT src/foo.cpp src/foo.hpp)
set_property(TARGET foo_objects PROPERTY POSITION_INDEPENDENT_CODE ON)
target_include_directories(foo_objects PUBLIC
    "$<BUILD_INTERFACE:src>"
    "$<INSTALL_INTERFACE:include>")

add_library(foo_shared SHARED)
add_library(foo_static STATIC)
target_link_libraries(foo_shared PUBLIC foo_objects)
target_link_libraries(foo_static PUBLIC foo_objects)