我是CMAKE的新手,对与target_link_libraries相关的PUBLIC,PRIVATE和INTERFACE关键字感到困惑.文档提到它们可用于在一个命令中指定链接依赖关系和链接接口.
链接依赖关系和链接接口实际上意味着什么?
ste*_*ire 139
如果要创建共享库和源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
Lar*_*dua 25
这不是我的创意,但这个非常有用的解释帮助我理解了情况。下面引用最重要的部分供参考:
- 当 A 将 B 作为PRIVATE链接时,表示 A 在其实现中使用了 B,但 B 并未在 A 的公共 API 的任何部分中使用。任何调用 A 的代码都不需要直接引用 B 中的任何内容。这方面的一个例子是网络库 A,它可以构建为在内部使用多个不同的 SSL 库之一(B 代表)。A 为客户端代码提供了一个统一的接口,它不引用任何内部 SSL 数据结构或函数。客户端代码不知道 A 正在使用什么 SSL 实现 (B),
客户端代码也不需要关心。- 当 A 将 B 作为INTERFACE链接时,表示 A 在其实现中没有使用 B,但 B 在 A 的公共 API 中使用。调用 A 的代码可能需要引用 B 中的内容才能进行此类调用。一个例子是接口库,它只是将调用转发到另一个库,但除了通过指针或引用之外,实际上并不引用途中的对象。另一个例子是 A 在 CMake 中定义为接口库,这意味着它本身没有实际的实现,它实际上只是其他库的集合(我在这里可能过于简化,但你明白了)。
- 当 A 以PUBLIC链接 B 时,它本质上是 PRIVATE 和 INTERFACE 的组合。它说 A 在其实现中使用 B,并且 B 也在 A 的公共 API 中使用。
首先考虑这对于包含搜索路径意味着什么。如果某些内容链接到 A,并且 B 位于 A 的公共 API 中,则它还需要来自 B 的任何包含搜索路径。因此,如果 A 作为 PUBLIC 或 INTERFACE 链接 B,则为目标 B 定义的任何标头搜索路径也将适用于链接到 A 的任何内容。B 的任何 PRIVATE 标头搜索路径将不会传递到仅链接到 A 的任何内容. target_include_directories() 命令处理此问题。使用 target_compile_definitions() 和 target_compile_options() 类似地处理编译标志的情况。
现在考虑实际涉及的库的情况。如果 A 是共享库,则 A 将在其中编码对 B 的依赖项。可以使用 Linux 上的 ldd、Mac 上的 otool 和 Windows 上的 Dependency Walker(又名depends.exe)等工具来检查此信息。如果其他代码直接链接到 A,那么它也会将对 A 的依赖项编码到其中。但是,除非 A 作为 PUBLIC 或 INTERFACE 链接 B,否则它不会依赖于 B。到目前为止,一切都很好。然而,如果 A 是静态库,情况就会改变。静态库不携带有关它们所依赖的其他库的信息。因此,当 A 将 B 作为 PRIVATE 链接并且另一个目标 C 链接 A 时,CMake 仍会将 B 添加到要为 C 链接的库列表中,因为 A 需要 B 的部分内容,但 A 本身没有这种依赖关系编码到其中。因此,即使 B 是 A 的内部实现细节,C 仍然需要将 B 添加到链接器命令中,CMake 可以方便地为您处理。
如果您仔细观察,您会注意到,当 A 将 B 作为 PRIVATE 链接时,B 的包含目录永远不会传播到链接到 A 的内容,但如果 A 是静态库,则 B 的链接表现为以下 关系:是公开的。静态库的这种“私有变为公共”行为仅适用于 链接,不适用于其他依赖项(编译器选项/标志和包含搜索路径)。所有这一切的结果是,如果您根据上面点中的说明选择 PRIVATE、PUBLIC 或 INTERFACE,那么 CMake 将确保依赖项传播到需要它们的位置,无论库是静态的还是共享的。当然,这依赖于开发人员没有遗漏任何依赖项或指定错误的 PRIVATE/PUBLIC/INTERFACE 关系。
ika*_*aro 11
@steveire 接受的答案很棒。我只是想添加一个表格以快速查看差异:
.-----------.------------------.----------------.
| | Linked by target | Link interface |
:-----------+------------------+----------------:
| PUBLIC | X | X |
:-----------+------------------+----------------:
| PRIVATE | X | |
:-----------+------------------+----------------:
| INTERFACE | | X |
'-----------'------------------'----------------'
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
11889 次 |
最近记录: |