Skip to content

Commit 2baa031

Browse files
committed
fix: GCC needs --sysroot for include-fixed, supplement with -isystem
GCC's include-fixed directory contains stdlib.h wrappers that use #include_next to find the sysroot's stdlib.h. This mechanism only works with --sysroot, not standalone -isystem paths. Fix: for GCC, keep --sysroot from probe_sysroot() and supplement with -isystem for linux kernel headers from payload when the probed sysroot is missing them. For Clang, continue using --no-default-config + explicit -isystem (Clang doesn't have include-fixed).
1 parent e9d088e commit 2baa031

2 files changed

Lines changed: 24 additions & 5 deletions

File tree

src/build/flags.cppm

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -135,14 +135,25 @@ CompileFlags compute_flags(const BuildPlan& plan) {
135135
// Linker flags that cfg normally provides
136136
sysroot_flag += " -fuse-ld=lld --rtlib=compiler-rt --unwindlib=libunwind";
137137
f.sysroot = sysroot_flag;
138+
} else if (!plan.toolchain.sysroot.empty()) {
139+
// GCC (or Clang without cfg): use --sysroot from probe.
140+
// GCC requires --sysroot for include-fixed headers (stdlib.h wrapper).
141+
// Supplement with -isystem for linux kernel headers from payload
142+
// if the probed sysroot is missing them.
143+
sysroot_flag = " --sysroot=" + escape_path(plan.toolchain.sysroot);
144+
if (plan.toolchain.payloadPaths && !plan.toolchain.payloadPaths->linuxInclude.empty()) {
145+
auto sysrootLinux = plan.toolchain.sysroot / "usr" / "include" / "linux" / "limits.h";
146+
if (!std::filesystem::exists(sysrootLinux))
147+
sysroot_flag += " -isystem" + escape_path(plan.toolchain.payloadPaths->linuxInclude);
148+
}
149+
f.sysroot = sysroot_flag;
138150
} else if (plan.toolchain.payloadPaths) {
139-
// GCC or Clang without cfg: use payload -isystem paths.
151+
// No sysroot but have payload paths: use -isystem.
140152
auto& pp = *plan.toolchain.payloadPaths;
141153
sysroot_flag += " -isystem" + escape_path(pp.glibcInclude);
142154
if (!pp.linuxInclude.empty())
143155
sysroot_flag += " -isystem" + escape_path(pp.linuxInclude);
144156
f.sysroot = sysroot_flag;
145-
} else if (!plan.toolchain.sysroot.empty()) {
146157
sysroot_flag = " --sysroot=" + escape_path(plan.toolchain.sysroot);
147158
f.sysroot = sysroot_flag;
148159
}

src/toolchain/stdmod.cppm

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -129,13 +129,21 @@ std::expected<StdModule, StdModError> ensure_built(
129129
} else if (!tc.sysroot.empty()) {
130130
sysroot_flag = std::format(" --sysroot='{}'", tc.sysroot.string());
131131
}
132+
} else if (!tc.sysroot.empty()) {
133+
// GCC: use --sysroot (required for include-fixed headers).
134+
// Supplement with -isystem for linux kernel headers from payload
135+
// if the probed sysroot is missing them.
136+
sysroot_flag = std::format(" --sysroot='{}'", tc.sysroot.string());
137+
if (tc.payloadPaths && !tc.payloadPaths->linuxInclude.empty()) {
138+
auto sysrootLinux = tc.sysroot / "usr" / "include" / "linux" / "limits.h";
139+
if (!std::filesystem::exists(sysrootLinux))
140+
sysroot_flag += std::format(" -isystem'{}'", tc.payloadPaths->linuxInclude.string());
141+
}
132142
} else if (tc.payloadPaths) {
133-
// GCC: use payload -isystem paths instead of --sysroot.
143+
// No sysroot: use payload -isystem paths.
134144
sysroot_flag += std::format(" -isystem'{}'", tc.payloadPaths->glibcInclude.string());
135145
if (!tc.payloadPaths->linuxInclude.empty())
136146
sysroot_flag += std::format(" -isystem'{}'", tc.payloadPaths->linuxInclude.string());
137-
} else if (!tc.sysroot.empty()) {
138-
sysroot_flag = std::format(" --sysroot='{}'", tc.sysroot.string());
139147
}
140148

141149
bool std_cached = std::filesystem::exists(sm.bmiPath) && std::filesystem::exists(sm.objectPath);

0 commit comments

Comments
 (0)