Skip to content

Commit 2f88075

Browse files
committed
fix: Windows xlings command execution — use _putenv_s instead of cmd.exe set
cmd.exe `set` in compound &&-chains is unreliable. Instead, set XLINGS_HOME/XLINGS_PROJECT_DIR/PATH directly in the process environment via _putenv_s (inherited by popen/system children). Also: - Skip patchelf bootstrap on Windows (ELF-only, like macOS) - Create sandbox home dir before xlings self init
1 parent e2eea3d commit 2f88075

2 files changed

Lines changed: 24 additions & 25 deletions

File tree

src/config.cppm

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -564,8 +564,8 @@ std::expected<GlobalConfig, ConfigError> load_or_init(
564564
// upstream (see docs/short-term-vs-long-track plan).
565565
ensure_sandbox_xlings_binary(cfg, quiet);
566566
ensure_sandbox_init(cfg, quiet);
567-
#if !defined(__APPLE__)
568-
// patchelf is ELF-only; macOS uses Mach-O and does not need it.
567+
#if !defined(__APPLE__) && !defined(_WIN32)
568+
// patchelf is ELF-only; macOS uses Mach-O and Windows uses PE.
569569
ensure_sandbox_patchelf(cfg, quiet, onBootstrapProgress);
570570
#endif
571571
ensure_sandbox_ninja(cfg, quiet, onBootstrapProgress);

src/xlings.cppm

Lines changed: 22 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ module;
1111
#include <cstdio>
1212
#include <cstdlib>
1313
#if defined(_WIN32)
14+
#include <stdlib.h> // _putenv_s
1415
#define popen _popen
1516
#define pclose _pclose
1617
#endif
@@ -424,22 +425,18 @@ std::filesystem::path sandbox_init_marker(const Env& env) {
424425
std::string build_command_prefix(const Env& env) {
425426
auto xvmBin = paths::sandbox_bin(env).string();
426427
#if defined(_WIN32)
427-
// Windows: use cmd.exe set + call semantics.
428-
if (env.projectDir.empty()) {
429-
return std::format(
430-
"cd /d {} && set \"PATH={};%PATH%\" && set \"XLINGS_HOME={}\" && set \"XLINGS_PROJECT_DIR=\" && {}",
431-
shq(env.home.string()),
432-
xvmBin,
433-
env.home.string(),
434-
shq(env.binary.string()));
428+
// Windows: set environment variables via the process environment
429+
// (cmd.exe `set` in compound &&-chains is unreliable) then invoke
430+
// xlings directly. _putenv_s is inherited by popen/system child.
431+
_putenv_s("XLINGS_HOME", env.home.string().c_str());
432+
_putenv_s("XLINGS_PROJECT_DIR",
433+
env.projectDir.empty() ? "" : env.projectDir.string().c_str());
434+
// Prepend sandbox bin to PATH
435+
{
436+
std::string newPath = xvmBin + ";" + (std::getenv("PATH") ? std::getenv("PATH") : "");
437+
_putenv_s("PATH", newPath.c_str());
435438
}
436-
return std::format(
437-
"cd /d {} && set \"PATH={};%PATH%\" && set \"XLINGS_HOME={}\" && set \"XLINGS_PROJECT_DIR={}\" && {}",
438-
shq(env.home.string()),
439-
xvmBin,
440-
env.home.string(),
441-
env.projectDir.string(),
442-
shq(env.binary.string()));
439+
return shq(env.binary.string());
443440
#else
444441
if (env.projectDir.empty()) {
445442
// Global mode: unset XLINGS_PROJECT_DIR (existing behavior).
@@ -663,10 +660,9 @@ int install_with_progress(const Env& env, std::string_view target,
663660
R"({{"targets":["{}"],"yes":true}})", target);
664661

665662
#if defined(_WIN32)
666-
auto cmd = std::format(
667-
"cd /d {} && set \"XLINGS_PROJECT_DIR=\" && set \"XLINGS_HOME={}\" && {} interface install_packages --args {} 2>nul",
668-
shq(env.home.string()),
669-
env.home.string(),
663+
_putenv_s("XLINGS_HOME", env.home.string().c_str());
664+
_putenv_s("XLINGS_PROJECT_DIR", "");
665+
auto cmd = std::format("{} interface install_packages --args {} 2>nul",
670666
shq(env.binary.string()),
671667
shq(argsJson));
672668
#else
@@ -787,13 +783,16 @@ void ensure_init(const Env& env, bool quiet) {
787783
auto marker = paths::sandbox_init_marker(env);
788784
if (std::filesystem::exists(marker)) return;
789785

786+
// Ensure the home directory exists before cd'ing into it.
787+
std::error_code ec;
788+
std::filesystem::create_directories(env.home, ec);
789+
790790
if (!quiet)
791791
print_status("Initialize", "mcpp sandbox layout (one-time)");
792792
#if defined(_WIN32)
793-
auto cmd = std::format(
794-
"cd /d {} && set \"XLINGS_PROJECT_DIR=\" && set \"XLINGS_HOME={}\" && {} self init >nul 2>&1",
795-
shq(env.home.string()),
796-
env.home.string(),
793+
_putenv_s("XLINGS_HOME", env.home.string().c_str());
794+
_putenv_s("XLINGS_PROJECT_DIR", "");
795+
auto cmd = std::format("{} self init >nul 2>&1",
797796
shq(env.binary.string()));
798797
#else
799798
auto cmd = std::format(

0 commit comments

Comments
 (0)