gccrs:Rust 的替代编译器

2024 年 11 月 7 日 · Arthur Cohen 代表 gccrs 项目发布

这是来自 gccrs 项目的客座文章,应 Rust 项目的邀请,旨在澄清与 Rust 项目的关系以及合作机会。

gccrs 是一个正在开发中的 Rust 替代编译器,它是 GCC 项目的一部分。GCC 是一个包含各种编程语言编译器的集合,它们都共享一个通用的编译框架。您可能听说过 gccgogfortrang++,它们都是该项目中的二进制文件,即 GNU 编译器集合gccrs 的目标是将 Rust 编程语言添加到该集合中,并力求与 rustc 具有完全相同的行为。

首先,gccrs 作为一个项目启动的原因是因为它很有趣。编译器是非常有价值的软件,而且组合起来非常有趣。该项目早在 2014 年 Rust 1.0 发布之前就开始了,但由于当时语言的不断变化而很快被搁置。大约在 2019 年左右,编译器的工作再次开始,由 Philip Herron 领导,并由 Open Source SecurityEmbecosm 资助。自那时起,我们一直在稳步朝着支持整个 Rust 语言的目标迈进,我们的团队也在不断壮大,大约有十几位贡献者定期参与该项目。我们已经连续四年参与了 Google 编程之夏 (Google Summer of Code) 项目,并且有多名学生加入了我们的行列。

gccrs 的主要目标是为编译 Rust 提供一个替代选项。GCC 是一个古老的项目,它最早于 1987 年发布。多年来,它积累了大量的贡献,并支持多个目标平台,包括一些 rustc 使用的主要后端 LLVM 不支持的平台。一个实际的例子是自制 Dreamcast 场景,充满激情的工程师们正在为 Dreamcast 游戏机开发游戏。它的处理器架构 SuperH 受 GCC 支持,但不受 LLVM 支持。这意味着 Rust 无法在这些平台上使用,除非通过诸如 gccrsrustc-codegen-gcc 后端等方式来实现 - 两者的主要区别将在后面解释。

GCC 还受益于几十年用不安全语言编写的软件。因此,该项目已经开发了大量的安全功能,作为外部插件,甚至在项目中作为静态分析器。这些分析器和插件在 GCC 的内部表示上执行,这意味着它们与语言无关,因此可以用于 GCC 支持的所有编程语言。同样,许多 GCC 插件用于提高关键项目的安全性,例如最近获得 Rust 编程语言支持的 Linux 内核。这使得 gccrs 成为分析不安全 Rust 代码的有用工具,更普遍地说是分析必须与现有 C 代码交互的 Rust 代码的有用工具。我们还希望 gccrs 成为 rustc 本身的有用工具,通过独特的视角帮助整理 Rust 规范工作 - 即一个工具试图复制另一个工具的功能,通常是通过仔细的实验和源代码阅读来完成,而现有文档并未深入探讨足够的细节。我们还在开发围绕 gccrsrustc 的各种工具,其唯一目的是确保 gccrsrustc 一样正确 - 这可能有助于发现令人惊讶的行为、意外的功能或未明言的假设。

我们要指出的是,我们帮助整理 Rust 规范的目标不是将其变成一个认证替代编译器为“Rust 编译器”的文档 - 虽然我们相信该规范对 gccrs 会有用,但我们的主要目标是通过尽可能多地审查和添加来为其做出贡献。

此外,该项目仍然“年轻”,仍然需要大量的工作。这里有很多地方可以让你留下印记,并且有很多简单的事情可以供对编译器感兴趣的贡献者去做。我们一直在努力为我们所有的团队和 GSoC 学生创造一个安全、有趣和有意义的空间。我们鼓励任何感兴趣的人在我们的 各种沟通平台 上与我们聊天,并为你们提供指导,让你们学习如何为项目和编译器做出贡献。

然而,也许更重要的是,gccrs 有许多不适用之处。该项目有多个明确的非目标,我们对其重视程度与我们的目标相同。

其中最关键的非目标是避免 gccrs 成为替代或扩展的类 Rust 编程语言的网关。我们不希望创建具有不同语义或略有不同的功能的 GNU 特定版本的 Rust。gccrs 不是引入新 Rust 功能的方式,也不会用于规避 RFC 流程 - 如果我们希望看到某些内容引入 Rust,我们将使用该流程。Rust 不是 C,我们不打算通过仅让 gccrs 用户可以使用某些功能来引入标准中的细微差异。我们知道特定于编译器的标准造成的痛苦,并从较旧编程语言的历史中吸取了教训。

我们不希望 gccrs 成为 rustc_codegen_gcc 后端的竞争对手。虽然这两个项目都将有效地实现相同的目标,即使用 GCC 编译器框架编译 Rust 代码,但每个项目将为该语言解锁的内容存在细微差异。例如,rustc_codegen_gcc 可以轻松地从 rustc 所有出色的诊断和有用的错误消息中受益,并使 Rust 能够轻松地在 GCC 特定平台上使用。另一方面,它首先需要 rustc 可用,而 gccrs 完全是单独项目的一部分。这对于某些用户和核心 Linux 开发人员来说很重要,例如,他们认为能够使用单个编译器编译整个内核(C 和 Rust 部分)至关重要。gccrs 还可以通过作为其自己独立的 GCC 前端来提供更多的插件入口点。它还允许在较旧的 GCC 上使用 Rust,在这些 GCC 上 libgccjit 不可用。尽管如此,我们与 rustc_codegen_gcc 的开发人员是非常好的朋友,并且多次互相帮助,特别是在处理 GCC 使用的基于补丁的贡献流程时。

