Skip to content

Commit 89df206

Browse files
committed
fix(macos): direct archive linking + floor 14.0 (forensics-driven)
CI forensics (3-mode matrix with a std::cout probe) overturned the working theory: - -Wl,-hidden-l under lld resolves like a plain -l and picks the SIBLING DYLIB in the same directory: binaries carried @rpath/libc++.1.dylib with no rpath and died at load (dyld 'Library not loaded' -> Abort trap 6). That — not static destruction — was what killed every gtest/e2e binary. Link the archives by path (the form already verified end-to-end on macos-14/15 in PR #115 run B5), keeping the per-unit split (tests use system -lc++). - The official LLVM-20.1.7-macOS-ARM64 static archives are built for macOS 14 (ld64.lld: 'has version 14.0.0, newer than target minimum of 11.0.0'): claiming a 11.0 floor would be false. Deployment target is now 14.0 everywhere — still fully covering the macOS 14 goal; 11-13 would need a custom libc++ build (follow-up).
1 parent 2055f4b commit 89df206

4 files changed

Lines changed: 18 additions & 16 deletions

File tree

.github/workflows/ci-macos.yml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -340,14 +340,13 @@ jobs:
340340
run_mode() {
341341
echo "=== mode: $1 ==="
342342
shift
343-
"$LLVM/bin/clang++" --no-default-config -std=c++17 -nostdinc++ -isystem "$LLVM/include/c++/v1" --sysroot="$SDK" -mmacosx-version-min=11.0 -fuse-ld=lld /tmp/probe.cpp -o /tmp/probe "$@" 2>&1 | head -5
343+
"$LLVM/bin/clang++" --no-default-config -std=c++17 -nostdinc++ -isystem "$LLVM/include/c++/v1" --sysroot="$SDK" -mmacosx-version-min=14.0 -fuse-ld=lld /tmp/probe.cpp -o /tmp/probe "$@" 2>&1 | head -40
344344
otool -L /tmp/probe | grep -E "libc|probe" | head -4
345345
/tmp/probe
346346
echo "exit=$?"
347347
}
348348
run_mode dylib -stdlib=libc++
349349
run_mode direct -nostdlib++ "$LLVM/lib/libc++.a" "$LLVM/lib/libc++abi.a"
350-
run_mode hidden -nostdlib++ -L"$LLVM/lib" -Wl,-hidden-lc++ -Wl,-hidden-lc++abi
351350
exit 0
352351
353352
- name: E2E suite

.github/workflows/release.yml

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -318,13 +318,15 @@ jobs:
318318
319319
- name: Build mcpp from source (two-stage self-host)
320320
env:
321-
# macOS min-version support: target the first arm64 macOS so the
322-
# release runs on 11.0+ instead of only the runner's OS. Needs
321+
# macOS min-version support: target macOS 14 so the release runs
322+
# on 14.0+ instead of only the runner's OS (the official LLVM
323+
# static libc++ archives are built for macOS 14 — going lower
324+
# needs a custom libc++ build, tracked as follow-up). Needs
323325
# static LLVM libc++ — the system libc++ on older macOS lacks
324326
# LLVM-20-era C++23 symbols (std::print's __is_posix_terminal
325327
# etc.; minos-14 + dynamic libc++ dies at launch on macos-14 CI).
326328
# See xlings .agents/docs/2026-06-05-macos-min-version-support.md.
327-
MACOSX_DEPLOYMENT_TARGET: '11.0'
329+
MACOSX_DEPLOYMENT_TARGET: '14.0'
328330
run: |
329331
export PATH="$HOME/.xlings/subos/default/bin:$PATH"
330332
export MCPP_VENDORED_XLINGS="$XLINGS_BIN"
@@ -346,10 +348,10 @@ jobs:
346348
test -x "$MCPP_BIN"
347349
file "$MCPP_BIN"
348350
otool -L "$MCPP_BIN"
349-
echo "=== LC_BUILD_VERSION (must be minos 11.0) ==="
351+
echo "=== LC_BUILD_VERSION (must be minos 14.0) ==="
350352
otool -l "$MCPP_BIN" | grep -A4 LC_BUILD_VERSION | head -6
351-
otool -l "$MCPP_BIN" | grep -A4 LC_BUILD_VERSION | grep -q "minos 11.0" \
352-
|| { echo "FAIL: expected minos 11.0"; exit 1; }
353+
otool -l "$MCPP_BIN" | grep -A4 LC_BUILD_VERSION | grep -q "minos 14.0" \
354+
|| { echo "FAIL: expected minos 14.0"; exit 1; }
353355
if otool -L "$MCPP_BIN" | grep -q "libc++"; then
354356
echo "FAIL: still linked against system libc++"; exit 1
355357
fi

docs/05-mcpp-toml.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ cflags = ["-DFOO=1"] # 额外 C 编译参数
9191
cxxflags = ["-DBAR=2"] # 额外 C++ 编译参数(不要放 -std=...)
9292
ldflags = ["-lfoo"] # 额外链接参数
9393
static_stdlib = true # 静态链接 libstdc++(默认 true)
94-
macos_deployment_target = "11.0" # macOS 产物的最低支持系统版本(仅 macOS 生效)
94+
macos_deployment_target = "14.0" # macOS 产物的最低支持系统版本(仅 macOS 生效)
9595
```
9696

9797
`macos_deployment_target` 设定产物 Mach-O 头里的最低系统版本

src/build/flags.cppm

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -378,13 +378,14 @@ CompileFlags compute_flags(const BuildPlan& plan) {
378378
auto libcxxAbiA = libDir / "libc++abi.a";
379379
if (std::filesystem::exists(libcxxA)
380380
&& std::filesystem::exists(libcxxAbiA)) {
381-
// -hidden-l links the ARCHIVE (never the sibling dylib)
382-
// and gives its symbols hidden visibility so the static
383-
// copy can coexist with the system libc++ that libSystem
384-
// pulls in indirectly. Distributable targets only — see
385-
// the field comments in CompileFlags.
386-
f.ldStdlibDefault = " -nostdlib++ -L" + escape_path(libDir)
387-
+ " -Wl,-hidden-lc++ -Wl,-hidden-lc++abi";
381+
// Link the archives BY PATH. (-Wl,-hidden-l looked like
382+
// the canonical choice, but lld resolves it like a plain
383+
// -l and picks the sibling dylib in the same directory —
384+
// the binary then carries @rpath/libc++.1.dylib with no
385+
// rpath and dies at load. Observed on macos CI; path
386+
// form verified end-to-end incl. macos-14.)
387+
f.ldStdlibDefault = " -nostdlib++ " + escape_path(libcxxA)
388+
+ " " + escape_path(libcxxAbiA);
388389
}
389390
}
390391
std::string version_min;

0 commit comments

Comments
 (0)