编译与运行
最快的路子:命令行
vml run examples/c/app/tetris.c # 源码 → 直接跑
vml run ~/main.vml # 文本汇编 → 跑
vml run ~/main.vmb # 字节码 → 跑(最快)
vml run 自动识别扩展名,不用你操心走哪条路。
在文件页点点点
文件 页 → 点文件名 → 菜单里选:
- VML 编译 → 生成下一级产物(
.c→.vml,.vml→.vmb) - VML 运行 → 直接跑
产物会出现在同一个目录下,同名。同名文件已存在时会问「覆盖 / 重命名 / 取消」。
手机上编译要多久
- C 语言最慢:一份带标准库的程序,前端编译 + 链接要一两分钟(手机上真的是一分钟量级)
- Python / Lua / BASIC 这类脚本语言快得多(几秒)
- **
.vmb装载几乎瞬时** —— 所以同一个程序反复跑,先编成.vmb再跑最省时间
编译期间不要以为卡死了:输入框那格会显示
⋯,跑完提示符~>会回来。
编译卡住会不会出不来
不会。前端编译是同步的、没有任何取消入口,所以宿主加了一道看门狗: 180 秒还没编完就把控制权交还给你(那个编译线程本身没法中止,只是不让界面卡着)。
为什么 .vml 还能单独存在
- 能读:它是文本,你能直接看到编译器生成的指令
- 能改:手写汇编也是合法的(
vml test跑的就是一段内置汇编) - 能当中间产物:
.c编一次成.vml,之后反复汇编成.vmb就不用再走前端了
编译参数(设置 → 编译)
设置 → 编译 里能调几个编译器行为参数,改完下一次编译生效。
| 项 | 默认 | 说明 |
|---|---|---|
| 优化级别 | 关闭 | 四档:关闭 / 初步 / 中度 / 极致(见下) |
| 编译警告 | 不报 | 打开后编译期的警告会显示出来(基本 = -Wall,更多 = -Wextra) |
| 把警告当错误 | 关 | 有警告就当成编译失败(-Werror) |
| 调试输出 | 关 | 打开前端里的诊断分支,以及编译结束时的警告计数 |
| 浮点(float/double) | 硬件 | 改成「关闭」= 遇到浮点代码直接编译报错 |
| 64 位整数(long/int64) | 硬件 | 同上 |
优化四档
| 档 | 做什么 | 实测(46 字节的 hello.c) |
|---|---|---|
| 关闭 | 一条指令都不删 | 69637 条指令 / 2.0 MB |
| 初步 | 清掉跳转之后用不到的填充代码 | 69637 条 / 2.0 MB(基本不变) |
| 中度 | 加上死代码消除:删掉没被调用的库函数 | 28 条 / 3.1 KB |
| 极致 | 再删冗余跳转、清数据段、去掉 .linked 声明 | 27 条 / 670 字节 |
这才是"打开优化真的变小":一个 hello world 从 2.0 MB 降到 670 字节,因为它本来就把整个标准库链了进来,而其中 99% 是被调用的函数一个都没有。
游戏上没这么夸张(它们本来就用得多):俄罗斯方块 74754 → 6282 条、五子棋 72921 → 3544 条、大猩猩(BASIC) 103437 → 29863 条。
优化不会改变程序行为 —— 27 门语言的示例在四档下的输出逐字节相同(有判据盯着)。它的规矩是"只删确定用不到的东西":遇到间接跳转、取函数地址、中断向量表这些静态看不全的情形,宁可留着不删。
未使用的东西会被丢掉:没人引用的全局变量、常量、字符串、整片库数据段(正弦表、调色板那些)都不会进产物。这不是某一档的专属 —— 数据段清理一直生效,中度以上因为删了库函数,连带清掉的更多。
「关闭」是报错,不是降级 —— 它用来确认"这个程序到底用没用浮点/64 位",而不是让程序悄悄变慢。软浮点(soft)本平台没有对应的库,所以不提供这个档。
这些参数不影响默认行为:不动它们(优化=关闭)时,编出来的东西与从前逐字节相同。