使用DMD自举GDC
摘要
作者描述了如何在FreeBSD上使用DMD编译器和一个小的包装程序自举GNU D编译器(GDC),挑战了GCC关于GDC必须使用GDC构建的说法。
暂无内容
查看缓存全文
缓存时间: 2026/07/15 13:44
# 我使用 DMD 构建了 GDC
来源:https://briancallahan.net/blog/20260713.html
## Brian Robert Callahan 博士 (https://briancallahan.net/blog/)
学者、开发者,致力于更美好的技术社会生活
---
---
##### [\[prev\]](https://briancallahan.net/blog/20260609.html)
##### \[next\]
## 2026-07-13 我使用 DMD 构建了 GDC
在此获取源代码 (https://github.com/ibara/gdc-wrapper)。
FreeBSD (https://www.freebsd.org/) 没有提供 GDC(GNU D 编译器)的软件包。GDC 是 GCC (https://gcc.gnu.org/) 的 D (https://dlang.org/) 语言前端。我经常在 FreeBSD 上使用 GDC 作为研究工具 (https://doi.org/10.2139/ssrn.6869668)。因此,我不得不自己为 FreeBSD 构建 GDC。我之前忘记分享具体做法;本文就是为了弥补这一点。
这个过程非常简单直接。如果你有 DMD (https://wiki.dlang.org/DMD),那么你可以轻松获得 GDC。我编写了一个小型包装程序 (https://github.com/ibara/gdc-wrapper) 来尽可能简化这个过程。
#### GCC 的说法
GCC 在其文档 (https://gcc.gnu.org/install/prerequisites.html) 中指出,GDC 必须用 GDC 构建。具体来说,文档写道:“为了构建 GDC(D 编译器),你需要一个可用的 GDC 编译器(GCC 9.4 或更高版本)以及 D 运行时库‘libphobos’,因为 D 前端是用 D 编写的。”文档接着说明:“GCC 12 之前版本的 GDC 可以使用 ISO C++11 编译器构建,然后可以安装并使用它来引导更新版本的 D 前端。”
其中部分内容确实无可争议:自 GCC 12 (https://gcc.gnu.org/gcc-12/changes.html) 起,GDC 就是用 D 编写的。但另一部分内容似乎未经检验:GDC 有什么特殊之处,以至于它是唯一能构建 GDC 的 D 编译器?所有 D 编译器共享同一个前端,而 D 前端并没有使用任何语言中晦涩难懂的部分。即便它使用了,三个 D 编译器也共享同一个前端,因此理论上任何 D 编译器都应该能够构建 GDC。这正是我想要测试的,即使没有其他理由,仅仅是因为构建一个旧版本的 GCC 来构建新版本的 GCC 会花费极其漫长的时间。而构建 DMD 只需要几秒钟。
#### 现实情况如何
为了构建 GDC,你需要一个 D 编译器以及足够版本的 libphobos,以便仅构建 stage1 的 GDC。stage1 的 GDC 会构建 stage1 的 libphobos。如果我们有一个 D 编译器能刚好做到足够构建一个可用的 stage1 GDC,那么我们就万事大吉了。这是我们需要克服的唯一障碍。
DMD 编译器(参考 D 编译器)完全有能力做到这一点。障碍并不在于 DMD 能否构建 stage1 GDC,而在于这三个 D 编译器前端(DMD、GDC 和 LDC (https://wiki.dlang.org/LDC))使用的标志集各不相同。DMD 和 LDC 彼此接近;GDC 为了匹配 GCC,使用了完全不同的标志风格。如果我们能编写一个小的包装程序来转换这些标志差异,那么就应该能够用 DMD 构建 stage1 GDC。
#### `gdc-wrapper`
这个小程序机械地转换标志,原样添加所有其他参数,然后用转换后的参数列表调用 DMD。我主要采用试错法,直到 DMD 能成功构建 stage1 GDC。我只是让 GDC 构建运行,当某个地方失败时,我就将该标志添加到包装程序中。最难处理的标志是 `-MF` 和 `-MT`,它们用于创建依赖规则文件。我的做法是忽略 `-MT`,并创建 `-MF` 指定的文件,但文件中只包含一个换行符。这有点取巧,但我们并不关心完全精确;我们只关心构建出 stage1 GDC,然后继续。
除此之外,我们忽略警告标志,将 `-o output.o` 转换为 `-ofoutput.o`,将 `-finline` 改为 `-inline`,将 `-fversion=VERSION` 改为 `-version=VERSION`,以及一些其他小的改动确保链接正确。
#### 它确实有效
我从 D 语言官网 (https://dlang.org/download.html) 下载了 FreeBSD x86_64 的 DMD 2.112.0 二进制文件,解压到我的 `HOME` 目录,然后通过 `./configure --dmd=/home/briancallahan/dmd2/freebsd/bin64/dmd && make` 构建了 `gdc-wrapper`。接着,我临时将 `/home/briancallahan/gdc-wrapper` 添加到 `PATH` 末尾(使用 `export PATH=$PATH:$PWD`),就可以毫无问题地构建 GDC。整个过程就是这么简单。在 FreeBSD 15 上,我可以用它构建 GDC 15.2.0 和 GDC 16.1.0。
#### 结论
希望这对某些 FreeBSD、NetBSD、GNU Hurd 或 Illumos 用户有所帮助,或者任何使用没有 GDC 包的 Linux 发行版的用户。
一个明显的限制是,目前 DMD 仅有 x86 和 x86_64 的后端(不过 ARM64 后端正在开发中!)。因此,如果你需要其他 CPU 架构的 GDC,你首先需要利用本方法构建一个原生的 GDC,然后可以按照我们之前的一篇文章 (https://briancallahan.net/blog/20250817.html) 来构建一个交叉编译的 GDC,最终过渡到不同 CPU 架构的原生 GDC。
回到顶部 (https://briancallahan.net/blog/20260713.html#top)
RSS (https://briancallahan.net/blog/feed.xml)
---
相似文章
在dsymutil中采用并行DWARF链接器
苹果的dsymutil工具用于将DWARF调试信息链接到自包含的捆绑包中,现在正在采用并行DWARF链接器来解决类型去重中的单线程瓶颈,尽管由于输出并非二进制完全相同而在验证方面面临挑战。
构建 GCC 1.27(2019)
一篇博客文章描述了在现代 Ubuntu 系统上构建 GCC 1.27(一款 1988 年的编译器)的过程,详细说明了必要的补丁和步骤。
在Bazel中一个从357字节开始的C++工具链
一篇博客文章,描述了一种新的Bazel工具链,它从357字节的stage0引导种子开始编译C++代码,在Bazel中实现了完全源码引导且封闭的C++工具链。作者演示了它从Bazel Central Registry构建未打补丁的Abseil和GoogleTest。
构建Clang后端并将Doom移植到我的自定义字节码虚拟机
作者复活了他的自定义字节码虚拟机(UVM),并借助AI解析文本LLVM IR构建了一个Clang后端,成功将Doom移植到该虚拟机上。
自举 Rust 被认为有害
对 Rust 编译器自举过程的批判性分析,指出与 OCaml 等其他语言相比,其体积过大和依赖臃肿的问题,并主张采用更轻量的方法。