Skip to content

Commit a2b18b8

Browse files
committed
feat: ensure sysroot complete by symlinking from payload xpkgs
When GCC's probed sysroot (subos/default) is missing linux kernel headers or glibc headers, symlink them from the payload xpkgs: - linux/, asm/, asm-generic/ ← scode-x-linux-headers xpkg - features.h, bits/, etc. ← xim-x-glibc xpkg This makes mcpp self-sufficient: it uses subos/default as a sysroot directory for GCC's include-fixed mechanism, but actively populates it from payload rather than depending on xlings init completeness. Principle: subos is just a directory layout that mcpp manages. Content comes from xpkgs payloads. Clang doesn't use subos at all (--no-default-config + explicit -isystem from payload).
1 parent 76a694d commit a2b18b8

2 files changed

Lines changed: 49 additions & 1 deletion

File tree

src/toolchain/detect.cppm

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,12 @@ detect(const std::filesystem::path& explicit_compiler) {
8181
// When available, flags are assembled from these paths instead of --sysroot.
8282
tc.payloadPaths = probe_payload_paths(tc.binaryPath);
8383

84+
// For GCC: ensure the probed sysroot has complete headers by symlinking
85+
// missing content (linux kernel headers, glibc) from payload xpkgs.
86+
// This makes mcpp self-sufficient — not dependent on xlings subos init.
87+
if (tc.payloadPaths && !tc.sysroot.empty())
88+
ensure_sysroot_complete(tc.sysroot, *tc.payloadPaths);
89+
8490
return tc;
8591
}
8692

src/toolchain/probe.cppm

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,10 +49,16 @@ probe_sysroot(const std::filesystem::path& compilerBin,
4949

5050
// Probe fine-grained sysroot paths from sibling xpkgs payloads.
5151
// Returns populated PayloadPaths if glibc xpkg found; linux-headers
52-
// may be empty if not available (host /usr/include used as fallback).
52+
// may be empty if not available.
5353
std::optional<PayloadPaths>
5454
probe_payload_paths(const std::filesystem::path& compilerBin);
5555

56+
// Ensure sysroot directory has complete headers by symlinking from
57+
// payload xpkgs. Called when GCC's probed sysroot exists but may
58+
// be missing linux kernel headers or glibc headers.
59+
void ensure_sysroot_complete(const std::filesystem::path& sysroot,
60+
const PayloadPaths& pp);
61+
5662
} // namespace mcpp::toolchain
5763

5864
namespace mcpp::toolchain {
@@ -345,4 +351,40 @@ probe_payload_paths(const std::filesystem::path& compilerBin) {
345351
return pp;
346352
}
347353

354+
void ensure_sysroot_complete(const std::filesystem::path& sysroot,
355+
const PayloadPaths& pp) {
356+
if (sysroot.empty()) return;
357+
358+
auto sysrootInclude = sysroot / "usr" / "include";
359+
if (!std::filesystem::exists(sysrootInclude)) return;
360+
361+
std::error_code ec;
362+
363+
// Ensure linux kernel headers are present in sysroot.
364+
// If missing, symlink from linux-headers payload.
365+
if (!pp.linuxInclude.empty()) {
366+
for (auto dir : {"linux", "asm", "asm-generic"}) {
367+
auto target = sysrootInclude / dir;
368+
auto source = pp.linuxInclude / dir;
369+
if (!std::filesystem::exists(target, ec) && std::filesystem::exists(source, ec)) {
370+
std::filesystem::create_directory_symlink(source, target, ec);
371+
}
372+
}
373+
}
374+
375+
// Ensure glibc headers are present if sysroot is bare.
376+
if (!std::filesystem::exists(sysrootInclude / "features.h", ec)) {
377+
// Symlink individual glibc dirs/files into sysroot.
378+
for (auto& entry : std::filesystem::directory_iterator(pp.glibcInclude, ec)) {
379+
auto target = sysrootInclude / entry.path().filename();
380+
if (!std::filesystem::exists(target, ec)) {
381+
if (entry.is_directory(ec))
382+
std::filesystem::create_directory_symlink(entry.path(), target, ec);
383+
else
384+
std::filesystem::create_symlink(entry.path(), target, ec);
385+
}
386+
}
387+
}
388+
}
389+
348390
} // namespace mcpp::toolchain

0 commit comments

Comments
 (0)