2天时间,聊今年最热的 Agent、上下文工程、AI 产品创新等话题。2025 年最后一场~ 了解详情
写点什么

LLVM 提议向 C 语言中加入模块机制

  • 2012-12-05
  • 本文字数:2096 字

    阅读完需:约 7 分钟

在今年 11 月的 LLVM 开发者大会上,来自 Apple 的 Doug Gregor 做了一场讲座,主题是向 C 语言中加入模块(Module)机制。讲座中提到:

长期以来,C 的预处理器就是程序员和工具的问题之源。写得不好的头文件致使宏污染和包含顺序等问题大量存在,程序员必须不断地与之斗争。为了缓解这些问题,开发者习惯上采用各种预处理器变通方案,比如 LONG_MACRO_PREFIXES 这种风格的很长的宏前缀,#include 防卫语句,或是临时使用#undef 来处理库中的宏。

另一方面,工具也必须能够处理重复解析相同头文件时所面对的内在可伸缩性问题,因为即便程序员并不希望,但不同的处理环境还是可能影响头文件的解释方式。

模块试图解决这一问题,它的理念是:隔离特定库的接口,并将其一次性编译为一种高效的、序列化的表示形式,当使用该库时,可以高效地导入,从而改进程序员的体验和编译过程的伸缩性。

