我是CMAKE的新手,对与target_link_libraries相关的PUBLIC,PRIVATE和INTERFACE关键字感到困惑。文档提到它们可用于在一个命令中指定链接依赖关系和链接接口。
链接依赖关系和链接接口实际意味着什么?
答案 0 :(得分:115)
如果要创建共享库和源cpp文件#include另一个库的头(例如,Say,QtNetwork),但是您的头文件不包含QtNetwork头,那么QtNetwork是PRIVATE
依赖性。
如果源文件和标题包含其他库的标题,则它是PUBLIC
依赖项。
如果您的头文件而不是您的源文件包含另一个库的标头,那么它是INTERFACE
依赖项。
PUBLIC
和INTERFACE
依赖项的其他构建属性会传播到使用库。 http://www.cmake.org/cmake/help/v3.0/manual/cmake-buildsystem.7.html#transitive-usage-requirements
答案 1 :(得分:3)
@steveire接受的答案很好。我只想添加一个表以快速查看区别:
.-----------.------------------.----------------.
| | Linked by target | Link interface |
:-----------+------------------+----------------:
| PUBLIC | X | X |
:-----------+------------------+----------------:
| PRIVATE | X | |
:-----------+------------------+----------------:
| INTERFACE | | X |
'-----------'------------------'----------------'
答案 2 :(得分:0)
某些回答仅说何时使用PRIVATE / PUBLIC / INTERFACE,但是影响被忽略。请参考:CMake-Public-Private-Interface
公共
紧随PUBLIC之后的所有对象都将用于链接到当前目标,并提供与依赖于当前目标的其他目标的接口。
PRIVATE
PRIVATE之后的所有对象将仅用于链接到当前目标。
界面
INTERFACE之后的所有对象将仅用于提供与当前目标有依赖关系的其他目标的接口。
答案 3 :(得分:0)
不是我的心血结晶,但这 extremely useful explanation 帮助我了解了情况。下面引用最重要的部分以供参考:
<块引用>首先考虑这对包含搜索路径意味着什么。如果有事 针对 A 的链接,它还需要来自 B 的任何包含搜索路径,如果 B 在 A 的公共 API 中。因此,如果 A 在 B 中链接为 PUBLIC 或 INTERFACE,则为目标 B 定义的任何标头搜索路径也将 适用于任何链接到 A. 的任何 PRIVATE 标头搜索路径 B 不会被带到任何只链接到 A 的东西。 target_include_directories() 命令处理这个。情况与 编译标志类似地用 target_compile_definitions() 处理 和 target_compile_options()。
现在考虑所涉及的实际库的情况。如果 A 是 一个共享库,那么 A 将在其中编码对 B 的依赖。 可以使用 Linux 上的 ldd、otool 等工具检查此信息 在 Mac 上,还有类似 Dependency Walker(又名depends.exe)的东西 视窗。如果其他代码直接链接到 A,那么它也会有 将其编码为对 A 的依赖。然而,它不会有 依赖于 B,除非 A 将 B 中的链接作为 PUBLIC 或 INTERFACE。到目前为止,所以 好的。但是,如果 A 是静态库,情况就会改变。 静态库不携带有关它们的其他库的信息 取决于。出于这个原因,当 A 在 B 中作为 PRIVATE 链接而另一个 目标 C 链接在 A 中,CMake 仍会将 B 添加到库列表中 为 C 链接,因为 A 需要 B 的一部分,但 A 本身 没有编码到其中的依赖项。所以即使 B 是一个 A、C 的内部实现细节仍然需要将 B 添加到 链接器命令,CMake 方便地为您处理。
如果你仔细观察,你会注意到当 B 中的 A 链接为 PRIVATE,B 的包含目录永远不会传播 到链接到 A 的东西,但如果 A 是一个静态库,那么 B 的链接表现得好像关系是公开的。静态库的这种 PRIVATE-becomes-PUBLIC 行为仅适用于 这 链接,而不是其他依赖项(编译器选项/标志和包含搜索路径)。所有这一切的结果是,如果您选择 PRIVATE、PUBLIC 或 INTERFACE 基于点中的解释 以上几点,然后 CMake 将确保依赖项传播到 需要它们的地方,无论库是静态的还是 共享。当然,这确实取决于您,开发人员不会错过 任何依赖项或指定错误的 PRIVATE/PUBLIC/INTERFACE 关系。