Platforms and Portability
Separate source paths, cross-builds, native runtime evidence, and full test gates before making deployment claims.
How to read platform status
Sharp Runtime’s platform status is evidence-based and multi-stage. A preprocessor branch proves only that a source path exists. A successful configuration proves only that CMake can construct the requested graph. A cross-build proves compilation and linking for that toolchain. Runtime behavior, the component test matrix, and a complete gate are stronger and separate claims.
| Evidence label | What it establishes | What it does not establish |
|---|---|---|
| Source path | Guarded implementation or explicit unsupported branch exists | Configure, compile, link, or correct runtime behavior |
| Configure evidence | CMake generated the selected target graph | That every translation unit compiles |
| Library cross-build | Selected library targets compiled and linked for another toolchain | GoogleTest discovery, host runtime behavior, or application integration |
| Downstream build | A real consumer exercised a useful subset and drove fixes | A standalone complete build or test gate |
| Native component tests | Named binaries executed on the target host | Untested components or environments |
| Complete native gate | The complete registered suite executed with a recorded outcome | Identical behavior on another host, compiler, kernel, or filesystem |
For deployment decisions, read both the platform row and the subsystem matrix. A Windows implementation of sockets does not imply that Process or FileSystemWatcher has a Windows backend; an Emscripten library build does not imply browser runtime tests.
Current evidence matrix
| Platform/toolchain | Strongest current evidence | What was covered | Qualification |
|---|---|---|---|
| Linux / GCC | Primary native baseline | Ubuntu CI, selective components, full local gate, documentation checks | The recorded complete gate at this pin ran 17,131 cases: 17,123 passed, two skipped, six failed; the failures are retained below |
| Linux / Clang | Source/toolchain path | Clang-aware warning configuration and portable source branches | No tracked Clang CI job or complete selected-pin gate |
| Windows / MinGW-w64 GCC 14-win32 | Historical cross-build | Earlier library-only All and selective Text.Json graphs with CMake 3.31.6 | Not rebuilt at this selected pin; GoogleTest was not compiled or run, so this is not native Windows runtime validation |
| Windows / MSVC | Implementation and build branches | Win32 paths, platform libraries, and /W4 /WX policy exist | No current hosted build/runtime gate; native-128-dependent types hard-fail under the MSVC frontend |
| macOS / Apple Clang | Downstream build evidence | Xcode 15.4 consumer builds drove a recorded portability-fix series | No current macOS CI job or standalone complete test result |
| Emscripten 5.0.7 | Historical cross-build | Earlier library-only All and Text.Json graphs with CMake 3.31.6 | Not rebuilt at this selected pin; no browser/Node runtime suite, and many native operations deliberately throw |
| Android | Integration path | Android storage-path branch and parent-provided SDL3 target wiring | No whole-project Android build or device/emulator test result at this pin |
What the tracked CI actually runs
The selected repository workflow runs on Ubuntu only. It contains nine selective component jobs—Core.Base, Text.Json, Net.Http.Headers, Net.WebSockets, IO.Compression, IO.Compression.Zip, IO.IsolatedStorage, Security.Cryptography.Random, and Xml.Linq—plus one complete local-integrity job and one Ubuntu 24.04 Doxygen warning-baseline job.
The complete integrity script covers more than behavior tests: component-boundary validation, validator tests, generated-catalogue drift, ODR seams, negative consumer fixtures, configuration, a warning-as-error build, and the component-aware test sequence. It remains one Linux/GCC baseline, not a substitute for a compiler/OS matrix.
Runtime availability by subsystem
| Subsystem | Implemented runtime path | Explicit reduced/unsupported path |
|---|---|---|
System::Net::Sockets | Windows and POSIX socket operations | Operations throw on Emscripten |
System::IO::RandomAccess | Win32 file APIs and POSIX positional I/O | All operations throw on Emscripten |
System::IO::FileSystemWatcher | Linux inotify, one directory | Enabling throws on Windows, macOS, Emscripten, and other targets |
NetworkInterface | Linux getifaddrs, packet metadata, and sysfs speed | Enumeration and queries throw elsewhere |
Ping | Native network path on the Linux baseline | Host permissions/configuration can expose the documented raw-ICMP fallback gap |
System::Diagnostics::Process | POSIX process, pipe, signal, and wait APIs | Operations throw on Windows and Emscripten |
PosixSignalRegistration | POSIX signal implementation | Registration throws on Windows and Emscripten |
AppDomain::BaseDirectory | Win32 executable path, Apple _NSGetExecutablePath, and the Linux executable path | Emscripten uses the virtual-filesystem-relative ./ fallback |
TimeZoneInfo | Windows APIs and POSIX zoneinfo/current-zone paths | Emscripten uses UTC for local and rejects system-zone lookup |
ThreadPool and threading timers | Native threads where available | Single-threaded Emscripten builds throw for work that requires pthreads |
StoragePaths | Current-directory root by default; Android SDL root; Emscripten /save root | Persistence/mount setup belongs to the embedding application |
Console | Win32 and POSIX TTY queries plus standard streams | Emscripten reports streams redirected and uses fallback dimensions |
Linux / GCC baseline
Linux with GCC is the only platform with a recorded complete native gate at the selected revision. The project also depends on Linux-specific facilities for its strongest watcher and network-interface behavior: inotify/eventfd, getifaddrs, Linux packet metadata, sysfs network speed, /proc paths, and the conventional /usr/share/zoneinfo database.
The complete gate is intentionally not summarized as green. Five recorded Ping cases were triggered by the host’s ping_group_range configuration and expose a real missing raw-ICMP receive fallback when the unprivileged datagram path cannot be used. One socket/interface case depended on IPv6 host state that was absent. These are environment-sensitive results with real library implications, not permission to discard failures.
Windows
Windows source paths are substantial rather than cosmetic. The networking component attaches ws2_32 privately; secure random attaches bcrypt; sockets, DNS, random access, executable-path discovery, runtime information, drive enumeration, console geometry, and time-zone lookup have Win32 branches. Consumers should link the Sharp Runtime component target and let its transitive platform libraries follow, rather than manually reproducing those links.
That implementation breadth is not a current native validation claim. MinGW evidence is an earlier library-only cross-compilation and was not repeated at the selected pin. No selected-pin Windows tests ran, and no tracked Windows job exists. In particular, Process, FileSystemWatcher, and NetworkInterface still lack Windows backends.
MSVC is a compiler boundary, not a Windows boundary
System::Decimal, System::Int128, and System::UInt128 require the GCC/Clang __int128 extension and deliberately produce a compile-time error under the MSVC frontend. BinaryReader::ReadDecimal is guarded out under MSVC so that one method does not make the whole reader unavailable. This limitation applies to the compiler, not to the Windows operating system: a Clang/GCC Windows target with native 128-bit extension support is a different case.
macOS / Apple Clang
macOS benefits from POSIX code and has explicit Apple paths for executable discovery and runtime platform identity. A real Xcode 15.4 downstream consumer drove a sequence of portability fixes, which is stronger evidence than an untouched preprocessor branch. It is still narrower than a standalone All build plus complete test suite. The repository has no hosted macOS job, and FileSystemWatcher has no Apple backend.
Emscripten and WebAssembly
The recorded Emscripten evidence covers library cross-builds of the complete graph and Text.Json, without GoogleTest or browser execution. Unsupported runtime operations are designed to compile and fail explicitly rather than disappearing at link time.
| Area | Emscripten behavior |
|---|---|
TCP sockets, HttpClient, WebSockets over native sockets | Unavailable in the single-threaded native-socket model; operations throw |
| DNS | Public lookup methods throw PlatformNotSupportedException |
| Random access | Throws for descriptor operations |
| Process and POSIX signals | Throw |
Thread pool/timers without __EMSCRIPTEN_PTHREADS__ | Work requiring native threads throws |
| Local time zone | Falls back to UTC; named system-zone lookup throws |
| Application base directory | Returns ./ in the virtual filesystem |
| Storage | Uses /save/.cna_isolated_storage; the application must mount/persist that path, typically with IDBFS |
| Console | Reports input/output/error redirected and returns 80×24 fallback dimensions |
Android
The Android-specific evidence centers on storage integration. When Storage is selected, the parent build must provide either SDL3::SDL3 or SDL3::SDL3-static. StoragePaths uses SDL_GetPrefPath, falls back to SDL_GetAndroidInternalStoragePath, and finally has a /data/local/tmp fallback if neither SDL query succeeds.
This code path does not prove a complete NDK configuration, every physical component, JNI/application lifecycle behavior, or device persistence. Android should be described as an integration path until a reproducible whole-project build and device/emulator suite are recorded.
Cross-platform semantic differences
Even APIs implemented on multiple platforms expose native realities:
- Paths: separators differ, the Sharp Runtime path grammar is smaller than full Windows drive/UNC semantics, and case sensitivity follows both implementation policy and filesystem/mount behavior.
- Files: deletion and rename of open files, sharing, permission errors, link behavior, and timestamp precision differ between Windows and POSIX.
- Creation time: POSIX
FileSystemInfomay approximate creation with inode metadata-change time. - Line endings:
TextWriterselects CRLF on Windows and LF elsewhere; some whole-file helpers write LF directly. - Console: terminal geometry and redirection are queried natively, with fallbacks. ANSI-oriented behavior is not a uniform GUI console abstraction.
- Network availability: interface presence, IPv6 state, ping permissions, firewalls, DNS, and container policies are host state, not merely OS names.
- Time zones: Windows IDs/APIs and POSIX IANA zoneinfo are bridged only for the curated mapping and reduced
TimeZoneInfomodel.
Toolchain and build requirements
The root project requires CMake 3.20 and C++23 with language extensions disabled. The common target requests cxx_std_23. Production and test targets use warnings as errors: /W4 /WX for MSVC and -Wall -Wextra -Werror elsewhere, with one GCC-specific format-truncation suppression that is intentionally not sent to Clang.
External dependencies remain attached to narrow owners: ZLIB to IO.Compression, vendored miniz to ZIP, tinyxml2 publicly to XML because public headers expose it, ws2_32 to networking on Windows, BCrypt to secure random on Windows, and parent-provided SDL3 to Storage on Android.
Portability checklist for consumers
- Select the narrow component set and configure it with every intended toolchain.
- Separate “compiled” from “executed” in your own release evidence.
- Exercise platform-limited APIs on their real host; a Linux mock does not validate a Win32 path.
- Expect
PlatformNotSupportedExceptionat documented runtime doors and decide whether to gate, fall back, or disable the feature. - Test real filesystem naming, permissions, timestamps, and open-file behavior on each target.
- Test networking under the deployment environment’s DNS, IPv6, firewall, sandbox, and ping permissions.
- For Emscripten, decide pthreads and virtual-filesystem persistence at the whole-application level.
- For Android, provide SDL3 before adding Sharp Runtime and verify the chosen storage root on a device.
- Do not strengthen a public platform label until the repository or product records the corresponding build/runtime evidence.