该提议的基本前提是,作为一种加速编译并允许复用之前解析过的头文件的手段,即使编译最简单的文件,也要避免使用预处理器来包含大量头文件。在一个与“Hello World”同名的例子中,他强调到,一个包含 64 个字符的 C 程序经过预处理变成了 11 074 个字符,而一个包含 81 个字符的 C++ 程序预处理后变成了 1 161 033 个字符。他还指出,因为包含要依赖于预处理器当时的状态,所以重新解析头文件可能让程序很脆弱(比如,如果在 #include 之前使用#define FILE “myfile.txt”,预处理器会破坏头文件,从而导致构建失败)。

他的建议是使用一个新关键字 import 来加载模块。不同于预处理器的文本包含方式,编译器能够理解该模块是一个固定的版本,所以只解析一次。如果多次使用相同的模块,可以使用前面解析过的同一数据结构,不需要每次都重新解析。

模块也可以嵌套,这允许导入子模块;在所给的例子中,他演示了 std 模块中的子模块 stdio 可以使用 import std.stdio 来包含。导入模块之后,其中的所有公开 API 就都导入到客户代码中了,但非公开 API 是隐藏的。为了实现这种控制,模块需要声明哪些接口是公开的,哪些是非公开的,这可以利用 public 关键字:

复制代码
// stdio.c
export std.stdio:
public:
typedef struct {
} FILE;
int printf(const char*, …) {
}

请注意,在这个例子中,仅提供实现文件就可以了,不需要头文件。export 包含了模块的名字,这里就是 std.stdio。public 用于区分 API 的公开部分与非公开部分。这可以编译为库以及带有充分元数据的函数类型和宏,供客户代码使用。

当然,这只是对未来的一个建议,并非标准。那么这种方式应如何实现呢?建议使用头文件来处理现有模块的公开 API,并将模块定义为一组头文件:

复制代码
// /usr/include/module.map
module std {
module stdio { header "stdio.h" }
module stdlib { header "stdlib.h" }
module math { header "math.h" }
exclude header "assert.h"
}
module ClangAST {
umbrella "AST/AST.h"
module * { }
} // 可以使用“import ClangAST.Decl”来导入 AST/Decl.h

为便于以后生成模块(部分原因是方便 Objective-C 框架导出模块),“umbrella module”机制允许将一个目录下的一组头文件作为单个模块导出。

适于处理模块的编译器可以在头文件上利用单独的一遍(Pass)来构建模块,之后在随后的头文件中复用该模块的信息。(编译好的模块应采用什么格式尚未指定,可能交由具体的编译器定义。)模块中也可以加入附加的元信息,比如说明模块运行所需的库。这允许编译器处理每个模块所需的链接标记,从而避免了用户在链接时提供一大堆 -l 标记。

要使用模块,客户代码唯一需要修改的是将#include 替换为等价的 import。此外,因为在预处理后,模块中带有导出的函数和类型等信息,因此能够更好地进行编译诊断;利用这些信息,编译器报错和 IDE 快速修复等功能也能提示所需的 import,而不仅仅是直接失败。

最后,复用模块信息也允许将调试信息与模块关联起来,而非让这些信息重复出现在每个目标文件中。编译器和链接器就可以少生成一些调试信息,反过来又加速了编译过程。模块也为调试器提供了额外的类型信息(而不是将类型信息内联到每个目标文件中),因此调试器可以报告模块中定义的正确类型。

模块提议的净效应是,它提供了一种能够兼容现有工具的迁移途径,同时,在用户无需对原有代码进行多少修改的条件下,还带来了一些优点(主要是提升了编译速度,并改进了诊断错误消息和调试)。它也支持文件增量式升级,支持增量式地将单个预处理器指令切换为基于模块的导入机制。同时无需将编译速度测量当做模块表示的一部分,该工作已经在 LLVM 实现这些模块时进行了。虽然模块机制没有考虑版本或命名空间(很大程度上是因为必须满足向后兼容性),但该机制如果得以广泛应用的话,能够显著提升 C 和 C++ 程序的编译速度。此外,向后兼容性被明确提了出来,像 LLVM 的块(block)规范,当需要的时候很可能用于支持其他编译器或规范中的包含。不过,在广为使用的 C 和 C++ 编译器中,LLVM 编译器工具链是唯一的一个保持创新并以身作则的了。其他编译器是否会引入这些特性,可能取决于 LLVM 实现方案能否成功以及能够带来哪些益处。

查看英文原文 LLVM Proposes Adding Modules to C

2012-12-05 05:473191
用户头像
臧秀涛 略懂技术的运营同学。

发布了 300 篇内容, 共 149.7 次阅读, 收获喜欢 35 次。

关注

评论

发布
暂无评论
发现更多内容

消除if-else之为Enum添加行为实现策略模式

topsion

Java clean code

数据分析实际案例之:pandas在餐厅评分数据中的使用

程序那些事

Python 数据分析 pandas 程序那些事 2月月更

白盒绕过、黑盒绕过——绕过waf(一)

喀拉峻

网络安全

低代码如何解锁制造业数字生态系统?

TOBESOFT特碧软件

低代码 数字化 TOBESOFT

网络安全kali渗透学习 web渗透入门 WireShark抓包及常用协议分析

学神来啦

DevOps进阶(四):Jenkins 实战之构建定时项目与远程触发器

No Silver Bullet

DevOps jenkins 定时器 2月月更 触发器

知名信息安全厂商渔翁信息加入龙蜥社区,共建开源生态

OpenAnolis小助手

Linux 开源 信息安全

G7完成2亿美元融资

极客天地

CTF中PHP相关题目考点总结(二)

H

网络安全 CTF

musl堆利用技巧,你知道多少

网络安全学海

网络安全 信息安全 渗透测试 WEB安全 安全漏洞

优秀程序员的30种思维--分析总结篇(13/100)

hackstoic

架构思维

北京冬奥有哪些AI“黑科技”?

澳鹏Appen

人工智能 自动驾驶 计算机视觉 nlp 黑科技

极光笔记 | 极光推送业务无中断迁移上云实践

极光GPTBots-极光推送

企业上云 后端技术 上云

英特尔CEO:开启超级摩尔定律的时代,推动前沿进展

科技新消息

Kubernetes应用,如何选择适合你的Kubernetes应用发布模式

阿里云云效

阿里云 Kubernetes 云原生 CI/CD 发布模式

DG-IoT: 开源项目职业教育助力解决过度补课难题

dgiot

物联网 2月月更 2月日更 dgiot dgiot物联网

一周信创舆情观察(2.7~2.13)

统小信uos

Java线程池必知必会

CRMEB

使用 Flink Hudi 构建流式数据湖平台

Apache Flink

大数据 flink 编程 数据湖 实时计算

如何构建一个流量无损的在线应用架构 | 专题中篇

阿里巴巴中间件

阿里云 云原生 中间件

如何构建一个流量无损的在线应用架构 | 专题尾篇

阿里巴巴中间件

阿里云 云原生 中间件 EDAS

手把手带你基于嵌入式Linux移植samba服务

华为云开发者联盟

Linux 嵌入式 Samba UNIX系统 SMB协议

教你用Elastic Search:运行第一条Hello World搜索命令 原创

华为云开发者联盟

数据库 全文检索 索引 Elastic Search 分布式实时搜索引擎

声网Agora Lipsync 技术揭秘:通过实时语音驱动人像模拟真人说话

声网

人工智能 音视频

Web_Components 系列(九)—— Shadow Host 的 CSS 选择器

编程三昧

前端 组件化 2月月更 WebComponent

哪个低代码平台上手度对小白更友好?专业测评来了!

优秀

低代码 应用开发

产品经理沟通技巧

史前靓仔

职场 产品经理 沟通技巧

MASA Framework - DDD设计(1)

MASA技术团队

C# .net 微软 框架 Framework

云原生多云应用利器--Karmada 总览篇

Daocloud 道客

云原生 多云管理 Karmada

新年新知 | 2022必读的5篇行业趋势(内附下载)

LigaAI

AI 创新 行业趋势 新能源

「重磅消息」OpenMLDB 官方网站 正式上线!

第四范式开发者社区

机器学习 大数据 OpenMLDB

LLVM提议向C语言中加入模块机制_C++_Alex Blewitt_InfoQ精选文章