普贤教程 › 进阶教程
工具链
工具链就是 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/hellotext
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 或一次健康检查)。四步都过再发布。