为了跑一个刚开源 6 天的模型,我把 llama.cpp 重新编译了一遍

markdown
## 环境
| 项目 | 版本 |
|---|---|
| CPU | R9-7900(Zen4 / AVX512) |
| GPU | RTX 3070 8G,驱动 581.15 |
| OS | Windows |
| 编译器 | MSVC 19.51(Visual Studio 18 / 2026 Build Tools) |
| CMake | 4.3.1-msvc1 |
| Ninja | 1.13.2 |
| CUDA Toolkit | 13.0 → 13.3.1 |
| 源码 | XHToken/llama.cpp fork(spark2_5 架构) |
## 结论
编译失败的根因是 **CUDA 13.0 不支持 VS 2026(MSVC 19.51)**,
不是显卡、驱动或操作问题。解法是把 CUDA Toolkit 升到 **13.2 及以上**
(官方从 13.2 起支持 VS 2026),无需降级编译器。
本文按坑的发生顺序整理 11 个报错、现象、根因与解法,
附可直接复制的 CMake 命令和三条 GPU 生效验证方法。
一、为什么非编不可
讯飞子公司 9 月 1 日开源了 Spark-X2.5,主打端侧原生 1M 上下文。我看中的是它 4B / 1.7B 两个尺寸------我这张 3070 跑得动。
兴冲冲去下模型,然后发现没有现成的轮子:
- llama.cpp 上游还没合并支持(PR #27868 挂着)
- vLLM 要装外挂插件才能跑
- Ollama / LM Studio 都得换后端
也就是说,"开箱即跑"这四个字,在这个模型上不成立。官方只给了个自定义 fork:XHToken/llama.cpp。
想要,就得自己编。
下面是我从零编译到跑通的全过程,一共踩了 11 个坑。每个坑都写了现象和解法,你可以按顺序对照着排查。
二、我的环境
| 项目 | 版本 |
|---|---|
| CPU | R9-7900(Zen4,支持 AVX512) |
| GPU | RTX 3070 8G,驱动 581.15 |
| 编译器 | MSVC 19.51(Visual Studio 18 / 2026) |
| CMake | 4.3.1-msvc1(VS 自带) |
| Ninja | 1.13.2(VS 自带) |
| CUDA Toolkit | 13.0(后来升到 13.3.1) |
| 源码 | D:\llamacpp(XHToken fork,含 spark2_5 架构) |
三、第一阶段:先让 CPU 版跑起来(坑 1--5)
我的策略是双轨:先确保 CPU 版能出东西,GPU 版另想办法。事实证明这个决定救了场。
坑 1:CMake 下成了源码包
我下了一个 cmake-4.4.3,解压完发现目录里只有 bootstrap、Source/、CMakeLists.txt,没有 bin/cmake.exe。
那是个源码 tarball,不是 Windows 发行包。
解法 :别下。VS 自带 CMake------...\Microsoft\CMake\CMake\bin\cmake.exe,版本 4.3.1-msvc1,零下载直接用。
坑 2:我以为我装的是 VS 2022
用 vswhere 一查,实际装的是 Visual Studio 18(2026) Build Tools,cl.exe 版本 19.51。
CPU 编译完全不受影响。但这个误判是后面 GPU 版三次碰壁的根源------我先记着,第五段会回来。
坑 3:环境变量大小写重复,MSBuild 直接崩
编译时报了个很怪的错:
MSB6001: "CL.exe" 的命令行开关无效
System.ArgumentException: 已添加项。字典中的关键字: "https_proxy"
所添加的关键字: "HTTPS_PROXY"
Windows 环境变量不区分大小写。 我环境里 http_proxy/HTTP_PROXY、https_proxy/HTTPS_PROXY 双双存在,MSBuild 建 Hashtable 时因为"重复键"抛异常。
解法:编译前把这四个变量全部 unset。
坑 4:MSYS 路径被吃掉
我传的是 Git Bash 风格的 /c/Program Files/...,CMake 是 Windows 原生程序,只认 C:\Program Files\...。
解法 :改原生路径格式。用 Bash 调原生程序时,加 MSYS_NO_PATHCONV=1 也能解决。
坑 5:GGML_NATIVE 和 GGML_BACKEND_DL 互斥
CMake 直接报:GGML_NATIVE is not compatible with GGML_BACKEND_DL。
解法 :留 GGML_NATIVE(吃满 Zen4 的 AVX512,性能优先),去掉动态后端加载。
到这里,CPU 版配置通过,编译成功 。我拿到了 llama-completion.exe,模型能加载能生成,指令集探测里 AVX512 那一栏是 Success。
CPU 版的底线守住了。接下来才是硬仗。

四、第二阶段:GPU 版三次碰壁(坑 6--10)
坑 6:CUDA_PATH 是空的
CMake 报找不到 cudart.lib。文件明明在 lib\x64\ 下躺着------问题是环境变量 CUDA_PATH 为空,CMake 靠它定位库目录。
解法:手动把 Toolkit 根目录喂给 CMake。
坑 7:CMAKE_SYSTEM_PROCESSOR 是空的
上一个坑填完,还是找不到。查 ggml 自己的检测逻辑才发现:CMake 打印的 CMAKE_SYSTEM_PROCESSOR 是空值 ,处理器架构未知,导致 FindCUDAToolkit 拼不出 lib\x64 这个子目录。
解法:手动指定架构 + 库路径。
坑 8:CUDA 13.0 的 MSBuild 集成只到 VS 2022
接着报 No CUDA toolset found。
原因回到坑 2 :CUDA 13.0 安装器只把 MSBuild 集成文件(BuildCustomizations)装到 VS 2022,我这是 VS 18(2026),没有。
官方给的修法是往 VS 目录里塞集成文件------我不动系统目录,所以绕开:改用 Ninja 生成器直接调 nvcc,不依赖 VS 集成。
坑 9:nvcc 拒绝我的编译器
Ninja 走起来后,nvcc 直接把这行拍脸上:
host_config.h(164): fatal error C1189: #error:
-- unsupported Microsoft Visual Studio version!
Only the versions between 2019 and 2022 (inclusive) are supported!
CUDA 13.0 的 nvcc 最高只认到 VS2022(MSVC 19.44),我是 19.51。
加 --allow-unsupported-compiler 可以绕过这个检查,社区有人这么干成过。我试了。
坑 10:cudafe++ 崩溃,这条路彻底堵死
绕过版本检查之后,CUDA 前端 cudafe++ 直接崩:
0xC0000005 (ACCESS_VIOLATION)
排查下来,cudafe++ 需要调 reg.exe 查注册表拿 VS/Windows SDK 路径,而 reg.exe 被安全中心的程序黑名单拦了------这是 Security Center 级别的策略,不是关掉沙箱就能解的。而且 cudafe++ 和 VS 2026 的全新 CRT 之间,可能还有真实的不兼容。
这条路到此为止。 我没有继续钻,停下来换思路。
五、破局:不是降级编译器,是升 CUDA
我本来准备装 VS2022 Build Tools 来迁就 CUDA 13.0。查了一圈官方文档才发现方向反了:
从 CUDA Toolkit 13.2 起,官方支持 Visual Studio 2026(MSVC 19.51)。
也就是说------不用动编译器,只要把 CUDA 从 13.0 升到 13.2 以上,现有工具链就能直接编。
几个让人安心的点(都从官方 Release Notes 确认过):
- 可以并存安装 。13.3.1 装到
v13.3.1目录,现有的 v13.0 原封不动。 - 不动显卡驱动。从 CUDA 13.1 起 Windows 安装包不再捆绑驱动,我现在的 581.15 一点没变。
- 不影响其他推理引擎 。我另外两个引擎目录里各自带着
cudart64_12.dll,Windows 加载 DLL 优先找 exe 所在目录,根本不会去碰 Toolkit 目录。我常用的 qwen3.6-35B-A3B、qwen3.8-27B 照跑不误。
下载地址(2026-09-07 验证可用):
https://developer.download.nvidia.com/compute/cuda/13.3.1/local_installers/cuda_13.3.1_windows.exe
约 2.36 GB。装的时候选 Custom,只勾 CUDA 主项(nvcc / cudart / cublas 都在里面),Nsight 和 Visual Studio Integration 可以取消,装得快占得小。
装完重新 configure + 编译,一次过 。产物在 build-cuda\bin\,里面有一个 50 MB 的 ggml-cuda.dll ,架构 sm_86(对应 3070)。
六、编完还没完:还有两个坑
坑 A:对话模式静默崩溃,退出码 127,一个字都不说
模型加载成功,打印完 chat template is available, enabling conversation mode,然后进程直接退出,退出码 127,没有任何报错信息。
我试了:关 reasoning------没用;换模型档位------没用;换 chatml 模板------能跑 ;用 -no-cnv 裸补全------能跑。
只有官方模板崩。
根因 :本 fork 的 --jinja 默认是关闭的。关闭时 llama.cpp 只接受一份硬编码的"常用模板"白名单(chatml / llama2 / qwen 这些)。而 Spark-X2.5 的官方 chat_template 用了大量高级 Jinja 特性:
{% macro %}宏、{% set ns = namespace(...) %}命名空间loop.previtem/loop.nextitemis defined/is string/tojson过滤器raise_exception(...)(HuggingFace 注入的全局函数,llama.cpp 不实现)
回落渲染器解析不了 → 抛出未捕获的 C++ 异常 → 进程 127 退出。
解法 :每次调用加 --jinja。 建议做成别名或写进启动脚本,别靠记性。
坑 B:两个 exe,我一直跑错的那个
这个是让我误判最久的。
- GPU 构建只编出了
llama-cli.exe(--jinja默认开) - CPU 构建只有
llama-completion.exe(--jinja默认关)
我一直跑的是旧的 CPU 版 llama-completion.exe,从来没调过新的 GPU 版 llama-cli.exe------所以"GPU 加速没生效"。
这不是编译失败,是二进制路径和名称混淆。 两套二进制别混用:跑 GPU 用 build-cuda\bin\llama-cli.exe,跑 CPU 用 build-cpu\bin\Release\llama-completion.exe。
七、关键参数(按你的路径改)
bat
REM ------ CPU 版 ------
cmake -B build-cpu -G "Visual Studio 18 2026" ^
-DGGML_NATIVE=ON ^
-DLLAMA_BUILD_SERVER=OFF
cmake --build build-cpu --config Release
REM ------ CUDA 版(装完 13.2+ 之后)------
cmake -B build-cuda -G Ninja ^
-DGGML_CUDA=ON ^
-DGGML_NATIVE=ON ^
-DCMAKE_CUDA_ARCHITECTURES=86 ^
-DCUDAToolkit_ROOT="C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v13.3.1"
cmake --build build-cuda --config Release
几个说明:
CMAKE_CUDA_ARCHITECTURES=86是 3070 的计算能力代号(sm_86)。只编这一个架构能省大量编译时间,别让它把所有架构都编一遍。GGML_NATIVE和GGML_BACKEND_DL二选一,别同时开(坑 5)。- 编译前把
http_proxy/HTTP_PROXY/https_proxy/HTTPS_PROXY清掉(坑 3)。 - 想开 OpenAI 兼容服务端就留
LLAMA_BUILD_SERVER,但注意 Web UI 子项目会联网拉资源、失败会中断编译,我这边是直接关掉的。
八、怎么确认你真的用上显卡了
别信感觉,看数字。三条验证:
- 看产物 :
build-cuda\bin\下有没有ggml-cuda.dll(约 50 MB)。没有就是没编进去。 - 看体积和架构 :编译日志里搜
CMAKE_CUDA_ARCHITECTURES,确认是你的卡(3070 是 86)。 - 跑个对照 :同一个模型、同一个问题,分别用
-ngl 99(全上显卡)和-ngl 0(强制纯 CPU)跑一遍,比速度。
我这边实测的对照:Spark-X2.5-4B-Q4,-ngl 99 是 105.3 t/s,-ngl 0 是 18.6 t/s,差 5.7 倍。差这么多,说明显卡确实在干活。
顺带一个提醒 :-ngl 99 意思是"尽可能多往显卡上放"。如果模型装不下(比如 8.23 GB 的 4B-F16 塞我这张 8G 卡),日志会明写 failed to fit params to free device memory,然后静默退化到 CPU+内存混合跑------速度会掉到十几 t/s,但不会报错。看到速度不对劲,先查这个。

九、值不值
回头看,这次编译大概耗了我大半天的排查,但换来的东西是实的:
- 上游 PR 合并之前,这是唯一能在我这张卡上跑这个模型的路子
- 完整摸清了 CUDA 13 + VS 2026 这个组合的脾气(网上这部分的资料还很少)
- 顺手沉淀了 11 个坑的排查顺序,下次再编别的 fork 能省一半时间
如果你也卡在类似的地方,我的建议是:先确认你的 VS 版本和 CUDA 版本的对应关系,再动手。 大部分"编译失败"都不是操作问题,是版本组合问题。
markdown
## 排错 checklist
按顺序自查:
- [ ] `cmake.exe` 在不在?VS 自带的就够用,别下源码包
- [ ] `vswhere` 确认 VS 真实版本(2022 是 17,2026 是 18)
- [ ] 编译前 unset `http_proxy` / `HTTP_PROXY` / `https_proxy` / `HTTPS_PROXY`
- [ ] 路径用 `C:\...` 原生格式,不要 `/c/...`
- [ ] `GGML_NATIVE` 与 `GGML_BACKEND_DL` 二选一
- [ ] `CUDA_PATH` 环境变量是否为空 → 手动指定 `CUDAToolkit_ROOT`
- [ ] `CMAKE_SYSTEM_PROCESSOR` 是否为空 → 手动指定架构
- [ ] `No CUDA toolset found` → CUDA 版本的 MSBuild 集成是否覆盖你的 VS 版本
- [ ] `host_config.h(164)` 报错 → nvcc 不认宿主编译器,查 CUDA 版本支持矩阵
- [ ] `cudafe++ 0xC0000005` → 检查 reg.exe 是否被安全策略拦截
- [ ] **根本解法:CUDA 13.2+ 支持 VS 2026,升级而非降级**
## 验证 GPU 生效
1. `build-cuda\bin\ggml-cuda.dll` 存在(约 50 MB)
2. 编译日志中 `CMAKE_CUDA_ARCHITECTURES` 与你的卡匹配(3070 为 86)
3. 同一模型 `-ngl 99` 与 `-ngl 0` 对比速度(本文实测 105.3 t/s vs 18.6 t/s)
## 可复现命令
(见正文第七节命令块)
如果你也想玩一下星火X2.5系列,可以关注我的同名GZH,后台回复【X2.5】获取我已经编译好的链接,下载即用。