Skip to content

Commit 0c96978

Browse files
committed
feat(toolchain): surface the windows-hosted linux cross in doctor and docs
doctor gains the mirror of its existing mingw probe: on a Windows host it now also reports whether the linux-musl cross payload is installed. Same shape, same optional-not-an-error wording, and it derives the package name the same way to_xim_package() does (`<triple>-gcc`) so the two cannot disagree. docs/03-toolchains.md gains the section this feature is for, written as the mirror of "Windows PE via MinGW-w64": the command is spelled identically on both hosts because cross is not a name in mcpp, just host != target. It also states the two limits explicitly rather than leaving users to discover them — linux-gnu from Windows is unsupported (glibc needs the sysroot payloads, which are Linux-only), and cross-arch from Windows is unsupported (the canadian-cross payload is built per host arch).
1 parent 4a2c1a8 commit 0c96978

2 files changed

Lines changed: 60 additions & 0 deletions

File tree

docs/03-toolchains.md

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,41 @@ windows = "gcc@16" # gcc family on Windows = MinGW-w64
158158
# legacy value "mingw@16.1.0" keeps working
159159
```
160160

161+
## Linux ELF from Windows (`x86_64-linux-musl`, no WSL required)
162+
163+
The mirror of the section above: a Windows machine producing a **fully static
164+
Linux binary**, with no WSL, no container, and nothing installed system-wide.
165+
166+
```bash
167+
mcpp build --target x86_64-linux-musl # from Windows OR Linux
168+
```
169+
170+
The command is spelled *identically* on both hosts, because "cross" is not a
171+
name in mcpp — it is just the relation `host ≠ target`. Which payload serves
172+
the target is resolved automatically: a Linux x86_64 host installs the native
173+
`musl-gcc`; a Windows host installs a **canadian-cross** GCC
174+
(built `x86_64-linux-gnu` → runs on `x86_64-w64-mingw32` → emits
175+
`x86_64-linux-musl`). Both are GCC 16.1.0 and both ship `bits/std.cc`, so
176+
`import std` works the same either way.
177+
178+
The output is a fully static ELF with no `PT_INTERP` — it runs on any Linux
179+
distribution regardless of its libc, which is exactly why musl is the target
180+
that got wired up first:
181+
182+
```console
183+
$ file mcpp
184+
mcpp: ELF 64-bit LSB executable, x86-64, statically linked, stripped
185+
```
186+
187+
`x86_64-linux-gnu` from Windows is **not** supported: a glibc target needs the
188+
`xim:glibc` and `xim:linux-headers` sysroot payloads, which are published for
189+
Linux hosts only. The musl target is self-contained and needs neither.
190+
191+
Cross-arch from Windows (e.g. `aarch64-linux-musl`) is not available either —
192+
the canadian-cross payload is built per host arch. `mcpp toolchain list` shows
193+
only what the current host can actually install, so if a target is missing from
194+
the Targets block, that host genuinely cannot serve it.
195+
161196
## MSVC (System Toolchain, Windows)
162197

163198
MSVC is different from every other toolchain mcpp manages: it is a **system

src/doctor.cppm

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,31 @@ export int doctor_report() {
147147
if (!any)
148148
ok("mingw not installed (optional — `mcpp toolchain install mingw 16.1.0`)");
149149
}
150+
151+
// The other direction: a windows-hosted cross toolchain that produces
152+
// Linux ELF. Same shape as the mingw probe above; the package is named
153+
// by triple, matching to_xim_package()'s `<triple>-gcc`.
154+
{
155+
auto triple = std::string(mcpp::platform::host_arch) + "-linux-musl";
156+
auto label = std::format("linux cross (xim:{}-gcc)", triple);
157+
mcpp::ui::status("Checking", label);
158+
auto pkgs = mcpp::home::root() / "registry" / "data" / "xpkgs"
159+
/ std::format("xim-x-{}-gcc", triple);
160+
std::error_code ec;
161+
bool any = false;
162+
if (std::filesystem::exists(pkgs, ec)) {
163+
for (auto& v : std::filesystem::directory_iterator(pkgs, ec)) {
164+
if (!v.is_directory(ec)) continue;
165+
ok(std::format("{} {} installed",
166+
triple, v.path().filename().string()));
167+
any = true;
168+
}
169+
}
170+
if (!any)
171+
ok(std::format("{} not installed (optional — "
172+
"`mcpp toolchain install gcc 16.1.0 --target {}`)",
173+
triple, triple));
174+
}
150175
}
151176

152177
mcpp::ui::status("Checking", "std module");

0 commit comments

Comments
 (0)