Skip to content

Commit 9bdb284

Browse files
committed
fix(flags): -fPIC is a property of the target format, not of the dialect
Windows CI, once the packer stopped swallowing the compiler's output: error: unsupported option '-fPIC' for target 'x86_64-pc-windows-msvc' every MSVC-ABI shared build died in clang-scan-deps before compiling anything. The comment beside the condition already said the right thing — "PE code is position independent by design" — and the condition tested the DIALECT: `!isMsvcDialect`. Windows' default toolchain is clang, which speaks the GNU dialect while targeting the MSVC ABI, so the flag went out anyway. Same shape as the shared-library guard this PR replaced: asking which COMPILER when the question is which TARGET. It keys on the target format now. Unreachable until this PR, because `kind = "shared"` was refused on that ABI — the refusal was hiding an untested path, which is what refusals do. 257 pins the absence on every Linux CI pass through mingw-cross rather than only on Windows: the flag is equally meaningless for a PE target whichever compiler emits it, and GCC merely ignores it where clang refuses.
1 parent c8ac60a commit 9bdb284

2 files changed

Lines changed: 34 additions & 2 deletions

File tree

src/build/flags.cppm

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import mcpp.platform.runtime_search;
2121
import mcpp.toolchain.clang;
2222
import mcpp.toolchain.detect;
2323
import mcpp.toolchain.dialect;
24+
import mcpp.toolchain.triple;
2425
import mcpp.toolchain.hostflags;
2526
import mcpp.toolchain.linkmodel;
2627
import mcpp.toolchain.model;
@@ -411,15 +412,31 @@ CompileFlags compute_flags(const BuildPlan& plan) {
411412

412413
const bool isMsvcDialect = (d.id == "msvc");
413414

414-
// PIC? (GNU-only concept; PE code is position independent by design.)
415+
// PIC is a GNU concept and a property of the TARGET FORMAT: PE code is
416+
// position independent by design (base relocations), and clang rejects the
417+
// flag outright — `unsupported option '-fPIC' for target
418+
// 'x86_64-pc-windows-msvc'`.
419+
//
420+
// ⚠️ The condition used to be `!isMsvcDialect`, i.e. the DIALECT. Windows'
421+
// default toolchain is clang, which speaks the GNU dialect while targeting
422+
// the MSVC ABI, so `-fPIC` was emitted and every MSVC-ABI shared build died
423+
// in clang-scan-deps before compiling anything. It was unreachable while
424+
// `kind = "shared"` was refused on that ABI; allowing it is what surfaced
425+
// this. Same shape as the shared-library guard itself: asking which
426+
// COMPILER when the question is which TARGET.
427+
const bool peTarget = [&] {
428+
if (auto t = mcpp::toolchain::triple::parse(plan.toolchain.targetTriple))
429+
return t->is_pe();
430+
return bool(mcpp::platform::is_windows);
431+
}();
415432
bool need_pic = false;
416433
for (auto& lu : plan.linkUnits) {
417434
if (lu.kind == LinkUnit::SharedLibrary) {
418435
need_pic = true;
419436
break;
420437
}
421438
}
422-
std::string pic_flag = (need_pic && !isMsvcDialect) ? " -fPIC" : "";
439+
std::string pic_flag = (need_pic && !isMsvcDialect && !peTarget) ? " -fPIC" : "";
423440

424441
// Include dirs — this is the TYPED PATH channel (bare paths from the
425442
// manifest; the dialect prefix is applied here at emission), not the

tests/e2e/257_shared_library_pe.sh

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,21 @@ imp="$(find target -name 'libmathkit.dll.a' | head -1)"
6666
echo "FAIL: no import library. The .dll alone is a library only mingw's ld"
6767
echo " will link, so the package would be unusable everywhere else."
6868
exit 1; }
69+
# ⚠️ And no `-fPIC`. PE code is position independent by design, and clang
70+
# targeting the MSVC ABI REJECTS the flag — `unsupported option '-fPIC' for
71+
# target 'x86_64-pc-windows-msvc'` — killing the build in clang-scan-deps before
72+
# anything compiles. The condition used to be the DIALECT rather than the target,
73+
# and Windows' default toolchain is clang, which speaks the GNU dialect while
74+
# targeting MSVC. Asserted here rather than only on Windows because this runs on
75+
# every Linux CI pass through mingw-cross, and the flag is equally meaningless
76+
# for a PE target whichever compiler emits it.
77+
nj_pic="$(find target -name build.ninja | head -1)"
78+
grep -q '\-fPIC' "$nj_pic" && {
79+
grep -n 'fPIC' "$nj_pic" | head -3
80+
echo "FAIL: -fPIC on a PE target. It means nothing here, and clang targeting"
81+
echo " the MSVC ABI refuses it outright."
82+
exit 1; }
83+
6984
# It is a declared output of the link edge, not a side effect ninja knows nothing
7085
# about — otherwise the consumer that links it has no producer and ninja stops
7186
# with 'no known rule to make it'.

0 commit comments

Comments
 (0)