这一切都与一个更全局的目标相关联,我们可以将其概括为以下几点:我们不希望分裂 Rust 生态系统。我们希望 gccrs 帮助该语言覆盖更多人,甚至更多平台。

为了确保这一点,我们已采取多项措施,以确保 Rust 项目的价值观得到尊重和适当的展示。我们最强烈感受到的功能之一是在编译器中添加了一个非常烦人的命令行标志 -frust-incomplete-and-experimental-compiler-do-not-use。如果没有它,您将无法使用 gccrs 编译任何代码,并且编译器将输出以下错误消息:

crab1: 致命错误:gccrs 尚未能够正确编译 Rust 代码。产生的大部分错误将是 gccrs 的错误,而不是您尝试编译的 crate 的错误。因此,请直接向我们报告错误,而不要在所述 crate 的存储库上打开问题。

我们的 github 存储库:https://github.com/rust-gcc/gccrs

我们的 bugzilla 跟踪器:https://gcc.gnu.org/bugzilla/buglist.cgi?bug_status=__open__&component=rust&product=gcc

如果您理解这一点,并且理解生成的二进制文件可能无法按预期运行,则可以通过传递以下标志以实验方式尝试使用 gccrs:

-frust-incomplete-and-experimental-compiler-do-not-use

或者通过定义以下环境变量(任何值都可以):

GCCRS_INCOMPLETE_AND_EXPERIMENTAL_COMPILER_DO_NOT_USE

对于 cargo-gccrs,这意味着传递:

GCCRS_EXTRA_ARGS="-frust-incomplete-and-experimental-compiler-do-not-use"

作为环境变量。

在编译器能够编译正确的 Rust 并且最重要的是拒绝错误的 Rust 之前,我们将把此命令行选项保留在编译器中。希望它可以防止用户因代码无法编译而可能打扰现有的 Rust crate 维护者,因为这很可能是我们没有实现部分语言的错误。我们为 Rust 语言创建替代编译器的目标绝不能对 Rust 社区的任何成员产生负面影响。当然,这个命令行标志并非所有人都喜欢,并且对其存在提出了强烈反对……但我们认为它很好地代表了我们的主要价值观。

同样,gccrs 通过不使用邮件列表作为其主要沟通方式,将自己与 GCC 项目的其他部分区分开来。我们正在构建的编译器将由 Rust 社区使用,并且我们认为我们应该让该社区更容易与我们联系并报告他们遇到的问题。由于 Rustaceans 习惯使用 GitHub,这也是我们过去五年一直在使用的开发平台。同样,我们使用 Zulip 实例 作为我们的主要沟通平台,并鼓励任何想与我们聊天的人加入它。请注意,我们仍然有一个邮件列表,以及一个 IRC 频道([email protected]oftc.net 上的 #gccrust),我们欢迎所有人。

为了进一步确保 gccrs 不会在生态系统中产生摩擦,我们希望在编译器的细节方面格外小心。对我们而言,这意味着尽可能地重用 rustc 组件,在这些组件上共同努力,并与社区中的 Rust 专家进行广泛的交流。gccrs 已经使用了两个 Rust 组件:略旧版本的 polonius,即下一代 Rust 借用检查器,以及编译器的 rustc_parse_format crate。重用这些 crate 的原因有很多,最主要的原因是正确性。借用检查是一个复杂的主题,也是 Rust 编程语言的支柱。rustcgccrs 在借用规则方面存在细微差别,这对用户来说会很烦人且毫无意义。但是,通过努力将 polonius 集成到我们的编译管道中,我们有助于确保我们生成的结果与 rustc 等效。您可以在这里阅读更多关于我们使用的各种组件的信息,并且我们计划重用更多的组件。我们还希望为 polonius 项目本身做出贡献,并在可能的情况下帮助它变得更好。这种组件的交叉使用显然会使我们受益,但我们相信它对 Rust 项目和整个生态系统也会很有用,并且将有助于加强这些实现。

重用 rustc 组件也可以扩展到编译器的其他领域:类型系统的各个组件,例如 trait 求解器,这是一个至关重要且复杂的软件,可以集成到 gccrs 中。简单的东西,例如解析,就像我们为格式化字符串解析器和内联汇编解析器所做的那样,对我们来说也是有意义的。它们将有助于确保我们处理的内部表示与 Rust 标准库期望的表示相对应。

最后,我们认为,为了防止 Rust 生态系统内的破坏,我们可以采取的最重要步骤之一是进一步改善我们与 Rust 社区的关系。我们从 Rust 人员那里获得的帮助非常多,我们认为 gccrs 可以成为广大用户感兴趣的项目。我们很乐意听到您对该项目的期望以及您关于减少生态系统破坏或降低与您已发布的 crate 之间的摩擦的想法。我们在 RustConf 2024 上就 gccrs 进行了愉快的交谈,每个人对该项目的兴趣都令人感动。如果您有任何关于我们如何进一步为 Rust 做出贡献的想法,请与我们联系。