|
| 1 | +# openkal-llvm-runtime |
| 2 | + |
| 3 | +LLVM's C++ runtime — libc++, libc++abi and libunwind — configured for |
| 4 | +[openkal-musl](https://github.com/mcpplibs/openkal-musl) rather than for a host |
| 5 | +C library. |
| 6 | + |
| 7 | +```toml |
| 8 | +[dependencies] |
| 9 | +openkal-llvm-runtime = "0.1.0" |
| 10 | +``` |
| 11 | + |
| 12 | +A C++ standard library is not portable in the way a program is. It is |
| 13 | +*configured* for one C library and compiled against that library's headers, and |
| 14 | +a build that merely finds the headers is not the same thing. The criterion is |
| 15 | +the one openkal keeps returning to: **whether an implementation has been |
| 16 | +configured for this target**, not whether its headers can be found. |
| 17 | + |
| 18 | +## What is vendored, and what is not |
| 19 | + |
| 20 | +| | | |
| 21 | +| --- | --- | |
| 22 | +| **vendored** | `libcxx`, `libcxxabi`, `libunwind`, and `compiler-rt`'s builtins, at the revision the toolchain itself was built from (`llvm/UPSTREAM-REV`) | |
| 23 | +| **not vendored, not changed** | the compiler and the linker | |
| 24 | + |
| 25 | +The compiler takes a target triple and emits for it; openkal changes no |
| 26 | +architecture and no object format, so it needs nothing. What has to be |
| 27 | +configured is what travels with the program, and that is what is here. |
| 28 | + |
| 29 | +Building it takes minutes rather than hours, because these are the pieces LLVM |
| 30 | +itself builds separately from the compiler. |
| 31 | + |
| 32 | +## The one thing the configuration decides |
| 33 | + |
| 34 | +`llvm-generated/generic/__config_site` is libc++'s configure product. Two |
| 35 | +positions in it carry the whole of what makes this package different from the |
| 36 | +one a toolchain ships: |
| 37 | + |
| 38 | +```c |
| 39 | +#define _LIBCPP_HAS_MUSL_LIBC 1 /* the C library beneath is musl's */ |
| 40 | +#define _LIBCPP_HAS_RANDOM_DEVICE 0 /* openkal has no source of entropy */ |
| 41 | +``` |
| 42 | +
|
| 43 | +The first was measured rather than assumed. With it at `0` — the value a |
| 44 | +toolchain configured for glibc ships — a translation unit that includes |
| 45 | +`<vector>` fails with twenty errors, of which the first names the cause: |
| 46 | +
|
| 47 | +``` |
| 48 | +__locale:439: error: unknown rune table for this platform |
| 49 | + -- do you mean to define _LIBCPP_PROVIDES_DEFAULT_RUNE_TABLE? |
| 50 | +``` |
| 51 | + |
| 52 | +With it at `1`, none. The second follows from openkal reporting `ENOSYS` for |
| 53 | +entropy: `std::random_device` is not built, and a program that names it is told |
| 54 | +by the linker. |
| 55 | + |
| 56 | +## What a program gets |
| 57 | + |
| 58 | +`examples/cxx` asserts it, and every assertion is written so that it can fail: |
| 59 | + |
| 60 | +- containers and algorithms — `std::vector` sorted by `std::sort` |
| 61 | +- strings — built and searched |
| 62 | +- values returned through several frames |
| 63 | +- **an exception thrown across three frames and caught** |
| 64 | +- **a destructor run while the stack is unwound** |
| 65 | + |
| 66 | +`examples/import-std` asserts the other half: `import std;` — the module, not the |
| 67 | +headers — with `std::ranges::sort` and `std::println`. |
| 68 | + |
| 69 | +## ⚠️ The observation a build cannot make |
| 70 | + |
| 71 | +The last two assertions are the package. Everything else here a runtime that was |
| 72 | +linked but never worked would also satisfy. |
| 73 | + |
| 74 | +This is not a precaution. While this package was written, the example printed its |
| 75 | +first line and then |
| 76 | + |
| 77 | +``` |
| 78 | +libc++abi: terminating due to uncaught exception of type std::runtime_error |
| 79 | +``` |
| 80 | + |
| 81 | +with `_Unwind_Backtrace` walking **zero frames**, and with the compile, the link, |
| 82 | +and every path that does not throw green. Nothing in that report named the |
| 83 | +cause, and the cause was two layers down: openkal-musl's replaced |
| 84 | +`__libc_start_main` does not read the auxiliary vector, so `dl_iterate_phdr` |
| 85 | +answered with one object having **no program headers** — and the unwinder, |
| 86 | +looking there for `PT_GNU_EH_FRAME`, concluded the program had no frame |
| 87 | +descriptions rather than that it had not been told. openkal-musl now answers |
| 88 | +that enquiry from `__ehdr_start`. |
| 89 | + |
| 90 | +A package that had only ever been built would have shipped that. |
| 91 | + |
| 92 | +## Not supported |
| 93 | + |
| 94 | +- **the sanitizers.** compiler-rt's sanitizers depend on a host's internals — |
| 95 | + memory layout, interceptors, symbolisation — and are outside this package. |
| 96 | +- **`std::random_device`**, for the reason above. |
| 97 | + |
| 98 | +## Licence |
| 99 | + |
| 100 | +The port is Apache-2.0. The vendored sources under `llvm/` are Apache-2.0 with |
| 101 | +LLVM exceptions and are unchanged; `llvm/LICENSE.TXT` is theirs. |
0 commit comments