px普贤教程PuXian
普贤教程 › 进阶教程

工具链

工具链就是 px 一个命令加若干子功能:run 跑、build 编、lint 查、fmt 整、test 测、doc 出文档、bench 压性能。

命令一览

命令作用常用参数
px run x.px解释执行--fast 编译并缓存后执行
px build x.px编译成二进制--no-quic 裁剪、--target 交叉、--min 最小化
px lint x.px静态检查语法与常见错误
px fmt -w x.px格式化-w 写回文件
px test跑测试—
px bench基准测试—
px doc x.px --output x.md生成文档—
px lsp启动语言服务编辑器接 LSP

run 与 run --fast

sh
px run app.px          # 每次解释,改完立刻见效
px run --fast app.px   # 首次编译并缓存,之后约 30 ms 起
--fast 解析 import,但严格0.2.379 起 px run --fast 与解释轨的 import 能力一致(本地文件 / std.* / .px_modules/ 裸名),输出也逐字节一致;区别在出错行为:--fast 编译失败就停(E3005 等),不回落解释轨。所以它是装包后的最佳冒烟工具。
首次运行会在 stderr 打一行「首次运行:编译并缓存」——那行不进 stdout,不影响管道处理。

build:产物在哪

sh
px build hello.px
# 产物:<源码所在目录>/build/hello
file hello/build/hello
text
ELF 64-bit LSB executable, x86-64, statically linked

产物是静态链接的,拷到任何同架构 Linux 上都能跑,不需要装 PuXian、不需要 glibc 版本匹配。

档位适合体积量级
默认(按引用自动裁剪)绝大多数场景3 MB 左右
--min极简工具、容器镜像(会裁掉内建模块,见下)2.7 MB 左右
--full动态调用多、不想管裁剪9 MB 左右
--no-quic不需要 HTTP/3少约 1 MB
--min 会裁掉内建:编译期通过,运行期才炸它聚合裁剪 sqlite / ws / zip / xml / aes / rsa / ed25519 / route / zlib / h2,另加 --no-quic。用到这些能力的程序加 --min 依然编译成功,运行时抛 R1001 未定义变量: 'sqlite_open'——看着像拼写错误,其实是模块被裁掉了。服务器类程序,以及任何用到 sqlite / WebSocket / HTTP 路由 / 压缩 / 加密的程序,不要加 --min。
实测:只用 sqlite_open 的程序,默认档 4,152,928 字节;--min 3,107,216 字节,跑起来直接 R1001。
选项必须写在文件名前面px build --min app.px 有效;px build app.px --min 的 --min 被静默忽略,产物与不加完全相同(实测同为 4,152,928 字节)。不报错、不提示,所以别靠字节数反推,按 px build --help 的顺序写。

fmt 与 lint

sh
px fmt -w app.px      # 按官方风格整理,写回
px lint app.px        # 只查不改

提交前跑一次 px fmt -w,团队里就不会有"缩进有人用 2 空格有人用 4 空格"的 diff 噪音。

写测试

最省事的测试是"断言脚本":一个普通 .px 文件,跑通输出全 PASS,失败直接非零退出。

px
# t_lib.px
var fails = 0

def check(name, got, want):
    if str(got) != str(want):
        print("FAIL " + name + ":期望 " + str(want) + ",实际 " + str(got))
        fails += 1
    else:
        print("ok   " + name)

def clamp(x, lo, hi):
    if x < lo:
        return lo
    if x > hi:
        return hi
    return x

def main():
    check("clamp 低", clamp(-5, 0, 10), 0)
    check("clamp 中", clamp(5, 0, 10), 5)
    check("clamp 高", clamp(50, 0, 10), 10)
    if fails > 0:
        print("共 " + str(fails) + " 项失败")
    else:
        print("全部通过")
text
ok   clamp 低
ok   clamp 中
ok   clamp 高
全部通过
断言脚本比框架实在公共库改动后跑一遍,一分钟知道有没有改坏。要更正式的能力,用生态包 testkit / quickcheck。

文件即路由

用 routegen 按文件名生成路由表(Ma 就是这样把 URL 映射到 .px 文件的):

text
get_healthz.px   → GET  /healthz
post_users.px    → POST /users
users/#id.px     → GET  /users/:id
index.px         → GET  /

规则由 std.webroute 解析:首段是方法名则作为 HTTP 方法,_ 当路径分隔,#name 变路径参数。这样目录结构本身就是路由表,不用维护一份额外的映射。

交叉编译

sh
px build --target aarch64 hello.px
px build --target x86_64-windows hello.px

需要对应的交叉工具链(如 aarch64-linux-musl-gcc)与目标架构的静态库;发布包已带 x86_64 / aarch64 / armv7 / riscv64 的库。

日常命令组合

sh
px lint app.px && px fmt -w app.px && px run app.px
px build app.px && ./build/app --selftest
CI 里跑什么① px lint ② 断言脚本 ③ px build(确认能编出来)④ 产物冒烟(--version 或一次健康检查)。四步都过再发布。