- 这个结构体的 sizeof 大小是多少?
- unsigned 与 long long 相乘的类型是什么?
- 你是否遇到过,想要测试一个简短的 C++ 代码,而为创建一个新文件,等待编译的漫长过程感到烦躁?
- 可不可以让 C++ 像 python 一样交互地运行?
Well,你需要的是一个交互式 C++ 解释器!
你没听错,在技术日新月异的今天,人们可以把解释型的语言做出“编译器”,把编译型的语言做出解释器……今天要介绍的 cling 正是一个基于 LLVM 和 clang 的交互式 C++ 解释器。
炫技时刻
在终端中启动 cling:
$ cling -std=c++17
会看见这样一个界面:
****************** CLING ******************
* Type C++ code and press enter to run it *
* Type .q to exit *
*******************************************
[cling]$
在 $ 后面就可以输入 C++ 代码了:
[cling]$ 15u*16ll
(long long) 240
[cling]$ struct node {
[cling]$ ? int v, sz;
[cling]$ ? node *ch[26], *fa;
[cling]$ ? }
[cling]$ sizeof(node)
(unsigned long) 224
cling 很棒地实现了 REPL,即 Read-evaluate-print loop,读取—求值—打印的循环。玩过 python 的都知道,每当输入一行表达式就立即得出值(以及类型)的感觉。
在 cling 中,没有分号结尾的被视为表达式,会显示类型和值,以分号结尾的语句则不会。
再来看一些例子:
[cling]$ long long v = 1145141919810
(long long) 1145141919810
[cling]$ scanf("%d", &v)
input_line_24:2:14: warning: format specifies type 'int *' but the argument has type 'long long *' [-Wformat]
scanf("%d", &v)
~~ ^~
%lld
32767
(int) 1
[cling]$ v
(long long) 1142461333503
编译警告很友好,并且你可能会注意到有个 (int) 1
——如果你平时比较粗心,你可能今天才想起 scanf
是有返回值的!
设计测试运算符优先级的表达式:
[cling]$ 3<<2|1
(int) 13
[cling]$ 3<<(2|1)
(int) 24
退出:
[cling]$ .q
像 .q
一样,cling 在 C++ 语言之外自身还有一些以点开头的特殊命令,如 .L
可以直接加载另一个 C++ 文件里的内容等等,具体可以参考官网。
cling 的更多玩法请读者自行探索。也许你过几天就需要它,为什么不现在就将他安装了呢?
安装方法
方法 1 手动安装
前提条件:你最好得使用类 Linux 的系统!目前没有针对 Windows 原生编译好的程序。 在 Windows 上用 WSL 也是可以的。
NOTE: 下面的步骤写的比较简略,需要一定的 Linux 实践经验。
到其官网这里下载你对应的操作系统的编译好的文件。
注意:因为 cling 基于 LLVM 和 clang 构建,它会附带一整个 clang 编译器,
导致编译好的文件非常大,做好准备让你的磁盘少掉一两个 G。
它附带的 clang 通常比你平常用的版本老。因此建议你放在别的(如
/opt
)目录下,并只创建一个 cling 的符号链接到/usr/bin/
以免混淆 clang 的版本。
然而,你会发现官方所谓《 N i g h t l y b u i l d 》最近一个版本是 2020 年 11 月编译的了。如果你嫌老……
我用学校机房的“破”电脑花费了一个晚上,针对 Ubuntu 20.04 自己编译了一个 0.9 版本,可以在这里下载。警告:这个压缩包大概有 600 MB!
在 Windows 上原生构建理论上也是可行的,但环境较难弄,我并未尝试,不知是否有冒险家愿意尝试。
方法 2 通过其他渠道安装
通过 Anaconda 或 docker 可以安装。注意,**以下的方法我都没有试过,**并且获得的版本可能较老。
conda config --add channels conda-forge
conda install cling
或
docker pull compilerresearch/cling
docker run -t -i compilerresearch/cling
背景补充和未来展望
cling 是 CERN 的 ROOT 工程 的一个核心一部分。没错 CERN 就是那个搞对撞机的【欧洲核子研究组织】,而 ROOT 则是一个面向高能物理学领域的 data scientist 的数据分析框架。早些年头 python 在科学数据分析领域还不如现在流行,C++ 语言在这方面有大量的应用。近 5 年来,cling 帮助分析了 1 EB 的物理数据,在 1000 多篇科学出版物的背后发挥着重要的作用。1
ROOT 的开发者也许不以为他们搞出了个多么了不起的东西,但 cling 却获得了越来越多的在科研之外的社区成员的喜爱,特别是 LLVM、搞编译器的人们,他们一起帮助完善 cling,修 bug。
尽管已有一些应用,cling 仍然处在版本号以 0. 开头的不稳定阶段。(甚至在若干版本以前,只要输入了会 CE 的代码就会崩溃……大概这种状态)cling 宣称能较快支持新语言标准,因为它大量复用 LLVM 和 clang 的代码。然而实际上稍差一点:今年 LLVM 发布 12 版本,cling 发布 0.9 版,而 cling 的基础 LLVM 是 2019 年的 9 版本。因为仅靠复用代码不能实现完全的解释器的功能,有的地方必须在 LLVM 之上打补丁。可想而知每一次 LLVM 新版发布时都维护一下这个“补丁”是很麻烦的。
随着两方社区增进交流,cling 想将其自己实现的有必要的部分回馈给 LLVM,而 cling 又想要从 LLVM 的更新中获益,依赖版本的跟进不及时成了摆在他们面前的挑战。最近,cling 宣布向 LLVM 的 clang-repl 项目过渡。2今年五月,clang-repl 最少的基本功能完成,进入 LLVM 仓库。(这不意味着 cling 作为一个项目会停止。)cling 和 clang-repl 的未来如何,让我们拭目以待。
注:以上含有我的个人理解,可能不准确。请参考官网和下面的参考资料。