Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Empty file added binDir
Empty file.
6 changes: 5 additions & 1 deletion src/toolchain/lifecycle.cppm
Original file line number Diff line number Diff line change
Expand Up @@ -285,7 +285,11 @@ export int toolchain_list(const mcpp::config::GlobalConfig& cfg) {
s.version = vEntry.path().filename().string();
s.target = id->target;
auto pkg = mcpp::toolchain::to_xim_package(s);
auto bin = mcpp::toolchain::toolchain_frontend(vEntry.path() / "bin", pkg);
// From the payload ROOT, not `root/bin`: msvc keeps cl.exe
// four levels deeper, and asking for `root/bin` skipped every
// installed toolset silently.
auto bin = mcpp::toolchain::payload_frontend(vEntry.path(), pkg,
id->family);
if (bin.empty()) continue;
payloads.push_back({ *id, s.version, bin });
}
Expand Down
31 changes: 31 additions & 0 deletions src/toolchain/registry.cppm
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,23 @@ ToolchainSpec with_resolved_xim_version(const ToolchainSpec& spec,
std::filesystem::path toolchain_frontend(const std::filesystem::path& binDir,
const XimToolchainPackage& pkg);

// The frontend inside an installed payload ROOT — for callers that have the
// root rather than a bin directory.
//
// Most families keep it in `bin/`, and for them this is `toolchain_frontend`
// on `root/bin`. MSVC does not: cl.exe sits four levels deeper, under
// `VC/Tools/MSVC/<version>/bin/Host<h>/<arch>/`.
//
// It exists because that difference had to be known in three places and was
// only handled in two. The third — `toolchain list`'s enumeration — asked
// `root/bin`, got nothing, and `continue`d, so an msvc toolset installed
// perfectly well and then did not appear in the list. Empty = no frontend
// here, which is the caller's cue to skip; a wrong LAYOUT and a missing
// PAYLOAD had been reporting the same way.
std::filesystem::path payload_frontend(const std::filesystem::path& payloadRoot,
const XimToolchainPackage& pkg,
Family family);

// Reverse mapping: an installed `xim-x-<name>` payload directory back to its
// (family, target) identity. nullopt for non-toolchain xpkgs (ninja, glibc,
// python, …) — list/doctor use this to filter what they enumerate.
Expand Down Expand Up @@ -357,6 +374,20 @@ std::filesystem::path toolchain_frontend(const std::filesystem::path& binDir,
return {};
}

std::filesystem::path payload_frontend(const std::filesystem::path& payloadRoot,
const XimToolchainPackage& pkg,
Family family) {
if (family == Family::Msvc) {
// Same resolution the install and build paths use, so the three
// cannot disagree about where an msvc payload keeps its compiler.
if (auto inst = mcpp::toolchain::msvc::installation_at(payloadRoot,
pkg.ximVersion))
return inst->clPath;
return {};
}
return toolchain_frontend(payloadRoot / "bin", pkg);
}

std::optional<PayloadIdentity> identify_xim_payload(std::string_view ximDirName) {
if (ximDirName == "gcc")
return PayloadIdentity{ Family::Gcc, {} };
Expand Down
28 changes: 28 additions & 0 deletions tests/unit/test_toolchain_msvc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,34 @@ TEST(MsvcManaged, VersionFallsBackToTheDeclaredOneWhenTheBannerCannotBeRead) {
EXPECT_EQ(inst->display_version(), "14.52.36629");
}

TEST(MsvcManaged, PayloadFrontendFindsClWhereMsvcActuallyKeepsIt) {
// The defect this pins: `toolchain list` asked `toolchain_frontend(root /
// "bin", …)`, got nothing, and skipped the row -- so an msvc toolset
// installed correctly and then did not appear anywhere. Three places need
// to know that cl.exe is four levels deeper than `bin/`; two knew.
FakeToolset t{"frontend"};
t.add_toolset("14.44.35207");

auto spec = parse_toolchain_spec("msvc@14.44.35207");
ASSERT_TRUE(spec.has_value());
auto pkg = to_xim_package(*spec);

auto found = payload_frontend(t.root, pkg, Family::Msvc);
ASSERT_FALSE(found.empty()) << "payload_frontend found no cl.exe under " << t.root;
EXPECT_EQ(found.filename(), "cl.exe");

// The `bin/`-shaped question is the one that used to be asked, and it
// still answers nothing here — which is exactly why it was the wrong
// question rather than a broken implementation.
EXPECT_TRUE(toolchain_frontend(t.root / "bin", pkg).empty());

// A root with no toolset at that version stays empty rather than
// returning a path that does not exist.
EXPECT_TRUE(payload_frontend(t.root,
to_xim_package(*parse_toolchain_spec("msvc@14.52.36629")),
Family::Msvc).empty());
}

// ─── Windows SDK discovery ───────────────────────────────────────────────

TEST(MsvcSdk, WindowsSdkDirBeatsTheHardcodedPaths) {
Expand Down
Loading