Files
xtrain/docs/00-build-chain.md
Gahow Wang c1b204296b docs: backfill T1 build-chain
T1 shipped without a design doc; capture the Rust↔CUDA build chain
(build.rs+nvcc, no_cuda cfg pattern, RAII GpuBuffer, gitea↔dash5 flow).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 15:12:55 +08:00

82 lines
3.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Phase T1: Rust↔CUDA Build Chain — Design Document
> 回填文档T1 随 commit `92acf9f` 落地scaffold + 构建链路 + vecadd 冒烟测试),
> 当时未写文档,此处补记,供后续 Phase 回溯。
## Goal
打通「Rust 调 CUDA」的最小闭环`build.rs``nvcc``csrc/*.cu`
经手写 `extern "C"` FFI 链入 Rust本地无 GPU/nvcc 时仍能 `cargo check`
验收以一个 vector-add kernel 冒烟通过为准。
## Module Layout
```
xtrain/
├── Cargo.toml # workspace
├── csrc/
│ └── test/vecadd.cu # 冒烟用 c[i]=a[i]+b[i]
└── crates/xtrain-cuda/
├── build.rs # 检测 nvcc → 编 .cu / 链 cudart否则发 no_cuda cfg
└── src/
├── ffi.rs # extern "C" 绑定cudaMalloc/Memcpy/Free…+ kernel launch
├── error.rs # CudaError + check(code)
├── device.rs # device_count / set_device / synchronize
└── memory.rs # RAII GpuBufferalloc/H2D/D2H/Drop
```
## Key Design Decisions
### `build.rs` 检测 nvcc缺失则发 `no_cuda` cfg
```rust
if !nvcc_available(&cuda_path) {
println!("cargo:warning=nvcc not found — skipping CUDA compilation (host-only build).");
println!("cargo:rustc-cfg=no_cuda");
return; // 不编 .cu、不链 cudart
}
// 否则cc::Build::new().cuda(true)…-gencode=arch=compute_120,code=sm_120
```
- 本地机无 GPU/nvcc → 跳过 CUDA 编译host 侧 Rust 照常 `cargo check`
- dash5 有 nvcc 12.9 → 实编 `.cu`,目标 `sm_120`RTX 5090
- 必须配 `println!("cargo:rustc-check-cfg=cfg(no_cuda)")` 声明自定义 cfg
否则新版 rustc 报 `unexpected_cfgs` warning。
### `no_cuda` cfg 门控 GPU-only 代码
GPU 专属的 kernel-launch FFI 与集成测试用 `#[cfg(not(no_cuda))]` 包起来:
```rust
#[cfg(not(no_cuda))]
unsafe extern "C" {
pub fn launch_vecadd_f32(a: *const f32, b: *const f32, c: *mut f32, n: i32, stream: CudaStream);
}
```
测试文件顶用 `#![cfg(not(no_cuda))]` 整体门控。**注意**`cudaMalloc`
runtime 符号在 `ffi.rs` 里**不**门控(恒声明),本地只 `cargo check`(不链接)所以无碍;
真正链接发生在 dash5cudart 在)。约定:**本地只 check/fmt链接+测试都在 dash5**。
### RAII `GpuBuffer`
`alloc`/`copy_from_host`(H2D)/`copy_to_host`(D2H)`Drop``cudaFree`
`unsafe impl Send`。后续张量层在其上搭 device 存储(见 `docs/01-tensor.md`)。
## 验证方法
```sh
ssh dash5
export PATH=/usr/local/cuda/bin:/opt/wjh/.cargo/bin:$PATH
cd ~/projects/xtrain && cargo test -p xtrain-cuda -- --nocapture
# vecadd OK: a[i]+b[i]c[i]=3i 通过
```
本地(无 GPU`cargo check` 绿build.rs 发 `no_cuda`GPU 测试编译出局)。
## gitea ↔ dash5 同步流
- `origin = git@gitea:gahow/xtrain.git`,分支 `main`git 身份用 `~/.gitconfig`(不 `-c` 覆盖)。
- 本地 `git push origin main` → dash5 `cd ~/projects/xtrain && git pull` → export PATH 后构建/测试。
- 连 gitea 会打印无害的 `Welcome to VyOS` banner可忽略。