Platforms and Portability

Separate source paths, cross-builds, native runtime evidence, and full test gates before making deployment claims.

Evidence matrixCurrent source pinNo inferred support

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 labelWhat it establishesWhat it does not establish
Source pathGuarded implementation or explicit unsupported branch existsConfigure, compile, link, or correct runtime behavior
Configure evidenceCMake generated the selected target graphThat every translation unit compiles
Library cross-buildSelected library targets compiled and linked for another toolchainGoogleTest discovery, host runtime behavior, or application integration
Downstream buildA real consumer exercised a useful subset and drove fixesA standalone complete build or test gate
Native component testsNamed binaries executed on the target hostUntested components or environments
Complete native gateThe complete registered suite executed with a recorded outcomeIdentical behavior on another host, compiler, kernel, or filesystem
“Supported” is not a single bit

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/toolchainStrongest current evidenceWhat was coveredQualification
Linux / GCCPrimary native baselineUbuntu CI, selective components, full local gate, documentation checksThe recorded complete gate at this pin ran 17,131 cases: 17,123 passed, two skipped, six failed; the failures are retained below
Linux / ClangSource/toolchain pathClang-aware warning configuration and portable source branchesNo tracked Clang CI job or complete selected-pin gate
Windows / MinGW-w64 GCC 14-win32Historical cross-buildEarlier library-only All and selective Text.Json graphs with CMake 3.31.6Not rebuilt at this selected pin; GoogleTest was not compiled or run, so this is not native Windows runtime validation
Windows / MSVCImplementation and build branchesWin32 paths, platform libraries, and /W4 /WX policy existNo current hosted build/runtime gate; native-128-dependent types hard-fail under the MSVC frontend
macOS / Apple ClangDownstream build evidenceXcode 15.4 consumer builds drove a recorded portability-fix seriesNo current macOS CI job or standalone complete test result
Emscripten 5.0.7Historical cross-buildEarlier library-only All and Text.Json graphs with CMake 3.31.6Not rebuilt at this selected pin; no browser/Node runtime suite, and many native operations deliberately throw
AndroidIntegration pathAndroid storage-path branch and parent-provided SDL3 target wiringNo 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

SubsystemImplemented runtime pathExplicit reduced/unsupported path
System::Net::SocketsWindows and POSIX socket operationsOperations throw on Emscripten
System::IO::RandomAccessWin32 file APIs and POSIX positional I/OAll operations throw on Emscripten
System::IO::FileSystemWatcherLinux inotify, one directoryEnabling throws on Windows, macOS, Emscripten, and other targets
NetworkInterfaceLinux getifaddrs, packet metadata, and sysfs speedEnumeration and queries throw elsewhere
PingNative network path on the Linux baselineHost permissions/configuration can expose the documented raw-ICMP fallback gap
System::Diagnostics::ProcessPOSIX process, pipe, signal, and wait APIsOperations throw on Windows and Emscripten
PosixSignalRegistrationPOSIX signal implementationRegistration throws on Windows and Emscripten
AppDomain::BaseDirectoryWin32 executable path, Apple _NSGetExecutablePath, and the Linux executable pathEmscripten uses the virtual-filesystem-relative ./ fallback
TimeZoneInfoWindows APIs and POSIX zoneinfo/current-zone pathsEmscripten uses UTC for local and rejects system-zone lookup
ThreadPool and threading timersNative threads where availableSingle-threaded Emscripten builds throw for work that requires pthreads
StoragePathsCurrent-directory root by default; Android SDL root; Emscripten /save rootPersistence/mount setup belongs to the embedding application
ConsoleWin32 and POSIX TTY queries plus standard streamsEmscripten 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.

AreaEmscripten behavior
TCP sockets, HttpClient, WebSockets over native socketsUnavailable in the single-threaded native-socket model; operations throw
DNSPublic lookup methods throw PlatformNotSupportedException
Random accessThrows for descriptor operations
Process and POSIX signalsThrow
Thread pool/timers without __EMSCRIPTEN_PTHREADS__Work requiring native threads throws
Local time zoneFalls back to UTC; named system-zone lookup throws
Application base directoryReturns ./ in the virtual filesystem
StorageUses /save/.cna_isolated_storage; the application must mount/persist that path, typically with IDBFS
ConsoleReports 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 FileSystemInfo may approximate creation with inode metadata-change time.
  • Line endings: TextWriter selects 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 TimeZoneInfo model.

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

  1. Select the narrow component set and configure it with every intended toolchain.
  2. Separate “compiled” from “executed” in your own release evidence.
  3. Exercise platform-limited APIs on their real host; a Linux mock does not validate a Win32 path.
  4. Expect PlatformNotSupportedException at documented runtime doors and decide whether to gate, fall back, or disable the feature.
  5. Test real filesystem naming, permissions, timestamps, and open-file behavior on each target.
  6. Test networking under the deployment environment’s DNS, IPv6, firewall, sandbox, and ping permissions.
  7. For Emscripten, decide pthreads and virtual-filesystem persistence at the whole-application level.
  8. For Android, provide SDL3 before adding Sharp Runtime and verify the chosen storage root on a device.
  9. Do not strengthen a public platform label until the repository or product records the corresponding build/runtime evidence.