Skip to content

Commit 4dad1c7

Browse files
committed
fix: Windows xpkg fallback — copy from xlings global data when sandbox is empty
xlings on Windows may extract large packages (LLVM ~148MB) into its global data dir instead of the mcpp sandbox. This happens because the extraction subprocess doesn't always inherit XLINGS_HOME. Small packages (ninja 268KB) work correctly in the sandbox. Workaround: after install, if the expected xpkg path is missing, check xlings' global data dirs and copy into the sandbox. This keeps mcpp functionally self-contained while working around the xlings Windows extraction behavior.
1 parent 6e4739f commit 4dad1c7

2 files changed

Lines changed: 31 additions & 2 deletions

File tree

src/pm/package_fetcher.cppm

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -605,6 +605,37 @@ Fetcher::resolve_xpkg_path(std::string_view target,
605605
};
606606

607607
auto resolve = [&]() -> std::expected<XpkgPayload, CallError> {
608+
#if defined(_WIN32)
609+
// Workaround: xlings on Windows may extract large packages (e.g. LLVM)
610+
// into its global data dir instead of the mcpp sandbox, because the
611+
// extraction subprocess doesn't inherit XLINGS_HOME. Detect this and
612+
// copy the payload into the sandbox so mcpp remains self-contained.
613+
if (!std::filesystem::exists(verdir)) {
614+
// Try xlings' own data dir (where `xlings self install` placed it)
615+
auto xhome = std::getenv("USERPROFILE");
616+
if (!xhome) xhome = std::getenv("HOME");
617+
if (xhome) {
618+
// xlings stores xpkgs at <home>/.xlings/data/xpkgs/ or
619+
// <home>/.xlings/subos/default/data/xpkgs/
620+
auto pkgDir = verdir.parent_path().filename().string();
621+
auto verName = verdir.filename().string();
622+
std::filesystem::path candidates[] = {
623+
std::filesystem::path(xhome) / ".xlings" / "data" / "xpkgs" / pkgDir / verName,
624+
std::filesystem::path(xhome) / ".xlings" / "subos" / "default" / "data" / "xpkgs" / pkgDir / verName,
625+
};
626+
for (auto& src : candidates) {
627+
std::error_code ec;
628+
if (std::filesystem::exists(src, ec) && std::filesystem::is_directory(src, ec)) {
629+
std::filesystem::create_directories(verdir.parent_path(), ec);
630+
std::filesystem::copy(src, verdir,
631+
std::filesystem::copy_options::recursive
632+
| std::filesystem::copy_options::overwrite_existing, ec);
633+
if (!ec) break;
634+
}
635+
}
636+
}
637+
}
638+
#endif
608639
if (!std::filesystem::exists(verdir)) {
609640
return std::unexpected(CallError{
610641
std::format("xpkg payload missing: {}", verdir.string())});

src/xlings.cppm

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -663,8 +663,6 @@ int install_with_progress(const Env& env, std::string_view target,
663663
_putenv_s("XLINGS_PROJECT_DIR", "");
664664
std::error_code ec_mkdir;
665665
std::filesystem::create_directories(env.home, ec_mkdir);
666-
// Use raw command — _putenv_s is inherited by popen child.
667-
// No 2>nul — let xlings output be visible for debugging.
668666
auto cmd = std::format("{} interface install_packages --args {}",
669667
env.binary.string(),
670668
shq(argsJson));

0 commit comments

Comments
 (0)