fix(build): stop disabling libc++ availability annotations - #180
Merged
Conversation
16bit-ykiko
force-pushed
the
fix/libcxx-availability
branch
from
July 25, 2026 05:32
9ed4d1a to
0bbd370
Compare
16bit-ykiko
added a commit
to clice-io/clice
that referenced
this pull request
Jul 25, 2026
) ## Summary Build cleanup: drop a duplicated dependency, pick up an upstream fix, and add a release check for the bug class that motivated that fix. ## Changes - **flatbuffers now comes from kotatsu.** kotatsu already fetches it for its own codec, so clice was fetching and building a second copy of the same library. `flatc` comes from pixi, since kotatsu does not build the schema compiler. - **gcc 15.2.0** in the build environment. - **kotatsu pin bumped, availability workaround deleted.** kotatsu defined `-D_LIBCPP_DISABLE_AVAILABILITY` globally, which made libc++ headers reference dylib-only symbols that a target system's libc++ may not have. clice worked around it by stripping the flag off every kotatsu target. The flag is gone upstream (clice-io/kotatsu#180), so the workaround goes with it. - **New check on packaged binaries.** `scripts/check_artifact_deps.py` reads a packaged binary's dynamic dependencies and fails if any of them resolve into a conda/pixi environment instead of the OS. It runs between packaging and upload, so a violation blocks the upload. ## Why the check exists A macOS artifact once linked conda's `@rpath/libc++.1.dylib`. It ran fine on the build machine, where that environment existed, and died everywhere else — and every test job passed, because they all ran inside that same environment. This turns that class of failure into a packaging-time error instead of a post-release surprise. ## Verification The kotatsu bump was checked against the fetched source rather than the declared pin: a stale `_deps` checkout still carries the old flag and would make removing the workaround look safe when it is not. The check was run against a binary carrying `@rpath/libc++.1.dylib`, against a conda-linked `libstdc++.so.6`, and against a clean packaged binary — plus empty and malformed tool output, to confirm it fails rather than passing silently when it cannot parse what it is given. Linux: 1060 unit, 304 integration, 3 smoke. ## Recorded, not fixed here Auditing the shipped artifacts turned up two portability limits. Both need the prebuilt LLVM rebuilt to fix, so both are recorded as `TODO(prebuilt-respin)` in `cmake/toolchain.cmake` and left for the next toolchain bump to carry, rather than triggering a rebuild on their own. **Windows binaries need the Visual C++ redistributable.** They import `MSVCP140.dll` and `VCRUNTIME140.dll` (x64 also `VCRUNTIME140_1.dll`), which are not part of Windows. This follows from building with `/MD`; `/MT` would make the exe self-contained. The flag cannot be flipped alone — every object embeds `/DEFAULTLIB` and `/FAILIFMISMATCH` directives naming its CRT, so linking a `/MD` prebuilt LLVM into a `/MT` clice is a hard link error. **macOS binaries require macOS 15 or newer.** No `CMAKE_OSX_DEPLOYMENT_TARGET` is set, so the target follows the build machine and the artifact is stamped `minos 15.0`. Lowering it needs the prebuilt built against the same target. Neither is covered by the new check: it reads ELF and Mach-O dependencies, not PE imports and not deployment targets. Extending it is noted in the script. For contrast, the Linux `RUNPATH` pointing into the build machine's pixi environment is *not* a problem: all six `NEEDED` entries are glibc sonames and that environment ships none of them, so the loader finds nothing there and falls through to the system — `ldd` on the build machine itself resolves every entry from `/lib/x86_64-linux-gnu`. The script prints it as a note so it stays visible without failing builds over a path that changes no resolution.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Removes the
-D_LIBCPP_DISABLE_AVAILABILITYmacro from both build systems(CMake and xmake). This macro made libc++ headers bypass the vendor
availability annotations.
Why this is wrong
With availability annotations disabled, libc++ headers emit
externreferences to dylib-only symbols (for example
std::__1::__hash_memory,introduced in libc++ 21) instead of taking the safe inline fallback path.
The consequences:
.tbdstubs), those symbols are undefined and the link fails.
exact libc++ dylib present in the build environment.
Downstream consumers hit this concretely when cross-linking on macOS x64.
The correct approach
If a future API is genuinely gated behind an availability annotation, the
right fix is to raise
CMAKE_OSX_DEPLOYMENT_TARGET(and the equivalentxmake deployment target), not to globally switch the annotations off.
macOS toolchain bump to clang 22.1.8
Removing the macro exposed a separate issue in the macOS CI toolchain:
conda-forge's libc++ 20 headers contain availability attributes (e.g. in
__charconv/from_chars_floating_point.h) written in a form that clang 20cannot parse once annotations are active — every TU that includes
<charconv>fails witherror: expected ')'. The attribute uses anunreachable sentinel version, so no deployment target setting can avoid it.
The clang 22.1.8 + libc++ 22.1.8 combination parses these headers
correctly and takes the inline fallback path with annotations enabled, and
has been verified green on downstream macOS CI. This PR therefore bumps
the
macos-clangpixi environment from 20.1.8 to 22.1.8 (clang, clangxx,lld, llvm-tools, compiler-rt, libcxx) and regenerates the lockfile. The
Linux and Windows toolchains are unchanged.
pixi bump and lockfile churn
The lockfile was regenerated with pixi v0.71.1, which writes the v7 lockfile
format — the v0.61.0 previously pinned in CI cannot read it, so the three
workflows move to v0.71.1 as well.
The v7 format adds per-platform
virtual-packagesrecords and reordersexisting entries, which is what most of the
pixi.lockdiff consists of.The only dependency change in it is the macOS toolchain bump described
above; Linux and Windows resolve to the same packages as before.