8.4 KiB
8.4 KiB
12 - 项目配置与构建
Viper 项目使用 project.vpj 配置文件管理编译和链接参数(Python 单文件模式仍接受 project.json)。
project.vpj 结构
{
"name": "Kernel",
"version": "1.0.0",
"source_dir": "./Kernel",
"build_dir": "./.tpv_build",
"compiler": {
"cmd": "llc",
"flags": ["-filetype=obj", "-mtriple=x86_64-none-elf", "-relocation-model=static", "-O2"]
},
"linker": {
"cmd": "ld.lld.exe",
"flags": [
"-m", "elf_x86_64",
"-T", "linker.ld",
"--oformat", "elf64-x86-64",
"--strip-all"
],
"output": "kernel.bin"
},
"includes": ["../../includes"],
"target": {
"triple": "x86_64-none-elf",
"datalayout": "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
},
"options": {
"slice_level": 3,
"sha1_slice_level": 1,
"target": "llvm",
"strict_mode": true
}
}
配置项说明
基本信息字段
| 字段 | 类型 | 说明 |
|---|---|---|
name |
string | 项目名称 |
version |
string | 项目版本 |
source_dir |
string | 源代码目录(相对于 project.vpj 所在目录) |
build_dir |
string | 构建目录(默认 ./.tpv_build);temp/output 均由它派生 |
编译器配置
| 字段 | 类型 | 说明 |
|---|---|---|
compiler.cmd |
string | 编译器命令(通常为 llc) |
compiler.flags |
string[] | 编译器标志 |
常用 llc 标志:
-filetype=obj:输出目标文件-mtriple=x86_64-none-elf:目标三元组-relocation-model=static:静态重定位-O2:优化级别
链接器配置
| 字段 | 类型 | 说明 |
|---|---|---|
linker.cmd |
string | 链接器命令(通常为 ld.lld.exe;TransPyV 宿主工程为 clang++) |
linker.flags |
string[] | 链接器标志 |
linker.static_libs |
string[] | 静态库/目标文件列表(.a/.obj) |
linker.dynamic_libs |
string[] | 动态库列表(.dll/.so) |
linker.output |
string | 输出文件名 |
支持 DSO(动态共享对象)构建:开启后产物为 *_dso.ll。
常用 ld.lld 标志:
-m elf_x86_64:ELF x86_64 格式-T linker.ld:链接脚本--oformat elf64-x86-64:输出 ELF 格式--oformat binary:输出原始二进制(用于内核)--strip-all:去除所有符号信息
目标平台配置
| 字段 | 类型 | 说明 |
|---|---|---|
target.triple |
string | LLVM 目标三元组 |
target.datalayout |
string | LLVM 数据布局字符串 |
注意:无统一默认 triple——由各工程 project.vpj 自行指定(TransPyV 自身为 x86_64-pc-windows-gnu;ViperOS 内核为 x86_64-none-elf)。target.datalayout 同样随工程配置,内核工程常用:
e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128
包含路径
| 字段 | 类型 | 说明 |
|---|---|---|
includes |
string[] | 模块搜索路径列表 |
编译选项
| 字段 | 类型 | 说明 |
|---|---|---|
options.slice_level |
int | 切片优化级别(0-3) |
options.sha1_slice_level |
int | SHA1 切片存储级别(默认 1;≥1 时产物按 {temp}/{sha1[0:2]}/ 子目录存放) |
options.target |
string | 编译目标(目前仅支持 llvm) |
options.strict_mode |
bool | 严格模式 |
切片优化级别
| 级别 | 名称 | 说明 |
|---|---|---|
0 |
no_optimize |
无优化 |
1 |
conservative |
保守优化 |
2 |
moderate |
适度优化 |
3 |
aggressive |
激进优化(默认) |
s |
size |
体积优化 |
项目结构示例
内核项目
VKernel/
├── project.vpj # 项目配置
├── linker.ld # 链接脚本
├── Kernel/ # 源代码目录
│ ├── main.vp # 内核入口
│ ├── bootinfo.vp
│ ├── intr/
│ │ ├── gdt.vp
│ │ ├── idt.vp
│ │ └── syscall.vp
│ ├── drivers/
│ │ ├── serial/
│ │ ├── video/
│ │ ├── storage/
│ │ └── ...
│ └── ...
├── .tpv_build/ # 构建目录(build_dir,自动生成)
│ ├── temp/ # 临时文件
│ │ ├── <sha1[0:2]>/ # SHA1 切片子目录(sha1_slice_level ≥ 1)
│ │ │ ├── <SHA1>.vpi # 签名存根
│ │ │ ├── <SHA1>.stub.ll # LLVM IR 声明
│ │ │ ├── <SHA1>.text.ll # 含代码的 .ll
│ │ │ └── <SHA1>.deps.txt # 依赖信息
│ │ └── _sha1_map.txt # SHA1→源文件路径映射(仅人类可读)
│ └── output/ # 输出文件
│ ├── kernel.bin # 内核二进制
│ ├── *.deps.txt # 依赖信息
│ └── linker.ld # 生成的链接脚本
应用项目
HelloWorld/
├── project.vpj # 项目配置
├── linker.ld # 链接脚本
├── main.vp # 应用入口
└── .tpv_build/ # 构建目录(自动生成)
├── temp/ # 临时文件
└── output/ # 输出文件
└── helloworld.elf # ELF 可执行文件
库项目
SerialLogger/
├── project.vpj # 项目配置
├── linker.ld # 链接脚本
├── serial_logger.vp # 库源码
└── .tpv_build/ # 构建目录(自动生成)
├── temp/ # 临时文件
└── output/ # 输出文件
链接脚本
ViperOS 使用自定义链接脚本控制内存布局:
ENTRY(_start)
SECTIONS
{
. = 0x100000; /* 加载地址 */
.text : {
*(.text.startup)
*(.text*)
}
.rodata : {
*(.rodata*)
}
.data : {
*(.data*)
}
.bss : {
*(.bss*)
*(COMMON)
}
}
编译命令
TransPyC 编译器的基本用法(注:适用于单个文件,而不适用于工程):
python TransPyC.py -f InputFile -o OutputFile [options]
命令行参数
| 参数 | 说明 |
|---|---|
-f |
输入文件路径 |
-o |
输出文件路径 |
-wh |
头文件列表 |
-debug |
调试输出文件 |
-cc |
编译命令 |
-cflags |
编译标志 |
-run |
编译后运行 |
-args |
运行参数 |
-h |
辅助文件(C 或 Python) |
工程编译使用(--project 指定工程文件):
python Projectrans.py --project project.vpj
即可
构建流程(真实骨架)
工程构建的实际流水线:
- Phase 1(声明阶段):扫描入口与依赖并建依赖图 → 1a 结构体注册 → 1b 生成
.vpi并翻译生成 stub - Phase 2(翻译与链接)
- Phase A-pre-vpi / Phase A-pre:加载
.vpi,预翻译准备 - Phase A:主循环多遍收敛翻译,
.stub.ll/.text.ll在此写盘 - Phase B:
llc并行编译.ll→.o - Phase B+:缺失 includes 按需编译
- Phase C:链接(
linker.cmd决定链接器)
- Phase A-pre-vpi / Phase A-pre:加载
增量编译
TransPyC 支持基于 SHA1 的增量编译,与两阶段编译模型紧密耦合:
阶段一增量
- 每个源文件按内容计算 SHA1 哈希(16 个十六进制字符,即 64 位截断)
- 如果
<SHA1>.vpi和<SHA1>.stub.ll已存在,则跳过生成(缓存命中) - 只有源文件内容变化导致 SHA1 变化时才重新生成声明接口
- SHA1 → 源文件路径映射在内存
Sha1Store中多遍收敛构建;temp/_sha1_map.txt(格式<sha1>:<relative_path>)仅人类可读
阶段二增量
- 阶段二(Phase A 主循环)在内存
Sha1Store/StubMergerStore中多遍收敛构建并复用映射,不依赖_sha1_map.txt - 旧产物清理使用
--clear-cache - 共享符号表为内存
StubMergerStore,按需加载避免每个文件重复加载
SHA1 命名空间与增量编译的协同
SHA1 同时服务于命名空间隔离和增量编译:
- 命名空间:非
t.CExport函数和结构体使用 SHA1 前缀,消除符号冲突 - 增量编译:SHA1 不变则缓存命中,SHA1 变化则重新生成