libc++ Configuration
lib/basalt/cpp/config_site is a 71-line C header that pins libc++'s compile-time configuration for SaltyOS.
It is included via -include config_site in every libcxx and libcxxabi compilation, before any standard libcxx header processes its own configuration logic.
The file replaces the upstream libcxx/include/__config_site.in template that LLVM’s CMake build would normally generate.
This page walks through every macro, explains the SaltyOS choice, and lists the user-visible consequences.
File Structure
// __config_site — SaltyOS libc++ compile-time configuration
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
#ifndef _LIBCPP___CONFIG_SITE
#define _LIBCPP___CONFIG_SITE
// ABI versioning
#define _LIBCPP_ABI_VERSION 1
#define _LIBCPP_ABI_NAMESPACE __1
#define _LIBCPP_ABI_FORCE_ITANIUM 1
#define _LIBCPP_ABI_FORCE_MICROSOFT 0
// Threading
#define _LIBCPP_HAS_THREADS 1
#define _LIBCPP_HAS_MONOTONIC_CLOCK 1
#define _LIBCPP_HAS_TERMINAL 0
#define _LIBCPP_HAS_MUSL_LIBC 0
#define _LIBCPP_HAS_THREAD_API_PTHREAD 1
#define _LIBCPP_HAS_THREAD_API_EXTERNAL 0
#define _LIBCPP_HAS_THREAD_API_WIN32 0
#define _LIBCPP_HAS_THREAD_API_C11 0
// Filesystem and random
#define _LIBCPP_HAS_FILESYSTEM 1
#define _LIBCPP_HAS_RANDOM_DEVICE 1
#define _LIBCPP_USING_GETENTROPY
// Locale (C-locale only via SaltyOS backend)
#define _LIBCPP_LOCALE_BACKEND_SALTYOS
#define _LIBCPP_HAS_LOCALIZATION 1
#define _LIBCPP_PROVIDES_DEFAULT_RUNE_TABLE
#define _LIBCPP_HAS_UNICODE 0
#define _LIBCPP_HAS_WIDE_CHARACTERS 1
#define _LIBCPP_HAS_TIME_ZONE_DATABASE 0
// Hardening (off — baremetal)
#define _LIBCPP_HARDENING_MODE_DEFAULT _LIBCPP_HARDENING_MODE_NONE
#define _LIBCPP_ASSERTION_SEMANTIC_DEFAULT _LIBCPP_ASSERTION_SEMANTIC_IGNORE
// Misc
#define _LIBCPP_INSTRUMENTED_WITH_ASAN 0
#define _LIBCPP_HAS_VENDOR_AVAILABILITY_ANNOTATIONS 0
#define _LIBCPP_LIBC_PICOLIBC 0
#define _LIBCPP_LIBC_NEWLIB 0
#define _LIBCPP_LIBC_LLVM_LIBC 0
#define _LIBCPP_PSTL_BACKEND_SERIAL 1
#endif
ABI Versioning
| Macro | Value | Effect |
|---|---|---|
|
1 |
Standard libc++ ABI v1. Compatible with mainstream Linux distributions. |
|
|
Inline namespace for ABI v1 symbols. Mangled into every libc++ symbol so that future ABI changes can coexist. |
|
1 |
Force the Itanium C++ ABI even on platforms where another ABI might be the default. Itanium is the standard on x86_64 and aarch64 Linux/BSD, so this is the safe choice. |
|
0 |
Disabled — basalt does not target the Microsoft Visual C ABI even though it has a Win32 subsystem (which uses MSVC ABI through `kernel32.dll` PE shim, separately from libc). |
Threading
| Macro | Effect |
|---|---|
|
Enable |
|
Enable |
|
Use the POSIX pthread API as the threading backend. The other three (EXTERNAL, WIN32, C11) are 0. |
The pthread backend means libc++'s thread/mutex/condvar are thin wrappers around basaltc’s pthread.rs, which is itself a thin wrapper around trona_posix::pthread::*.
See Threads and Synchronization.
_LIBCPP_HAS_TERMINAL = 0 disables libc's terminal-color output (for assertion messages); SaltyOS does not have a `<termios>`-aware libc output path.
_LIBCPP_HAS_MUSL_LIBC = 0 is correct because SaltyOS uses basaltc, not musl. libc++ has a few musl-specific workarounds (mostly around wchar_t and locale) that this disables.
Filesystem
_LIBCPP_HAS_FILESYSTEM = 1 enables <filesystem> headers, but the runtime support is partial:
-
std::filesystem::path— fully working (pure path string manipulation, no I/O). -
std::filesystem::filesystem_clock— working. -
std::filesystem::filesystem_error— working. -
std::filesystem::directory_entry,directory_iterator,recursive_directory_iterator— not built (the libcxx sourcesdirectory_entry.cpp,directory_iterator.cpp,operations.cppare deliberately excluded from_cxx_srcsinlib/basalt/cpp/meson.build). -
std::filesystem::create_directory,remove,rename, etc. — not built for the same reason.
Programs that include <filesystem> to manipulate path strings (parse, join, normalize) work fine.
Programs that walk a directory tree with directory_iterator will fail at link time with unresolved symbols.
This is a known partial conformance.
The directory walk operations could be enabled by adding the libcxx sources to the build and providing the underlying posix_opendir / posix_readdir calls (which basaltc already exposes), but that work has not been done.
Random Device
_LIBCPP_HAS_RANDOM_DEVICE = 1 enables std::random_device.
_LIBCPP_USING_GETENTROPY selects the getentropy(2) backend rather than reading from /dev/random or /dev/urandom.
The reason: SaltyOS provides getentropy directly through trona_posix::getrandom (which talks to the kernel’s RDRAND/randr source), but does not yet have a /dev/random device file.
Pre-defining _LIBCPP_USING_GETENTROPY ensures libc's random_device implementation picks the right backend on the first try.
Without this, libc's __config chain falls through to "unknown target" and selects /dev/random, which would fail at runtime.
Locale Backend
| Macro | Effect |
|---|---|
|
Custom backend defined under |
|
Enable the |
|
Tells libc++ to use its built-in power-of-two rune table for |
|
Disable the Unicode-aware |
|
Enable |
|
Disable |
The C-locale-only choice is consistent across basaltc and libc++. See Locale, ctype and wchar for the basaltc side.
Hardening
| Macro | Effect |
|---|---|
|
Disable all bounds-checking, debug assertions, and runtime invariant checks in libc++. Programs that index out of bounds in |
|
Make |
The choice prioritizes runtime overhead over safety.
basalt is a "baremetal-style" libc++: small, fast, and trusts the caller.
A future build flag could expose _LIBCPP_HARDENING_MODE_FAST (the upstream default) for debug builds without changing this file — that would require the __assertion_handler to actually do something useful.
Miscellaneous
| Macro | Effect |
|---|---|
|
Not built with AddressSanitizer. SaltyOS does not have ASan support. |
|
Apple-specific availability annotations disabled. |
|
Not using picolibc. |
|
Not using newlib. |
|
Not using LLVM libc. (basaltc is implicitly the C library.) |
|
Parallel STL uses the serial backend — |
User-Visible Consequences
What works:
-
All container types:
vector,string,map,unordered_map,set,unordered_set,deque,list,array,forward_list,tuple,optional,variant,expected,span,string_view. -
Algorithms:
<algorithm>,<numeric>,<ranges>(C++20). -
Threading:
thread,mutex,condition_variable,shared_mutex,barrier,latch,atomic,future. -
Iostreams:
cin,cout,cerr,ifstream,ofstream,stringstream. (Note: stream<<formatting is locale-bound but uses the C locale, which is fine for English text and numbers.) -
<chrono>for clocks and durations. -
<charconv>forto_chars/from_charsnumeric conversion (uses Ryu). -
<format>C++20/23 format strings (basic forms). -
<random>random number generators (random_device backed by getentropy). -
<regex>(libc++'s own regex, distinct from the Cregex.hin basaltc). -
RTTI (
typeid,dynamic_cast). -
C++ exceptions (with libunwind).
What does not work:
-
std::filesystem::directory_iteratorand the directory traversal API. -
std::chrono::time_zone,zoned_time, and the IANA tzdb. -
std::execution::parparallel STL. -
Locale-aware sorting (
std::collatereturns C-locale results). -
Locale switching (
std::locale("ja_JP.UTF-8")returns the C locale). -
Unicode-aware width and case in
<format>. -
Hardening assertions on container access.
Modifying the Configuration
To change a setting, edit lib/basalt/cpp/__config_site and rebuild.
The file is included via -include in every libcxx compilation, so a change triggers a full rebuild of libc++.so.
To enable libc++ assertions for debugging:
#define _LIBCPP_HARDENING_MODE_DEFAULT _LIBCPP_HARDENING_MODE_FAST
#define _LIBCPP_ASSERTION_SEMANTIC_DEFAULT _LIBCPP_ASSERTION_SEMANTIC_TRAP
This catches out-of-bounds accesses with a hard trap. Useful when debugging a port crash. Production builds should leave the hardening off because it adds bounds-check instructions to every container access.
To enable filesystem directory traversal:
-
Add the missing libcxx sources to
_cxx_srcsinlib/basalt/cpp/meson.build:filesystem/directory_entry.cpp,filesystem/directory_iterator.cpp,filesystem/operations.cpp. -
Verify that the basaltc
posix_opendir/posix_readdirpaths are reachable from libcxx (they should be, via the C library). -
Test against a port that uses
directory_iterator.
Related Pages
-
libc++ Runtime — overall composition
-
libcxxabi and libunwind — exception runtime detail
-
Locale, ctype and wchar — the C-locale policy on the basaltc side
-
Heap and malloc —
operator newcalls into basaltc’s malloc