首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >Rust 编写首个真正的 PHP 到原生语言的编译器(无需虚拟机,也无需运行时环境)

Rust 编写首个真正的 PHP 到原生语言的编译器(无需虚拟机,也无需运行时环境)

作者头像
Tinywan
发布2026-07-01 17:56:36
发布2026-07-01 17:56:36
740
举报
文章被收录于专栏:开源技术小栈开源技术小栈

一款将 PHP 代码编译为原生代码的编译器。它仅处理 PHP 的子集代码,并直接将其编译为原生汇编代码,从而生成可在当前支持的目标平台上运行的独立二进制文件:macOS ARM64、Linux ARM64 以及 Linux x86_64。该编译器不需要解释器、虚拟机,也无需 Zend Engine 或操作码回退机制。

安装

支持平台:macOS、Linux

安装要求

  • 如果从源码编译:需要 Rust 工具链(cargo
  • 目标平台原生汇编器和链接器(asld

macOS:安装 Xcode 命令行工具

代码语言:javascript
复制
xcode-select --install

这会提供 elephc 需要的汇编器 as 和链接器 ld

Linux:安装发行版的原生工具链,使 asld 以及 libc 开发文件可用。

通过 Homebrew(macOS)

代码语言:javascript
复制
brew install illegalstudio/tap/elephc

验证安装是否成功:

代码语言:javascript
复制
echo '<?php echo "ok\n";' > check.php
elephc check.php && ./check

输出 ok 即表示成功,确认 elephc 可以生成并运行原生二进制文件。

从源码编译

如果你喜欢从源码构建,也需要 Rust 工具链:

代码语言:javascript
复制
git clone https://github.com/illegalstudio/elephc.git
cd elephc
cargo build --release

编译后的二进制文件位于 ./target/release/elephc。你可以将其复制到 PATH 目录:

代码语言:javascript
复制
cp target/release/elephc /usr/local/bin/

从 GitHub 发布版下载

预构建的二进制文件可以在 GitHub Release 页面 找到。 下载对应平台的 artifact,添加可执行权限并移动到 PATH

代码语言:javascript
复制
chmod +x elephc
mv elephc /usr/local/bin/

你的第一个程序

Hello, World

创建文件 hello.php

代码语言:javascript
复制
<?php
echo "Hello, World!\n";

编译:

代码语言:javascript
复制
elephc hello.php

会生成同目录下的原生二进制文件 hello。运行它:

代码语言:javascript
复制
./hello

输出:

代码语言:javascript
复制
Hello, World!

这就是全部:一个完全独立的原生二进制文件,无需 PHP 解释器。

稍大一点的例子

创建 greet.php

代码语言:javascript
复制
<?php
if ($argc < 2) {
    echo "Usage: ./greet <name>\n";
    exit(1);
}

$name = $argv[1];
echo "Hello, " . strtoupper($name) . "!\n";

编译并运行:

代码语言:javascript
复制
elephc greet.php
./greet elephc

输出:

代码语言:javascript
复制
Hello, ELEPHC!

程序通过 argc 和 argv 读取命令行参数(与 PHP 完全一致)。

FizzBuzz

经典示例,展示变量、循环和条件判断:

代码语言:javascript
复制
<?php
for ($i = 1; $i <= 100; $i++) {
    if ($i % 15 == 0) {
        echo "FizzBuzz\n";
    } elseif ($i % 3 == 0) {
        echo "Fizz\n";
    } elseif ($i % 5 == 0) {
        echo "Buzz\n";
    } else {
        echo $i . "\n";
    }
}

编译运行:

代码语言:javascript
复制
elephc fizzbuzz.php
./fizzbuzz

编译器底层原理

运行 elephc hello.php 时,编译器会执行以下步骤:

  1. 词法分析:将源代码转换为词法标记(tokens)
  2. 语法分析:将标记转换为抽象语法树(AST)
  3. 降低:文件本地魔术常量及应用 --define 的 ifdef 分支
  4. 构建:从 Composer 元数据和支持的 spl_autoload_register() 规则构建编译时自动加载注册表
  5. 解析:解析 include / require 文件,预扫描静态可解析的 include 声明,折叠编译时包含路径,并降低 *_once 运行时保护
  6. 解析:解析命名空间、导入和完全限定名称
  7. 运行:为引用的类符号静态插入自动加载
  8. 折叠:折叠已知静态的常量表达式
  9. 类型检查:类型检查程序并收集非致命警告
  10. 优化:通过传播、剪枝、规范化、死代码消除优化已检查的 AST 控制流
  11. 降低:将已检查 AST 降低为验证后的 EIR
  12. 生成:从 EIR 生成目标汇编代码
  13. 准备:或重用缓存的运行时对象
  14. 汇编和链接:将 .s / .o 文件组装成原生可执行文件

中间的 .s.o 文件会自动清理。你最终会得到一个单个可执行文件

实用检查标志

如果你想更深入查看编译过程,以下是良好起点:

  • 打印每个阶段的编译时间(到标准错误):
代码语言:javascript
复制
elephc --timings hello.php
  • 只输出汇编代码,并附带侧边源映射文件:
代码语言:javascript
复制
elephc --emit-asm --source-map hello.php

--timings 会报告词法分析、解析、早期优化、类型检查、常量传播、后检查剪枝、控制流规范化、死代码消除、运行时缓存准备、代码生成、汇编和链接等阶段。

--source-map 会将 hello.map JSON 文件写入 hello.s 旁边。该文件记录哪些汇编代码行来源于哪个 PHP 源代码行和列。

如果你想对比 elephc 与 PHP 解释器和等效的 C 固定装置,请查看 基准测试套件

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2026-06-16,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 开源技术小栈 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 安装
    • 安装要求
    • 通过 Homebrew(macOS)
    • 从源码编译
    • 从 GitHub 发布版下载
  • 你的第一个程序
    • Hello, World
    • 稍大一点的例子
    • FizzBuzz
  • 编译器底层原理
  • 实用检查标志
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档