为了构建 Lumen 或对其进行更改,您需要安装以下内容:安装 rustup 后,您将需要安装 Rust 的夜间版本(目前我们的 CI 是针对 2021-01-29 nightly 构建的)。由于我们使用了大量的夜间功能,以及我们使用的 WebAssembly 目标的一些依赖性,我们需要每晚。 # 使用最新的 nightlyrustup default nightly# 或者,如果出现问题,请安装 2021-01-29 nightly 以匹配我们的 CIrustup default nightly-2021-01-29 为了在项目中运行各种构建任务,您将需要 Cargo 的 cargo-make 插件。您可以通过以下方式安装它:您可能还想安装以下工具以支持编辑器(所有拉取请求都需要 rustfmt!):Lumen 的代码生成后端使用 LLVM(经过我们的修改)。需要构建编译器。通常,您需要自己构建它,我们在下面有说明;但我们也提供了具有所需一切的预构建发行版。下面的说明将 $XDG_DATA_HOME 引用为环境变量,一般建议导出 XDG 变量,但如果没有,只需将下面的 $XDG_DATA_HOME 的用法替换为 $HOME/.local/share,这是此 XDG 变量的通常默认值.
我们尚未为其他操作系统提供预构建包,您需要按照以下说明从源代码构建。 LLVM 需要 CMake、C/C++ 编译器和 Python。强烈建议您同时安装 Ninja 和 CCache 以显着加快构建速度,尤其是在后续重建时。您可以在系统包管理器中找到所有这些依赖项,包括 macOS 上的 Homebrew。如果未设置 $XDG_DATA_HOME,这会将 LLVM 安装到 $XDG_DATA_HOME/llvm/lumen 或 $HOME/.local/share/llvm/lumen。它假定安装了 Ninja 和 CCache,但是您可以通过从 cmake 的调用中删除 -G Ninja 来自定义 Makefile 中的 llvm 目标以使用 make,同样您也可以通过删除该选项来更改设置以使用 CCache。注意:第一次构建 LLVM 需要很长时间,所以喝杯咖啡,如果你有它们,就抽它们,等等。这将为项目根目录中的 bin 下的主机创建编译器可执行文件和相关联的工具链。您可以通过符号链接 bin/lumen 调用 lumen,例如:这将生成与当前工作目录中的源文件同名的可执行文件,扩展名为 .out 或 .exe,具体取决于您的平台。注意:编译器/运行时仍处于试验阶段,因此无法保证稳定性,如果链接器警告丢失符号,您可能需要提供额外的编译器标志,例如 -lpthread。
Lumen 的前端和诊断库已移入 EIRProject,其中包括 Erlangparser 和高级中间表示 EIR(ErlangIntermediate Representation 的缩写)。 Lumen 依赖于这些组件的 EIR 库。 liblumen_session,包含编译器的单个实例化或“会话”的状态和配置。您可以在此处找到大量选项处理、输入/输出生成和相关项目。 liblumen_compiler,包含编译器驱动程序和增量编译引擎(建立在 salsa 之上)的核心,以及用于从解析源生成工件的所有更高级别的查询。 liblumen_codegen,包含代码生成后端,它分为两个主要阶段:第一个阶段处理从 EIR 到我们自己的 MLIR 方言(或在某些情况下,直接 LLVM IR)的转换。此转换主要旨在保留 EIR 中的抽象级别,同时准备转换为 LLVM IR。第二阶段是将我们的 MLIR 方言转换为 LLVM,这是大部分代码生成工作发生的地方。 liblumen_term,包含我们术语编码方案的基本部分,并与运行时库共享。编译器需要这样做,以便在编译期间处理编码常量项。 liblumen_core,包含用于与系统交互、执行分配以及在 Lumen 中使用的各种常见类型的基本 API。 liblumen_crt,作为可执行文件的核心运行时入口点,处理引导运行时系统。这链接到所有编译器生成的可执行文件
lumen_rt_minimal (wip) 一个建立在 lumen_rt_core 之上的实验性运行时库,专为 x86_64 平台设计。当前用作编译器生成的可执行文件的运行时。 lumen_rt_full,所有目标的原始运行时库。这正在慢慢地分解成更小的部分,或者合并到 lumen_rt_core 中,或者合并到更多特定于目标的运行时箱。当前由解释器使用,并包含迄今为止实现的所有 BIF 函数。在进行任何重大更改之前,请打开一个标记为“RFC”的问题,其中包含您需要解决的问题、您提出的解决方案以及您在实施方面的任何悬而未决的问题。核心团队(和您)将使用该问题进行讨论更改并为提案亮绿灯,或请求更改。在某些情况下,提案可能会请求与项目目标不相容的更改,或者强加太高的维护或复杂性负担,并且会被拒绝。首先进行 RFC 讨论的重要性在于,它可以防止某人做一堆最终不会被上游处理的工作,并允许核心团队或社区提供反馈,从而使工作最终变得更简单或更好。对于较小的更改/错误修复,如果您是该项目的新手并希望获得一些有关修复工作的指导,请随时打开问题。否则,直接用你的修复打开 PR 是可以接受的,然后让审查在那里进行。始终可以自由地为错误打开问题,甚至是感知到的问题或问题,因为它们可以成为对其他人有用的资源;但请务必使用搜索功能以避免重复!如果您打算参与讨论或为项目做出贡献,请注意该项目不会容忍对社区其他成员的任何形式的滥用;如果您觉得有人辱骂或不当,请直接联系其中一名核心团队成员(或我们所有人)。我们希望营造一种环境,让新人和有经验的人都感到受欢迎,可以回答他们的问题,并希望共同努力使这个项目变得更好! Lumen 不仅是一个编译器,也是一个运行时。它由两部分组成:
Lumen 开发的主要动力是能够编译可以针对 WebAssembly 的 Elixir 应用程序,从而能够将 Elixir 用作前端开发的语言。通过在 x86 等平台上生成自包含的可执行文件,也可以使用 Lumen 来针对其他平台。它有一些额外的限制以允许进行更强大的优化,特别是不支持热代码重新加载 Lumen 提供的运行时库是用 Rust 编写的,虽然非常相似,但在大多数透明的方式上有所不同。目标之一是为学习如何实现运行时提供更好的基础,并利用 Rust 更强大的静态分析来及早发现错误。通过 Lumen 编译 BEAM 应用程序的结果是一个静态可执行文件。这与今天在 BEAM 上的部署方式(即通过 OTP 版本)有很大不同。虽然我们牺牲了执行热升级/降级的能力,但我们在跨平台兼容性和易用性方面取得了巨大的进步。只需将可执行文件放到兼容平台上,然后运行它,需要的 notools 或构建期间的特殊注意事项。这与今天构建 Rustor Go 应用程序的工作方式相同。 Lumen 是 Erlang/OTP 的另一种实现,因此它没有经过实战测试,也不一定像 BEAM 本身那样具有性能。在我们有机会运行一些基准测试之前,很难知道两者在性能方面的实际差异。 Lumen 目前不打算取代 BEAM。至少,该项目声明的非目标意味着至少有一定比例的项目会缺少某些必需的功能。但是,它旨在替代通过其功能集提供更好服务的应用程序。编译器前端接受 Erlang 源文件。这被解析为抽象语法树,降级为 EIR(Erlang 中间表示),最后降级为执行代码生成的 LLVM IR。
在降级到 LLVM IR 期间,延续表示被剥离,并生成用于实现各种构造的特定于平台的方法。函数applicationfacilities 用于执行apply。目前,C++ 风格的零成本异常模型用于实现异常。有一些 WebAssembly 正在进行的未来提案可能允许我们对异常使用延续,但尚未稳定或在浏览器中实现。编译器生成对象文件,并处理将对象链接到可执行文件中。它还可以转储所有中间工件,例如各种形式的 AST、EIR、MLIR、LLVM IR、LLVM 位码和普通汇编。运行时设计与 OTP 基本相同,但我们没有运行解释器,而是提前编译了代码:进程在与其产生的进程相同的调度程序上产生,但调度程序能够窃取它们远离负载平衡 初始版本将非常简陋,但这样我们就可以专注于在我们返回添加更多功能之前获得坚如磐石的运行时行为。 NIF 将能够使用 C FFI 以任何语言定义,并且需要编译为目标文件,然后通过链接器标志传递给编译器。然后编译器将确保 NIF 链接到可执行文件中。 FFI 的设计仍然悬而未决——我们可能会有一个兼容层来模仿现有的 erl_nif.h 接口,但由于运行时不同,可能有机会为系统的各个部分提供更直接的挂钩。