From 0838fa8ebf8d9664bd585009ddf835c78d6cd922 Mon Sep 17 00:00:00 2001 From: Sunrisepeak Date: Fri, 30 Oct 2026 05:14:26 +0900 Subject: [PATCH] 0.16.9 --- the ok image exports __cxa_thread_atexit; openkal-musl 0.22.9 Co-authored-by: speak-agent <248744407+speak-agent@users.noreply.github.com> --- README.md | 2 +- examples/image-cxx/mcpp.toml | 6 +++--- examples/image-cxx/src/main.cpp | 8 ++++++++ llvm/libcxxabi/src/cxa_thread_atexit.cpp | 16 ++++++++++++---- mcpp.toml | 16 ++++++++++++++-- 5 files changed, 38 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 288b7a86..63f41d48 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ C library. ```toml [dependencies] -openkal-llvm-runtime = "0.16.8" +openkal-llvm-runtime = "0.16.9" ``` > **Engine floor (mcpp 2026.9.20.1):** this version of this package pins diff --git a/examples/image-cxx/mcpp.toml b/examples/image-cxx/mcpp.toml index fc97e657..85ca092e 100644 --- a/examples/image-cxx/mcpp.toml +++ b/examples/image-cxx/mcpp.toml @@ -1,7 +1,7 @@ # The C++ runtime inside an ok image (target `-openkal', openkal SPEC # clause 12): one image per architecture, run through okrun on Linux, macOS and -# Windows. `import std', an exception, a thread, a thread-local variable and the -# containers, above openkal-musl's image form. +# Windows. `import std', an exception, a thread, thread-local variables (one +# with a destructor) and the containers, above openkal-musl's image form. [package] name = "image-cxx" version = "0.1.0" @@ -10,7 +10,7 @@ version = "0.1.0" openkal-llvm-runtime = { path = "../.." } [build-dependencies] -openkal-tools = { version = "0.1.3", tools = ["okld", "okrun"] } +openkal-tools = { version = "0.1.4", tools = ["okld", "okrun"] } [targets.image-cxx] kind = "bin" diff --git a/examples/image-cxx/src/main.cpp b/examples/image-cxx/src/main.cpp index fa9186f5..0beae9cb 100644 --- a/examples/image-cxx/src/main.cpp +++ b/examples/image-cxx/src/main.cpp @@ -9,6 +9,8 @@ void check(bool held, std::string_view what) { if (!held) ++failures; } thread_local int tl = 7; +std::atomic tls_dtor_ran{0}; +struct TlsProbe { int v; ~TlsProbe() { tls_dtor_ran.store(v); } }; } int main(int argc, char** argv) { @@ -24,6 +26,12 @@ int main(int argc, char** argv) { t.join(); check(seen == 7 && tl == 7, "a thread has its own thread-local variable"); + // A thread_local with a destructor needs `__cxa_thread_atexit`, which the + // image's runtime provides; the image would not link without it. + std::thread d([] { thread_local TlsProbe p{7}; (void)p; }); + d.join(); + check(tls_dtor_ran.load() == 7, "a thread_local's destructor runs when its thread ends"); + std::map m{{"a", 1}, {"b", 2}}; std::vector v(100); std::iota(v.begin(), v.end(), 1); diff --git a/llvm/libcxxabi/src/cxa_thread_atexit.cpp b/llvm/libcxxabi/src/cxa_thread_atexit.cpp index 72f07741..d5b8e916 100644 --- a/llvm/libcxxabi/src/cxa_thread_atexit.cpp +++ b/llvm/libcxxabi/src/cxa_thread_atexit.cpp @@ -179,14 +179,19 @@ namespace { // // THE FALLBACK BELOW WAS ALREADY COMPLETE; only the export was missing. What // was NOT complete is where it kept its list --- see `run_dtors` above. +// +// THE OK IMAGE IS THE FOURTH SUCH TARGET. Its triple names no operating system, +// so the guard reads `OPENKAL_TARGET_IMAGE`, which `mcpp.toml` states for +// `cfg(os = "openkal")` as it states `OPENKAL_TARGET_WINDOWS` for PE. #if defined(__linux__) || defined(__Fuchsia__) \ - || defined(OPENKAL_TARGET_WINDOWS) || defined(__APPLE__) + || defined(OPENKAL_TARGET_WINDOWS) || defined(OPENKAL_TARGET_IMAGE) \ + || defined(__APPLE__) extern "C" { _LIBCXXABI_FUNC_VIS int __cxa_thread_atexit(Dtor dtor, void* obj, void* dso_symbol) throw() { #ifdef HAVE___CXA_THREAD_ATEXIT_IMPL return __cxa_thread_atexit_impl(dtor, obj, dso_symbol); -#elif defined(__APPLE__) +#elif defined(__APPLE__) || defined(OPENKAL_TARGET_IMAGE) // NO WEAK PROBE ON MACH-O, AND THE REASON IS THE OBJECT FORMAT. // // The `else` branch below declares `__cxa_thread_atexit_impl` weak and @@ -198,7 +203,10 @@ extern "C" { // ld64.lld: error: undefined symbol: __cxa_thread_atexit_impl // // The test is also pointless here: what would define that symbol is - // libSystem, and libSystem is what this stack replaces. + // libSystem, and libSystem is what this stack replaces. An ok image takes + // the same branch: nothing beneath it defines the symbol either, and an + // image may import nothing but `kal_*`, which an unresolved weak reference + // would put in question. (void)dso_symbol; return register_dtor(dtor, obj); #else @@ -229,5 +237,5 @@ extern "C" { #endif } // extern "C" -#endif // defined(__linux__) || defined(__Fuchsia__) +#endif // the targets that export __cxa_thread_atexit } // namespace __cxxabiv1 diff --git a/mcpp.toml b/mcpp.toml index 78f2ee4e..4f9e5719 100644 --- a/mcpp.toml +++ b/mcpp.toml @@ -1,7 +1,7 @@ [package] namespace = "mcpplibs" name = "openkal-llvm-runtime" -version = "0.16.8" +version = "0.16.9" description = "LLVM's C++ runtime libraries — libc++, libc++abi and libunwind — configured for openkal-musl rather than for a host C library." license = "Apache-2.0" authors = ["mcpplibs"] @@ -220,7 +220,7 @@ cflags = ["-DDISABLE_AARCH64_FMV=1"] # runtime itself (`mcpp:compiler-runtime=compiler-rt' above), and on an ok image # (`-openkal') that feature would bring a second supplier of the same layer # --- which a build refuses rather than picks between. -openkal-musl = { version = "0.22.8", default-features = false, features = ["posix"] } +openkal-musl = { version = "0.22.9", default-features = false, features = ["posix"] } [build] @@ -523,6 +523,18 @@ sources = [ "!llvm/compiler-rt/lib/builtins/*xc3.c", ] +[target.'cfg(os = "openkal")'.build] +# WHICH TARGET THIS IS, FOR THE ONE FILE THAT MUST KNOW IT IS AN OK IMAGE. +# +# An ok image's triple is `-unknown-none-elf`: no `__linux__`, no +# `__APPLE__`, nothing a source can read the target off. `cxa_thread_atexit.cpp` +# exports `__cxa_thread_atexit` on the targets where no other runtime does, and +# without this define the ok image was not one of them: every image holding a +# `thread_local` with a destructor was refused by `okld check` for the undefined +# symbol (measured building clangd as an ok image, 2026-10-29). +cflags = ["-DOPENKAL_TARGET_IMAGE=1"] +cxxflags = ["-DOPENKAL_TARGET_IMAGE=1"] + [target.'cfg(windows)'.build] # WHICH TARGET THIS IS, STATED HERE RATHER THAN READ OFF `_WIN32`. #