【问题标题】:is there something similar to target_include_files in cmakecmake中是否有类似于target_include_files的东西
【发布时间】:2020-10-12 13:08:47
【问题描述】:

有没有办法以与目标包含目录相同的方式添加文件,但针对单个文件?

我的用例是这样的。我使用了很多模板和概念,而且我的头文件变得越来越庞大。我真的很喜欢将实现与定义分开,所以想要这样的东西:

.h 文件

template <typename T>
T foo(T bar);

#include <name_of_implementation_file>

实现.h文件

template <typename T>
T foo(T bar) { return bar; };

当前包含必须如下所示:#include "path/to/implementation_file_name"

这很烦人,因为它让以后的重构变得很痛苦。我也不想添加只有 1 或 2 个文件的额外目录并调用 target_include_directories。我不想只是include,因为我的项目是一个库,我不希望用户能够包含实现文件。我也在构建多个目标,并希望将它们包含的文件分开。

【问题讨论】:

  • 首先,你不应该 #include cpp 文件。
  • 对于模板,你不需要头文件本身的完整定义吗?您可以保留 .cpp 文件,但它基本上是空的。
  • @0x5453 当然可以,所以假设实现文件是另一个头文件
  • @squareskittles 我在头文件的底部包含了实现,所以它仍然是完整的,可以编译+链接
  • 创建一个目录。将文件复制到该目录。添加该目录以包含路径。 |无论如何,只需将实现与标题保持在同一目录中并包含文件名。 and I don't want the user to be able to include the implementation files 您是否在源文件中实例化模板?很可能不是,这使得它不可能 - 用户使用模板,他必须看到实现......

标签: c++ cmake


【解决方案1】:

TLDR:用户要使用模板,用户必须看到它全部

cmake中是否有类似target_include_files的东西

不,没有。

有没有办法以与目标包含目录相同的方式添加文件,但针对单个文件?

唯一的办法是:

  • 创建一个空目录(在CMAKE_CURRENT_BINARY_DIR 中的某处)
  • 将文件复制到那里
  • 将该目录添加到 include_directories

只是为了好玩,看起来很容易用未经测试的伪代码实现:

function(target_include_files target mode)
    string(MD5 dir "${ARGN}")
    set(dir ${CMAKE_CURRENT_BINARY_DIR}/${dir})
    file(MAKE_DIRECTORY ${dir})
    foreach(i IN LISTS ARGN)
       # TODO: replace with build-time generation
        configure_file(${i} ${CMAKE_CURRENT_BINARY_DIR}/${dir} COPYONLY)
    endforeach()
    target_include_directories(${target} ${mode} ${dir})
endfunction()

我真的很喜欢将实现与定义分开,所以想要这样的东西:

最简单的方法是将实现文件与头文件保存在同一目录中 - 这样,简单的#include "file" 就足够了,因为包含" 首先搜索当前包含目录。如果不是 - 将实现文件移动到子目录,并且只包含相对于当前文件的子目录。如果不是 - 将包含实现文件的其他目录添加到搜索路径。

我不希望用户能够包含实现文件。

因此,正如一些闭源 C++ 库所做的那样,为源文件中的常见类型显式实例化模板,并在头文件中为它们模板化的类型提供外部显式实例化声明。这会导致您的模板的可用性仅限于您显式实例化的类型。

我希望用户能够自己[实例化模板],

那么不可能这样做(或者它会使您的库无法使用且毫无意义)。任何使用模板的人,为了实例化它必须查看模板的整个定义(或者,在某些情况下,可以在一个单独的翻译单元,如上所述)。如果用户看不到他使用的所有符号的完整定义,并且不会提供外部显式实例化,则用户最终会得到模板中的 undefined reference to 符号。

为了进一步研究,我建议只研究 C++ 上下文中的“显式实例化”、模板以及何时使用它以及它与“隐式实例化”有何不同。如需进一步研究,请查看有关编译器和链接器如何工作、什么是链接以及如何设计 C++ 模板的材料。

【讨论】:

    猜你喜欢
    • 2011-12-04
    • 2011-01-07
    • 2014-09-22
    • 2011-05-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多