VMLTool 主工具 · VMLAssembler 汇编器 · VMLToHex 烧录工具 · VMLPacker 打包器 · GenLib 静态库 · GenDyn 动态库 · GenDev 设备代码生成
从源码到可执行文件的完整工具链流程
GCC 风格 CLI,自动根据扩展名选择编译器
| 命令 | 说明 |
|---|---|
vmltool input.c -o output.vml | 编译 C 为 VML |
vmltool input.c -o output.hex -t avr -f hex | C → AVR HEX 一键烧录 |
vmltool -S input.c -o output.s -t arm-cm | C → ARM 汇编(仅生成汇编) |
vmltool -E input.c | 仅预处理(展开宏和 include) |
vmltool -c input.c -o out.vml -D DEBUG -O2 -Wall | GCC 兼容编译选项 |
vmltool -v | 显示版本信息 |
vmltool -r program.vml | 运行 VML 程序 |
# 1. 编译 C 源码为 VML
$ vmltool hello.c -o hello.vml
已编译: hello.c → hello.vml (120 条指令)
# 2. 直接运行 VML 程序
$ vmltool -r hello.vml
Hello from C!
# 3. 一键编译+运行
$ vmltool hello.py -r
Hello from Python!
# 4. 交叉编译到 AVR 并生成 HEX
$ vmltool blink.c -o blink.hex -t avr -f hex
将 VML 汇编文本编译为 VMB 二进制格式
; 输入: hello.vml
.entry main
LABEL main
MOVE R0, #72 ; 'H'
SYSCALL #0 ; putchar
HALT
; 输出: hello.vmb (二进制)
; 头 24 字节 + 指令序列
; MOVE = OpCode 1, R0=0, #72=72
; SYSCALL = OpCode 42, #0=0
VMLAssembler/OpCode.cs 是 VML 操作码的唯一权威定义。所有 92 个操作码的枚举值和语义在此文件中定义。C 运行时头文件必须与之保持同步。
从源码到 HEX 固件的一站式工具,16 个目标架构,6 种输出格式
| 命令 | 说明 |
|---|---|
vml2hex main.c -arch avr | C → VML → AVR → HEX(全自动) |
vml2hex main.bas -arch 8051 | BASIC → VML → 8051 → HEX |
vml2hex main.py -arch arm-cm | Python → VML → STM32 → HEX |
vml2hex program.vml -arch avr | VML → AVR → HEX |
vml2hex blink.c -arch arm-cm --chip stm32f429 -f hex | STM32 指定芯片型号烧录 |
| 参数 | 说明 |
|---|---|
-O0 | 不优化 — 调试用,保留所有指令 |
-O1 | 死代码消除 + 常量折叠 — 默认 |
-O2 | O1 + 复制传播 + 循环优化 — 生产发布 |
| 参数 | 格式 | 用途 |
|---|---|---|
-f hex | Intel HEX | 烧录(默认) |
-f bin | Binary | 裸二进制镜像 |
-f s19 | Motorola S19 | Freescale 烧录器 |
-f elf | ELF | GDB 调试 / objdump 反汇编 |
-f exe | DOS EXE | DOS 可执行文件 |
-f dump | Text Dump | 人类可读文本 |
# 1. 编译 C 源码 → ARM HEX
$ vml2hex blink.c -arch arm-cm --chip stm32f429 -f hex -o blink.hex
# 2. ST-LINK 烧录
$ STM32_Programmer_CLI -c port=SWD -w blink.hex -v -rst
# 3. 或者输出 ELF 用于 GDB 调试
$ vml2hex blink.c -arch arm-cm -f elf -o blink.elf
$ arm-none-eabi-gdb blink.elf
将 VML/VMB 程序打包为独立可执行文件,支持跨平台分发
| 命令 | 说明 |
|---|---|
vmlpacker input.vml | 汇编并运行 |
vmlpacker input.vml -o out.vmb | 打包为 VMB 二进制 |
vmlpacker input.vml --vmb | 打包为 VMB |
vmlpacker input.vml --exe | 生成当前平台独立 EXE |
vmlpacker input.vml --exe linux-x64 | 交叉打包为 Linux EXE |
vmlpacker input.vml --run | 汇编并立即运行 |
VMLFast/VMLPackerC/ 提供 C 语言版本的打包工具:vmlpacker (VML→VMB) 和 vmlexe (VMB→EXE),静态编译后体积更小。
从 C 源码自动编译 VML 共享库,为 22 种语言生成模块包装和绑定代码
| 命令 | 说明 |
|---|---|
genlib -A | 一键全流程:编译 + 模块包装 + 聚合文件 + 源文件绑定 |
genlib -b | 增量编译 Lib/shared/src/*.c → .vml |
genlib -m -l python | 为 Python 生成模块包装 .vml |
genlib -a -l go | 生成 Go 语言的 builtin/stdlib/vmllib 聚合文件 |
genlib -g -l rust -p mylib | 生成 Rust 绑定 shared.rs,包名 mylib |
genlib -s | 扫描所有导出函数 |
| 类型 | 模块 | 进入聚合文件 | 使用方式 |
|---|---|---|---|
| core | math, string, time, file, console, system | 是 | .include "math.vml" 或自动链接 |
| custom | 用户自写模块 | 否 | 仅 .include "xxx.vml" |
Lib/modules.json 和 Lib/naming.json 缺失时自动生成,删了也能重建。
扫描 .dylib/.so/.dll 导出符号,生成 VML FFI 包装器和 22 种语言调用绑定
| 命令 | 说明 |
|---|---|
gendyn -A -n demodll | 一键全流程:扫描 + 构建 + 包装 + 绑定 |
gendyn -s | 扫描动态库导出符号 → dynlibs.json |
gendyn -b -n mylib | 编译 C 胶水代码为共享库 |
gendyn -w -n mylib | 生成 VML FFI 包装器 → Lib/dynamic/mylib.vml |
gendyn -g -l python -n mylib | 为 Python 生成绑定 → Lib/python/ext/libmylib.py |
gendyn -A -n mylib -H mylib.h | 全流程 + 指定头文件获取类型信息 |
| 文件类型 | 静态库 (GenLib) | 动态库 (GenDyn) |
|---|---|---|
| VML 文件 | Lib/{lang}/{module}.vml | Lib/dynamic/{name}.vml |
| 语言绑定 | Lib/{lang}/shared.{ext} | Lib/{lang}/ext/lib{name}.{ext} |
| JSON 配置 | Lib/modules.json | Lib/dynamic/dynlibs.json |
从 XML 设备描述文件自动生成 22 种语言设备驱动代码
| 命令 | 说明 |
|---|---|
gendev -i ATmega328P.xml -o atmega328p.h -l c | 生成 C 头文件 |
gendev -i ATmega328P.xml -d Generated -a | 生成所有 22 种语言 |
gendev ATmega328P.xml -l basic | 生成 BASIC 代码 |
gendev ATmega328P.xml -l python | 生成 Python 代码 |
<!-- ATmega328P.xml 示例结构 -->
<Device>
<Metadata>
<Name>ATmega328P</Name>
<Architecture>AVR</Architecture>
<RAM>2048</RAM>
<ROM>32768</ROM>
</Metadata>
<Registers>
<Register name="PORTB" address="0x25" />
<Register name="DDRB" address="0x24" />
<Register name="PINB" address="0x23" />
</Registers>
<Peripherals>
<Timer name="TIMER0" bits="8" />
<UART name="USART0" />
</Peripherals>
</Device>
// atmega328p.h — 自动生成
#define PORTB (*(volatile unsigned char*)0x25)
#define DDRB (*(volatile unsigned char*)0x24)
#define PINB (*(volatile unsigned char*)0x23)
// 外设初始化函数
void timer0_init(unsigned char prescaler);
void usart0_init(unsigned int baud);
# atmega328p.py — 自动生成
PORTB = 0x25
DDRB = 0x24
PINB = 0x23
def timer0_init(prescaler):
pass # VML MMIO 操作
def usart0_init(baud):
pass
' atmega328p.bas — 自动生成
CONST PORTB = &H25
CONST DDRB = &H24
CONST PINB = &H23
SUB timer0_init (prescaler)
' VML MMIO 操作
END SUB