Skip to content
Closed
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
29 changes: 29 additions & 0 deletions src/toolchain/registry.cppm
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,35 @@ parse_toolchain_spec(std::string compilerArg,
"supported alias like mingw / musl-gcc)", compilerArg));
}

// `@system` means "whatever this machine has", and it is deliberately
// available for MSVC ONLY.
//
// xlings depends on the host as little as it can: a toolchain comes from
// a payload, which is what makes "the manifest says 14.44.35207" true on
// every machine instead of on the one that happened to have it. Offering
// `gcc@system` would invite the uncertainty back in, and the alternative
// is one command away.
//
// MSVC is the exception because Windows is: Visual Studio is frequently
// already installed and cannot always be redistributed, so refusing to
// use it would mean refusing to build. That is a platform fact, not a
// general capability, so it is not generalised.
//
// Rejected here rather than left unimplemented: an unimplemented spelling
// fails somewhere further in with a message about something else.
if (norm->version == "system" && norm->family != "msvc") {
return std::unexpected(std::format(
"'{}@system' is not a thing — mcpp does not build with the "
"machine's own {}.\n"
" A toolchain comes from a payload, so a manifest means the same "
"thing on every machine.\n"
" Name a version instead: `{}@<version>` "
"(`mcpp toolchain list` shows what is available).\n"
" Only `msvc@system` exists, because Visual Studio cannot always "
"be redistributed.",
norm->family, norm->family, norm->family));
}

ToolchainSpec spec;
if (norm->family == "llvm") spec.family = Family::Llvm;
else if (norm->family == "msvc") spec.family = Family::Msvc;
Expand Down
24 changes: 24 additions & 0 deletions tests/unit/test_toolchain_msvc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,30 @@ TEST(MsvcSpec, SystemOriginIsTheUnversionedSpec) {
EXPECT_FALSE(is_system_toolchain(*gcc));
}

TEST(MsvcSpec, OnlyMsvcHasASystemOrigin) {
// xlings depends on the host as little as it can: a toolchain comes from
// a payload, which is what makes "the manifest says 14.44.35207" true on
// every machine rather than on the one that happened to have it.
// `gcc@system` would invite that uncertainty back.
//
// MSVC is the exception because Windows is — Visual Studio is often
// already installed and cannot always be redistributed. A platform fact,
// not a general capability, so it is not generalised.
//
// Rejected rather than merely unimplemented: an unimplemented spelling
// fails later, somewhere else, with a message about something else.
for (auto s : {"gcc@system", "llvm@system", "clang@system"}) {
auto spec = parse_toolchain_spec(s);
ASSERT_FALSE(spec.has_value()) << s << " was accepted";
// The message has to say what to do instead, or it is just a refusal.
EXPECT_NE(spec.error().find("@<version>"), std::string::npos)
<< s << ": " << spec.error();
EXPECT_NE(spec.error().find("msvc@system"), std::string::npos)
<< s << ": " << spec.error();
}
EXPECT_TRUE(parse_toolchain_spec("msvc@system").has_value());
}

TEST(MsvcSpec, ToolsetVersionIsAManagedPayloadNotASystemSpec) {
// The defect this closes: EVERY msvc spec used to be a system spec, so a
// manifest could name a toolset and silently get whatever the machine
Expand Down
Loading