【问题标题】:How to create a library without headers?如何创建没有标题的库?
【发布时间】:2021-09-27 05:49:04
【问题描述】:

我们有 C++20 中的模块,我们可以在我们的代码中完全删除 #include 吗?

例如,我们可以写

import boost.asio;
...

代替

#include <boost/asio.hpp>
...

过去我们需要这些步骤来安装一个库:

  • 将所有源文件 (.cpp) 编译成对象 (.o)。
  • 将它们打包到库(.a 或 .so)中。
  • 将标头安装到/usr/include
  • 将库文件安装到/usr/lib

在 C++20 中,我们可以:

  • 编译所有源文件,但每个源文件可能生成一个对象 (.o) 和一个编译模块接口 (CMI)。对于 gcc,它们具有 .gcm 后缀。
  • 将对象 (.o) 打包到库(.a 或 .so)中。
  • 将库文件安装到/usr/lib
  • 将 CMI 安装到某个路径中。

但是使用 CMI 发布您的库会导致问题:

  • 我们没有专门的文件夹来放置 CMI(我猜可能是 /usr/include/c++-modules)。
  • 不同的编译器产生不同的 CMI。开发人员为他们的库提供不同版本的 CMI 是很糟糕的。
  • 如果我们根据模块 B 编译模块 A,但使用不同的编译标志怎么办?不同的标志可能不会引起您的注意,但可能会导致潜在的错误。

这不是用 CMI 替换标头的好方法。那么我们如何才能从 C++ 中完全删除标头呢?


我不是在谈论标准库,因为模块化 c++ 标准库是在 c++23 中引入的。

【问题讨论】:

  • 对于不同的标志,您已经遇到了二进制 (.a/.so) 的问题...
  • 鉴于编译器和工具支持介于不存在和处于起步阶段之间,我认为这个问题还早了 5 年。
  • @Jarod42 我对 OP 抱怨的解释是,从单头文件+多二进制文件到多 CMI+多二进制文件感觉像是倒退了一步。
  • 今天要做这件事是非常雄心勃勃的。我建议等到您使用的编译器都支持该功能,并且您已验证该功能适用​​于您的项目。
  • 在系统级别“安装库”的想法让我觉得很奇怪。库和依赖项应该是每个项目的,而不是每个系统的。如果两个项目共享完全相同的库依赖项,则您的库管理代码可以共享它。这适用于.o 文件;两个不同的编译器可以编译不兼容的.o.dylib 或来自同一源的任何文件。他们只是按照惯例同意。

标签: c++ c++20 c++-modules


【解决方案1】:

模块并不意味着是一个二进制分发机制;您应该期望提供模块接口文件(,编译为库中目标文件的相同文件, 它们不是头文件)以非常类似于头文件的方式,并将 CMI 生成和缓存留给客户端的编译器和构建树(分别)。因此,每个客户端只有在使用给定模块的第一个翻译单元之后才能实现构建速度优势。

其他共享机制很可能会在实践中出现,但这里的重要部分是它本质上并不比现有构建策略更复​​杂或更不兼容。

【讨论】:

  • 所以在发布我们的库时,我们需要扫描我们的项目,并将所有函数、全局变量、结构体和类的声明提取到一个单独的.cxx文件中,这个文件称为“模块导出文件”并像标题一样安装到系统中。当用户构建依赖于我们的库的东西时,他们会从我们的“模块导出文件”生成 CMI 并编译它们的源代码。现在没有任何工具可以进行扫描和提取,我们需要开发一个。
  • @aleck099:模块接口是手写的,不是提取出来的,好在冗余度和头文件一样或者更少。当前未安装的源文件变成了也未安装的模块实现单元,或者可能被合并到已安装的接口中(减少冗余),至少在某些实现中没有资格内联。
  • 一个大的项目可能有很多头文件,我们通常会写几个头文件#include其他相关头文件,为用户提供一个简单易用的方法来使用我们的库——他们只是@987654322 @一个文件。至于模块,可能还有很多模块接口。我们是写几个模块接口给import他们,还是用另一个叫做“模块分区”的特性来集成它们?
  • @aleck099:您通常应该拥有比头文件更少的模块,因为通过隔离减少编译时间的压力会减少。例如,有人认真建议整个标准库可能是一个模块(但这还没有决定)。另一方面,像 Boost 这样的大型库可能会选择每个组件一个模块。模块分区主要用于依赖管理,但实际上也可以用于控制文件大小。
猜你喜欢
  • 2023-03-31
  • 1970-01-01
  • 1970-01-01
  • 2011-02-08
  • 1970-01-01
  • 2020-01-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多