以下是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
,一切都会正常编译。
如何让foo
和foo_static
自动使用(并根据它们转发内容)包含来自foo-object
的目录?
答案 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-object
和foo
之间没有这样的链接。
如果您将源文件添加到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(...)
...
PUBLIC
和INTERFACE
项将填充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)