Repository navigation
Description
问题
mcpp 2026.11.9.1 解析官方推荐的不加引号的点分依赖名时,如果命名空间下有一个包叫 version,会把整个命名空间表误认成单个依赖配置。
实际项目中的声明:
[dependencies]
gpp.core = { path = "../GalTranslPP" }
gpp.version = { path = "../GPPVersion" }mcpp emit build-database --format json 对包含上述依赖的成员返回:
MCPP_BUILD_DATABASE_PLAN_FAILED: GPPGUI: workspace member 'GPPGUI':
GPPGUI/mcpp.toml: error: [dependencies."gpp"] must specify 'path', 'version', or 'git'
同样的问题发生在 CLI 和 Updater 成员中,它们也依赖 gpp.version。不包含这些普通依赖的 Core 和 Version 成员仍能被描述,结果是只有部分编译数据库可用。
对 IDE 的实际影响
mcppls 0.21.0 的诊断包记录了以上 producer-partial 错误,调用的 mcpp 为 2026.11.9.1,emit build-database 退出码为 1。
GUI 成员缺少有效编译命令后,打开 GPPGUI/UpdateWidget.cpp,引擎使用了带 Core 配置的命令:只有 QtCore 的包含路径和 QT_CORE_LIB,没有 QtWidgets、QtGui 和 ElaWidgetTools 的路径,因此出现:
UpdateWidget.h:3:10: fatal error: 'QWidget' file not found
QtWidgets/QWidget 文件实际存在。这里的 Qt 报错是依赖解析失败后的下游现象,根因不在 Qt 安装或头文件路径本身。
原因定位
v2026.11.9.1 的 modules/manifest/src/toml.cppm 中:
auto looks_like_inline_dep_spec = [](const t::Table& sub) {
if (sub.empty()) return false;
for (auto& [sk, sv] : sub)
if (sk == "path" || sk == "version" || sk == "git" || sk == "workspace")
return true;
return false;
};这里只检查键名,没有检查 sv 的类型。
TOML 将 gpp.version = { path = "../GPPVersion" } 解析成 gpp 命名空间表,其 version 子项的值是一个表。上述函数看到 version 键就返回 true,后续把 gpp 当作依赖,并尝试从其直接子项读取字符串 path/version/git。由于此时 version 实际是表,最终报 dependencies."gpp" 缺少来源。
函数前的注释假设 “no package is named version / path / git / workspace”,而 gpp.version 是实际存在的正常包名。当前 main 上仍能看到同样的键名判断。
可供独立复现的最小配置
下面是从实际项目缩减的示例;本次没有额外执行该独立示例,也没有运行构建。实际观察来自上述诊断包和对应版本源码核对。
目录:
repro/
app/
mcpp.toml
main.cpp
version/
mcpp.toml
version.cpp
app/mcpp.toml:
[package]
name = "app"
version = "0.1.0"
standard = "c++23"
[dependencies]
gpp.version = { path = "../version" }
[targets.app]
kind = "bin"
main = "main.cpp"app/main.cpp:
int main() { return 0; }version/mcpp.toml:
[package]
namespace = "gpp"
name = "version"
version = "0.1.0"
standard = "c++23"
[build]
sources = ["version.cpp"]
[targets.version]
kind = "lib"version/version.cpp:
int example_version() { return 1; }在 app 目录执行:
mcpp emit build-database --format json
预期应解析为依赖 gpp.version,而不是名为 gpp 的单个依赖。
预期修复方向
判别依赖配置和命名空间表时,应结合来源字段的值类型,不能只因存在同名键就判定为依赖配置。例如本例的 version 是表,应该继续作为命名空间内的包处理。建议覆盖包名为 version/path/git/workspace 的情况,并保留对真正依赖配置的错误诊断。
"gpp.version" = { path = "../GPPVersion" } 可以在结构上避开这次误判,但没有额外验证;而且官方文档从 2026.11.8.1 起已建议将带引号的点分键改成不带引号的形式,所以不应要求用户靠恢复旧写法绕过。
环境
- Windows x64
- mcpp 2026.11.9.1
- mcppls 0.21.0
- 项目工具链 Clang 23.1.3,目标 x86_64-pc-windows-msvc
- mcppls 诊断包生成时间:2026-11-10T07:31:02.065Z
Activity
2026.11.10.2: FreeBSD's musl identity; cfg barewords from the rows; #918
speak-agent commentedon Nov 10, 2026
mcpp 2026.11.10.2(#920)修正了此问题。
依赖表仅当
path/version/git的值为字符串、或workspace的值为布尔时,才被视为单个依赖说明;同名键的值为表时,该键是命名空间中的包。因此声明
gpp.core与gpp.version两个包,[workspace.dependencies]同理。emit build-database可完整描述依赖gpp.version的成员。验证:单元测试
Manifest/APackageNamedLikeASpecField;e2e 1074 以 issue 中的最小配置构建、运行并生成编译数据库(在 2026.11.10.1 上复现[dependencies."gpp"] must specify ...,在 2026.11.10.2 上通过)。xlings install mcpp@2026.11.10.2可获得此版本。