Skip to content

Windows 上 mcpp 调用 xlings 时应使用 --args-file 而非 --args,避免 cmd.exe 破坏 JSON 引号转义 #306

Description

@FarnaHerry

摘要

除摘要外内容均为ai生成,具体是agent的debug经理总结,是让agnet帮我build一下eui,直接mcpp build会报错,ai使用浑身解数用奇技淫巧修复了,大概问题有windows的cmd兼容问题和解析eui-neo这个带连字符的包创建的缓存问题。
具体内容如下

环境

┌───────────┬───────────────────────────┐
│ │ │
├───────────┼───────────────────────────┤
│ OS │ Windows 11 Pro 10.0.26200 │
├───────────┼───────────────────────────┤
│ mcpp │ 2026.7.27.1 │
├───────────┼───────────────────────────┤
│ xlings │ 0.4.66 │
├───────────┼───────────────────────────┤
│ toolchain │ llvm@20.1.7 (clang++) │
├───────────┼───────────────────────────┤
│ mirror │ CN(GLOBAL 同样复现) │
└───────────┴───────────────────────────┘

问题概述

Windows 上 mcpp build 无法安装 mcpplibs 注册 :

error: xlings install_packages failed (exit 1) for '' with 1 index repo configured
xlings emitted no structured error; re-runhe raw xlings invocation + output.

根因是 mcpp 通过 --args "" 向 xlings ows cmd.exe 时引号转义被破坏。xlings 提供了--args-file 专门解决这个问题——其帮助文档明确写了 "avoids cmd.exe quoting on Windows"——但 mcpp 没有使用它。

复现步骤

mcpp new testproj
cd testproj
echo '[dependencies.compat]' >> mcpp.toml
echo 'zlib = "1.3.2"' >> mcpp.toml
mcpp build

必现 xlings install_packages failed (exit 1)。

注意:包的源码实际上已经下载并解压成功——失败发生在 xlings 内部的安装后校验步骤,原因是 xlings 收到了被 cmd.exe 破坏的参数。

排查过程

  1. 隔离依赖

从 mcpp.toml 中去掉依赖后 mcpp build 成功。加回后稳定复现。所有 compat
包均受影响:zlib、freetype、libpng、yyjson、-neo。

  1. 检查注册表

本地 mcpplibs 克隆 (~/.mcpp/registry/data/mcpackages feature 分支上。切到 main 并pull(064de38)后获取了所有 compat 包描述文件。问题依旧。

  1. 向 xlings 注册 mcpplibs 源

xlings 默认只有 xim 源。手动注册 mcpplibs:

xlings interface add_repo --args '{"name":"mcpplibs","url":"https://github.com/mcpplibs/mcpp-index.git"}'
xlings update

此后 xlings interface package_info 可以正确返回 compat 包的元数据。但 mcpp build 仍然失败——因为 mcpp 自己调用 xlings 时用的是 --args,与手动注册无关。

  1. 直接复现 xlings 调用

通过 MCPP_VERBOSE=1 mcpp build 可以看到 mcpp 实际执行的命令:

xlings interface install_packages --args "{\0.5.3"],"yes":true}" 2>nul

直接在终端执行这条命令同样失败(exit 1,stderr 被 2>nul 丢弃所以看不到错误)。

  1. 用 --args-file 绕过(关键证据)

xlings 的 interface --help 输出:

--args-file Read capability arguments from a file (avoids cmd.exe quoting on Windows)

把 JSON 写入临时文件,改用 --args-file:

$d = @{targets=@("compat:freetype@2.13.3"); yes=$true}
$d | ConvertTo-Json -Compress | Set-Content ing UTF8
& xlings.exe interface install_packages --args-file "$env:TEMP\xargs.json"

所有包全部安装成功:zlib、freetype、libpng、d、glfw、tray——全部 exitCode: 0, failed: 0,success: 1。

这证实了问题出在 --args 的 cmd.exe 引号转义上,而非网络、SHA256、或包描述文件本身。

  1. eui-neo 的连字符解析问题(次生 bug)

eui-neo 是唯一一个即使用了 --args-file 仍然安装失败的包。install_summary 显示 failed: 1, success: 0,但下载成功(SHA256 已验证匹配:6951ac330d0307c633bafe720b7888bf32785103eb16973adb4ee05ef06e64d1)。

进一步排查发现 xlings 创建的缓存目录为:

compat-x-eui/0.5.3/ ← 错误,缺少 "-neo"

compat-x-eui-neo/0.5.3/ ← 正确

包名 eui-neo 含连字符,xlings 在生成缓存路径时从第一个连字符处截断了名称。手动将 tarball 复制到正确路径并解压后,mcpp 可以成功编译 eui-neo。

根因总结

  1. 主因:mcpp 调用 xlings 时使用 --args "<JS并破坏了 JSON 的转义。修复方案:将 JSON写入临时文件,改用 --args-file 传参——这正是 xlings 推荐的做法,改动量应在 2-3 行代码以内。
  2. 次因:xlings 对含连字符的包名(如 compat:eui-neo)存在解析 bug,名称截断导致缓存路径不匹配。
  3. 附带问题:mcpp new 生成的模板项目默认带有地 mcpplibs 注册表克隆可能处于尚未合并eui-neo 的旧分支。

建议修复

mcpp 侧:将 xlings interface 调用从 --args 改为 --args-file。流程:写 JSON 到临时文件 → 传 --args-file →
xlings 返回后清理临时文件。

xlings 侧:修复包名中连字符的解析,使 eui-neo 正确映射到 compat-x-eui-neo 而非 compat-x-eui。

临时 Workaround

在 mcpp build 之前手动预装依赖:

HOME = "$env:USERPROFILE.mcpp\registry"

$packages = @(
@{targets=@("compat:zlib@1.3.2"); yes=$true},
@{targets=@("compat:freetype@2.13.3"); yes=$true},
@{targets=@("compat:libpng@1.6.43"); yes=$true},
@{targets=@("compat:yyjson@0.12.0"); yes=$true},
@{targets=@("compat:opengl@2026.05.31"); yes=$true},
@{targets=@("compat:glad@0.0.0-651a425")
@{targets=@("compat:glfw@3.4"); yes=$true},
@{targets=@("compat:tray@0.0.0-8dd1358")
)
$xlings = "$env:USERPROFILE.mcpp\registry\bin\xlings.exe"
foreach ($p in $packages) {
$json = $p | ConvertTo-Json -Compress
$file = "$env:TEMP\mcpp_xargs.json"
$json | Set-Content -Path $file -Encodin
& $xlings interface install_packages --args-file $file
}

eui-neo 需要额外手动解压:

$base = "$env:USERPROFILE.mcpp\registry\dat3"
New-Item -ItemType Directory -Force -Path $base | Out-Null
tar -xzf "$base\v0.5.3.tar.gz" -C $base

之后 mcpp build 即可成功。

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions