Skip to content

Commit 063fb6f

Browse files
authored
fix: detect xlings package path and fallback MCPP_HOME to ~/.mcpp (#60)
When mcpp is installed via `xlings install mcpp`, the binary lives at ~/.xlings/data/xpkgs/xim-x-mcpp/<ver>/bin/mcpp. The previous home_dir() detected bin/ and used the grandparent (the xpkgs package directory) as MCPP_HOME, creating a nested xlings sandbox that broke toolchain installation and lost installed toolchains on mcpp upgrade. Now home_dir() checks for the data/xpkgs ancestor pattern and falls back to ~/.mcpp/ (same behavior as CI with explicit MCPP_HOME). Also extract default_mcpp_home() with unified Windows (%USERPROFILE%) and POSIX ($HOME) fallback logic.
1 parent 326f97c commit 063fb6f

2 files changed

Lines changed: 55 additions & 15 deletions

File tree

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# Fix: xlings 包内 mcpp 的 MCPP_HOME 检测
2+
3+
## 问题
4+
5+
`xlings install mcpp` 安装的 mcpp 二进制位于 `~/.xlings/data/xpkgs/xim-x-mcpp/0.0.20/bin/mcpp`
6+
`home_dir()` 检测到 `bin/` 父目录后,将祖父目录作为 MCPP_HOME,导致嵌套沙箱:
7+
8+
```
9+
MCPP_HOME = ~/.xlings/data/xpkgs/xim-x-mcpp/0.0.20/
10+
→ registry/ = ~/.xlings/data/xpkgs/xim-x-mcpp/0.0.20/registry/
11+
→ XLINGS_HOME = 同上
12+
→ 工具链安装到 registry/data/xpkgs/xim-x-llvm/20.1.7/ ← 嵌套失败
13+
```
14+
15+
## 修复
16+
17+
`home_dir()` 的自包含模式检测中,增加 xlings 包路径排除:如果祖先目录中存在
18+
`data/xpkgs` 模式,说明在 xlings 包内,fallback 到 `~/.mcpp/`
19+
20+
同时提取 `default_mcpp_home()` 统一三平台的 HOME fallback(Windows 用 %USERPROFILE%)。
21+
22+
## 改动
23+
24+
`src/config.cppm``home_dir()` 函数,约 20 行。

src/config.cppm

Lines changed: 31 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -168,31 +168,47 @@ void print_status(std::string_view verb, std::string_view msg) {
168168
}
169169
}
170170

171+
std::filesystem::path default_mcpp_home() {
172+
// Windows: %USERPROFILE%\.mcpp POSIX: $HOME/.mcpp
173+
if constexpr (mcpp::platform::is_windows) {
174+
if (auto* e = std::getenv("USERPROFILE"); e && *e)
175+
return std::filesystem::path(e) / ".mcpp";
176+
}
177+
if (auto* e = std::getenv("HOME"); e && *e)
178+
return std::filesystem::path(e) / ".mcpp";
179+
return std::filesystem::current_path() / ".mcpp";
180+
}
181+
171182
std::filesystem::path home_dir() {
183+
// 1. Explicit $MCPP_HOME takes priority (CI, advanced users).
172184
if (auto* e = std::getenv("MCPP_HOME"); e && *e)
173185
return std::filesystem::path(e);
174186

175-
std::error_code ec;
176187
auto exe = mcpp::platform::fs::self_exe_path();
177188
if (exe.has_parent_path() && exe.parent_path().filename() == "bin") {
178-
// Dev builds emit binaries at target/<triple>/<fp>/bin/<exe>,
179-
// matching the bin/ shape. Any ancestor literally named
180-
// "target" disqualifies self-contained mode and falls through
181-
// to $HOME/.mcpp — so first-run on a dev binary doesn't drop
182-
// a half-populated sandbox into target/.
183-
bool isDevPath = false;
184-
for (auto p = exe.parent_path();
185-
!p.empty() && p != p.parent_path();
189+
auto candidate = exe.parent_path().parent_path();
190+
191+
// Disqualify self-contained mode for two cases:
192+
// a) Dev builds: .../target/<triple>/<fp>/bin/<exe>
193+
// b) xlings packages: .../data/xpkgs/xim-x-mcpp/<ver>/bin/mcpp
194+
// Creating a nested xlings sandbox inside the xpkgs directory
195+
// breaks toolchain installation (nested XLINGS_HOME) and loses
196+
// installed toolchains when the mcpp package version is upgraded.
197+
bool disqualified = false;
198+
for (auto p = candidate;
199+
p.has_parent_path() && p != p.root_path();
186200
p = p.parent_path()) {
187-
if (p.filename() == "target") { isDevPath = true; break; }
201+
if (p.filename() == "target") { disqualified = true; break; }
202+
if (p.filename() == "xpkgs") {
203+
auto parent = p.parent_path().filename().string();
204+
if (parent == "data") { disqualified = true; break; }
205+
}
188206
}
189-
if (!isDevPath)
190-
return exe.parent_path().parent_path();
207+
if (!disqualified)
208+
return candidate;
191209
}
192210

193-
if (auto* e = std::getenv("HOME"); e && *e)
194-
return std::filesystem::path(e) / ".mcpp";
195-
return std::filesystem::current_path() / ".mcpp";
211+
return default_mcpp_home();
196212
}
197213

198214
std::expected<std::string, std::string> run_capture(const std::string& cmd) {

0 commit comments

Comments
 (0)