Sharp Runtime exposes independently selectable CMake targets. Applications request only their direct components; Sharp Runtime resolves and enables the transitive dependency closure.
The registered graph currently contains 41 physical modules and 91 direct production dependency edges. The boundary validator reports no cycles, duplicate include paths, orphan files, undeclared edges, stale edges, or visibility mismatches. The dependency allow-list is empty.
The complete component, ownership, dependency, external-library, and representative-header table is generated from the CMake registrations: generated component catalogue. Local validation and the tracked GitHub Actions workflow reject an out-of-date catalogue.
BlockingCollection<T> is owned by the narrow Collections.Blocking
component. This preserves the Collections.Core boundary: consumers such as
Text.Json do not configure Threading or TimeZone unless they explicitly
request a component that needs them.
Set SHARP_RUNTIME_COMPONENTS before adding the project:
set(SHARP_RUNTIME_COMPONENTS
Net.WebSockets
Text.Json
)
set(SHARP_RUNTIME_BUILD_TESTS OFF CACHE BOOL "" FORCE)
add_subdirectory(path/to/sharp-runtime)
target_link_libraries(MyApp PRIVATE
SharpRuntime::Net.WebSockets
SharpRuntime::Text.Json
)The application does not list transitive dependencies. For a standalone configuration, pass a semicolon-separated list:
cmake -S . -B build-components \
-DSHARP_RUNTIME_BUILD_TESTS=OFF \
'-DSHARP_RUNTIME_COMPONENTS=IO;IO.Hashing'
cmake --build build-components --parallel 3An unset or empty list selects All in a standalone repository build.
Embedding applications should always set the list explicitly.
Each physical module owns its public headers, implementation, tests, and CMake
declaration under modules/<module>/{include,src,tests,CMakeLists.txt}.
Existing System/... and SharpRuntime/... include spellings are unchanged.
PUBLIC_DEPENDENCIESare used by a module's public headers. Their include roots and link requirements propagate to consumers.PRIVATE_DEPENDENCIESare used only by implementation sources. Static-link requirements remain correct, but their include roots do not leak to consumers.TEST_DEPENDENCIESare available only to the owning module's test binary. They do not affect production targets or consumers.- Platform and vendor targets are attached by the owning module's setup function with the narrowest valid visibility.
The validator derives actual edges from project-local includes and rejects a missing, stale, or incorrectly visible declaration.
New code should prefer the narrow physical targets:
SharpRuntime::Core.Baseowns foundation types.SharpRuntime::Console,SharpRuntime::Uri, andSharpRuntime::TimeZoneare optional physical components.SharpRuntime::Collections.Coreis intended to own synchronous collection fundamentals without optional high-level closures.BlockingCollection<T>belongs toSharpRuntime::Collections.Blocking, which isolates itsThreadingdependency.SharpRuntime::Collections.AsyncandSharpRuntime::Collections.ObjectModelsimilarly isolate asynchronous and notification-specific dependencies.
Compatibility targets preserve the historical broad surfaces:
SharpRuntime::CoreaggregatesCore.Base,Console,Uri, andTimeZone.SharpRuntime::Collectionsaggregates all four collection components.SharpRuntime::Xml.XPathaliases the physicalSharpRuntime::Xmlarchive.SharpRuntime::Allaggregates every physical component.- The legacy
SHARP_RUNTIMEtarget forwards toSharpRuntime::AllwhenAllis enabled.
The legacy target is deliberately absent from selective configurations because creating it unconditionally would instantiate every optional dependency.
Tests no longer force All. A selective configuration builds the requested
component's tests plus explicitly declared test-only production dependencies:
cmake -S . -B build-json-tests \
-DSHARP_RUNTIME_COMPONENTS=Text.Json \
-DSHARP_RUNTIME_BUILD_TESTS=ON
cmake --build build-json-tests --target SharpRuntimeTests --parallel 3
scripts/run_component_tests.sh build-json-testsThat command runs only SharpRuntimeTests_Text_Json. It does not build tests
for dependencies or unrelated components.
For the repository-wide suite:
cmake -S . -B build \
-DSHARP_RUNTIME_COMPONENTS=All \
-DSHARP_RUNTIME_BUILD_TESTS=ON
cmake --build build --target SharpRuntimeTests --parallel 3
scripts/run_component_tests.sh buildSharpRuntimeTests is a convenient aggregate build target. Executable targets
are named SharpRuntimeTests_<Component>; genuinely cross-module scenarios
are in SharpRuntimeIntegrationTests. CTest also discovers every individual
GoogleTest case.
The verified 2026-07-25 All baseline contains 12,681 tests across 36
component executables and one integration executable.
Run the full native gate with:
scripts/local_ci_check.sh buildRun the selective consumer matrix with:
scripts/check_selective_components.sh.github/workflows/components.yml runs the ten selective configurations and
the full compatibility build on Ubuntu for pushes and pull requests. It does
not currently provide Windows, macOS, or Emscripten coverage.
The full selective matrix is green. Its Text.Json job explicitly verifies that
the configured target graph excludes Threading, ComponentModel, networking
and external-library targets, then compiles negative include-leakage fixtures.
External libraries are configured only by their owning component:
IO.Compressionfinds ZLIB privately.IO.Compression.Zipbuilds vendored miniz privately.Xmlbuilds vendored tinyxml2 and exposes it publicly becauseXmlDocument.hppexposes tinyxml2 types.Netlinksws2_32privately on Windows.Security.Cryptography.Randomlinksbcryptprivately on Windows.Storageprivately links an existing SDL3 target on Android.
A Text.Json-only build configures none of Threading, TimeZone, ZLIB,
miniz, tinyxml2, SDL, socket, or platform-crypto targets. The negative
consumer fixtures also cover private/sibling header leakage: Text.Json must not expose
Collections.Core or Collections.ObjectModel, and Xml.Linq must not
expose Xml's private Diagnostics dependency.
The detailed Core classification is recorded in
Core ownership. In particular, selected cross-namespace
foundation types remain in Core.Base when moving them would create a static
dependency cycle. Examples include System::IO::IOException,
System::IO::DirectoryNotFoundException, and
System::Buffers::MemoryHandle.
Xml and XPath remain one physical archive because their existing implementations have mutual binary dependencies. This preserves both public component names without introducing a graph cycle.
When adding or moving runtime code:
-
Place every public header, source, and module test under one physical
modules/<module>owner. Put only genuinely cross-module scenarios undertests/integration. -
Register each new physical directory once in
cmake/SharpRuntimeModules.cmake. -
Declare public-header edges as
PUBLIC_DEPENDENCIES, source-only edges asPRIVATE_DEPENDENCIES, and test-only edges asTEST_DEPENDENCIES. -
Attach vendor or platform libraries only in the owning module setup function. Propagate them publicly only if a public header exposes their types.
-
Avoid depending internally on the
Core,Collections, orAllcompatibility umbrellas. -
Regenerate the catalogue and run all boundary fixtures:
python3 scripts/validate_module_boundaries.py python3 test/validate_module_boundaries_test.py python3 scripts/generate_component_catalog.py
-
Run
scripts/check_selective_components.shandscripts/local_ci_check.shbefore committing.
Allow-list entries in
cmake/SharpRuntimeModuleDependencyAllowlist.json are reserved for genuine
link-only or generated edges. Every entry requires an owner, visibility, and
specific reason.
Collections.Blocking restores the lean closures below while preserving the
same public header path, namespace, and Collections compatibility umbrella:
| Requested component | Production closure |
|---|---|
Text.Json |
Core.Base, Buffers, Text, Collections.Core, Text.Json |
Net.Http.Headers |
Core.Base, Uri, Collections.Core, Net.Http.Headers |
Net.Mime |
Core.Base, Collections.Core, Net.Mime |
Numerics |
Core.Base, Buffers, Collections.Core, Numerics |
These closures avoid Threading, TimeZone, ComponentModel, the broad
Collections umbrella, Console, networking/XML, and unrelated external
libraries.