如何在没有 headers 的情况下创建库?
How to create a library without headers?
我们在 C++20 中有模块,我们可以完全删除代码中的 #include
吗?
比如我们可以这样写
import boost.asio;
...
而不是
#include <boost/asio.hpp>
...
过去我们需要这些步骤来安装库:
- 将所有源文件 (.cpp) 编译成 objects (.o)。
- 将它们打包到库中(.a 或 .so)。
- 将 headers 安装到
/usr/include
。
- 将库文件安装到
/usr/lib
。
在 C++20 中,我们可以:
- 编译所有源文件,但每个源文件可能会生成一个 object (.o) 和一个 编译模块接口 (CMI)。对于 gcc,它们具有 .gcm 后缀。
- 将 objects (.o) 打包到库中(.a 或 .so)。
- 将库文件安装到
/usr/lib
。
- 将 CMI 安装到某个路径。
但是使用 CMI 发布你的库会导致问题:
- 我们没有专门的文件夹来放置 CMI(我猜可能
/usr/include/c++-modules
)。
- 不同的编译器产生不同的CMI。开发人员为他们的库提供不同版本的 CMI 是很糟糕的。
- 如果我们依赖模块B编译模块A,但是使用不同的编译标志呢?不同的标志可能不会引起您的注意,但可能会导致潜在的错误。
用 CMI 替换 headers 不是一个好方法。那么我们如何才能从 C++ 中完全删除 headers 呢?
我不是在谈论标准库,因为模块化的 c++ 标准库是在 c++23 中引入的。
模块并不意味着是二进制分发机制;您应该期望提供模块接口文件(即,将相同的文件编译为库中的目标文件,
它们不是头文件)以非常 类似头文件的方式 并将 CMI 生成和缓存留给客户端的编译器和构建树(分别)。因此,只有在使用给定模块的第一个翻译单元之后,每个客户端才能实现构建速度优势。
其他共享机制很可能会在实践中出现,但重要的是它本质上并不比现有的构建策略更复杂或更不兼容。
我们在 C++20 中有模块,我们可以完全删除代码中的 #include
吗?
比如我们可以这样写
import boost.asio;
...
而不是
#include <boost/asio.hpp>
...
过去我们需要这些步骤来安装库:
- 将所有源文件 (.cpp) 编译成 objects (.o)。
- 将它们打包到库中(.a 或 .so)。
- 将 headers 安装到
/usr/include
。 - 将库文件安装到
/usr/lib
。
在 C++20 中,我们可以:
- 编译所有源文件,但每个源文件可能会生成一个 object (.o) 和一个 编译模块接口 (CMI)。对于 gcc,它们具有 .gcm 后缀。
- 将 objects (.o) 打包到库中(.a 或 .so)。
- 将库文件安装到
/usr/lib
。 - 将 CMI 安装到某个路径。
但是使用 CMI 发布你的库会导致问题:
- 我们没有专门的文件夹来放置 CMI(我猜可能
/usr/include/c++-modules
)。 - 不同的编译器产生不同的CMI。开发人员为他们的库提供不同版本的 CMI 是很糟糕的。
- 如果我们依赖模块B编译模块A,但是使用不同的编译标志呢?不同的标志可能不会引起您的注意,但可能会导致潜在的错误。
用 CMI 替换 headers 不是一个好方法。那么我们如何才能从 C++ 中完全删除 headers 呢?
我不是在谈论标准库,因为模块化的 c++ 标准库是在 c++23 中引入的。
模块并不意味着是二进制分发机制;您应该期望提供模块接口文件(即,将相同的文件编译为库中的目标文件, 它们不是头文件)以非常 类似头文件的方式 并将 CMI 生成和缓存留给客户端的编译器和构建树(分别)。因此,只有在使用给定模块的第一个翻译单元之后,每个客户端才能实现构建速度优势。
其他共享机制很可能会在实践中出现,但重要的是它本质上并不比现有的构建策略更复杂或更不兼容。