Files
TransPyC/wiki/12-project.md
T

8.4 KiB
Raw Blame History

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 决定链接器)

增量编译

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 命名空间机制。