274 lines
8.4 KiB
Markdown
274 lines
8.4 KiB
Markdown
# 12 - 项目配置与构建
|
||
|
||
Viper 项目使用 `project.vpj` 配置文件管理编译和链接参数(Python 单文件模式仍接受 `project.json`)。
|
||
|
||
## project.vpj 结构
|
||
|
||
```json
|
||
{
|
||
"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 使用自定义链接脚本控制内存布局:
|
||
|
||
```ld
|
||
ENTRY(_start)
|
||
|
||
SECTIONS
|
||
{
|
||
. = 0x100000; /* 加载地址 */
|
||
|
||
.text : {
|
||
*(.text.startup)
|
||
*(.text*)
|
||
}
|
||
|
||
.rodata : {
|
||
*(.rodata*)
|
||
}
|
||
|
||
.data : {
|
||
*(.data*)
|
||
}
|
||
|
||
.bss : {
|
||
*(.bss*)
|
||
*(COMMON)
|
||
}
|
||
}
|
||
```
|
||
|
||
## 编译命令
|
||
|
||
TransPyC 编译器的基本用法(注:适用于单个文件,而不适用于工程):
|
||
|
||
```bash
|
||
python TransPyC.py -f InputFile -o OutputFile [options]
|
||
```
|
||
|
||
### 命令行参数
|
||
|
||
| 参数 | 说明 |
|
||
|------|------|
|
||
| `-f` | 输入文件路径 |
|
||
| `-o` | 输出文件路径 |
|
||
| `-wh` | 头文件列表 |
|
||
| `-debug` | 调试输出文件 |
|
||
| `-cc` | 编译命令 |
|
||
| `-cflags` | 编译标志 |
|
||
| `-run` | 编译后运行 |
|
||
| `-args` | 运行参数 |
|
||
| `-h` | 辅助文件(C 或 Python) |
|
||
|
||
工程编译使用(`--project` 指定工程文件):
|
||
```bash
|
||
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` 决定链接器)
|
||
|
||
## 增量编译
|
||
|
||
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 变化则重新生成
|
||
|
||
详见 [01-overview.md 中 SHA1 命名空间机制](01-overview.md#sha1-命名空间机制)。
|