【问题标题】:CMake target_include_directories meaning of scopeCMake target_include_directories 范围的含义
【发布时间】:2014-12-02 07:16:10
【问题描述】:

与CMake的target_include_directories相关的关键字PUBLICPRIVATEINTERFACE是什么意思?

【问题讨论】:

标签: cmake


【解决方案1】:

这些关键字用于告诉何时需要您传递给目标的包含目录列表。 when 表示是否需要这些包含目录:

  • 编译该目标本身。
  • 编译依赖于该目标的其他目标(例如使用其公共标头)。
  • 在上述两种情况下。

当 CMake 编译目标时,它使用目标 INCLUDE_DIRECTORIESCOMPILE_DEFINITIONSCOMPILE_OPTIONS 属性。当您在 target_include_directories() 等中使用 PRIVATE 关键字时,您会告诉 CMake 填充这些目标属性。

当 CMake 检测到目标 A 和另一个目标 B 之间的依赖关系时(例如使用 target_link_libraries(A B) 命令时),它会将 B 使用要求传递到 A 目标。那些目标使用要求是依赖于B 的任何目标必须满足的包含目录、编译定义等。它们由上面列出的属性的INTERFACE_* 版本(如INTERFACE_INCLUDE_DIRECTORIES)指定,并在调用target_*() 命令时使用INTERFACE 关键字填充。

PUBLIC 关键字大致意思是PRIVATE + INTERFACE

因此,假设您正在创建一个库 A,它使用了一些 Boost 标头。你会这样做:

  • target_include_directories(A PRIVATE ${Boost_INCLUDE_DIRS}) 如果您只在源文件 (.cpp) 或私有头文件 (.h) 中使用这些 Boost 标头。
  • target_include_directories(A INTERFACE ${Boost_INCLUDE_DIRS}) 如果您不在源文件中使用那些 Boost 头文件(因此,不需要它们来编译 A)。我真的想不出一个真实的例子。
  • target_include_directories(A PUBLIC ${Boost_INCLUDE_DIRS}) 如果您在公共头文件中使用这些 Boost 头文件,这些头文件既包含在 A 的某些源文件中,也可能包含在您的 A 库的任何其他客户端中。

CMake 3.0 文档对此build specification and usage requirements 属性有更多详细信息。

【讨论】:

  • 关于INTERFACE 的真实示例。 target_include_directories(libname INTERFACE include PRIVATE include/libname)。这意味着您可以在库中直接包含文件,但作为库的用户,您必须先插入 libname/
  • 这个答案对我来说对于创建库很有意义。但是为一个可执行的目标调用 target_include_directories 怎么样?
  • @NormanPellet:如果您需要设置包含目录,可以找到这些可执行文件使用的头文件(例如:Boost::Program_options,如果您使用它来解析 main() 函数中的参数)。在这种情况下,您可能会使用PRIVATE 关键字,因为需要这些文件来编译可执行文件本身。不过,我不知道INTERFACEPUBLIC 在可执行文件上是否有用。
  • "这意味着您可以在库中直接包含文件,但作为库的用户,您必须先插入 libname/。"这可能适用于您的库中的实现文件。但是,它不适用于库中的其他“公共”头文件。如果include/libname/file1.h 包含include/libname/file2.h 仅使用#include <file2.h>,则当使用您的库的可执行文件包含file1.h(通过#include <libname/file1.h>)时,它将中断。 include/libname 不会在可执行文件的包含搜索路径中,因此无法找到 file2.h
  • @ KaareZ “但作为库的用户,您必须先插入 libname/。”?那是什么?能否请您为我详细解释一下?
【解决方案2】:

需要 INTERFACE、PUBLIC 和 PRIVATE 关键字来指定 以下论点的范围。 PRIVATE 和 PUBLIC 项目将 填充 的 INCLUDE_DIRECTORIES 属性。公众和 INTERFACE 项目将填充 INTERFACE_INCLUDE_DIRECTORIES 的属性。以下参数指定包括 目录。

来自文档:http://www.cmake.org/cmake/help/v3.0/command/target_include_directories.html

用我自己的话改写文档:

  • 您想将目录添加到目标的包含目录列表中
  • 使用 PRIVATE 将目录添加到目标的包含目录中
  • 使用 INTERFACE,目标不会被修改,但 INTERFACE_INCLUDE_DIRECTORIES 由目录扩展。该变量是库的公共包含目录列表。
  • 使用 PUBLIC 会执行来自 PRIVATE 和 INTERFACE 的操作。

【讨论】:

  • 我浏览了 CMAKE 文档,但我仍然不明白它们的实际含义和上下文(制作文件或它们如何编译)?
  • @Sirish:我试图改写文档,希望对您有所帮助。
  • @usr1234567 如果我们不指定关键字的默认值,它是什么?我看到很多项目只是使用target_link_librariestarget_include_directories 而不指定PRIVATEPUBLICINTERFACE 关键字。
  • @IgNite 见cmake.org/pipermail/cmake/2016-May/063400.html,倒数第二段。这很复杂:-)
猜你喜欢
  • 2021-04-17
  • 1970-01-01
  • 2015-11-05
  • 2016-09-09
  • 2021-09-27
  • 2022-07-10
  • 2021-10-24
相关资源
最近更新 更多