ADR-0374: Build-time-optional public APIs return -ENOSYS when disabled¶
- Status: Accepted
- Date: 2026-05-10
- Deciders: lusoris
- Tags:
dnn,cuda,sycl,hip,vulkan,metal,mcp,build,api,fork-local
Context¶
The fork exposes several build-time-optional features behind meson boolean options: -Denable_dnn, -Denable_cuda, -Denable_sycl, -Denable_hip, -Denable_vulkan, -Denable_metal, -Denable_mcp. Each feature has a public C-API surface declared in a header under core/include/libvmaf/.
When a feature is disabled, its public symbols must still be present in the final shared/static library so that callers compiled against the headers always link successfully regardless of the build configuration. The symbols cannot simply be absent — that would break any downstream binary that references them conditionally or that links against a pre-built libvmaf where the build configuration is opaque.
A Phase-A audit (2026-05-10) flagged the five -ENOSYS return sites in core/src/dnn/dnn_api.c and the one in core/src/dnn/dnn_attach_api.c as "needs clarification: intentional or real gap?" This ADR records the answer: they are intentional.
Decision¶
Every build-time-optional feature in this fork follows the same disabled-build stub contract:
- Always present: every public symbol declared in the feature's header is defined in the TU, unconditionally, so linking always succeeds.
- Returns
-ENOSYSfrom every entry point that would require the feature to be active (open, run, close, import, attach, start, etc.). - Returns
0(false / unavailable) from the availability probe (vmaf_dnn_available,vmaf_cuda_available,vmaf_hip_available, etc.). - Returns
NULLfrom entry points whose return type is a pointer (e.g.vmaf_dnn_session_attached_ep). - Callers must probe availability first: check the feature's
vmaf_X_available()function at runtime before calling any other entry point.-ENOSYSis the "not built in" signal, not a programming error.
The contract is explicitly documented in the file-level comment of each stub TU (see dnn_api.c §"disabled-build stub contract" and dnn_attach_api.c §"Disabled-build stub contract (see ADR-0374)").
Alternatives considered¶
| Option | Pros | Cons | Why not chosen |
|---|---|---|---|
Omit the symbols entirely when disabled; use weak symbols or #ifdef at call sites | No stub overhead | Breaks callers that don't #ifdef every call site; requires the header itself to #ifdef away the declarations, making the API conditional — a maintenance burden and a source of subtle include-order bugs | Rejected |
Return -ENOTSUP instead of -ENOSYS | Slightly more descriptive on some platforms | ENOSYS is the established POSIX convention for "function not implemented" and is already used by every other disabled-build stub in tree (CUDA, HIP, Vulkan, Metal, MCP) | Rejected in favour of consistency |
| Implement a real fallback when DNN is disabled | Nothing to fall back to — ORT is the only inference runtime; CPU ONNX loading without ORT is out of scope | Adds dead code; the correct answer is "don't call this without enabling DNN" | Rejected |
Consequences¶
- Positive: downstream binaries link against any configuration of libvmaf without conditional compilation. Feature probing is uniform across all optional backends:
if (!vmaf_X_available()) { /* skip */ }. - Positive: the audit ambiguity is resolved with a single ADR entry; future sessions will not re-investigate these sites.
- Negative: callers that forget to probe availability will receive
-ENOSYSat runtime rather than a link error. The mitigation is the availability probe API and this documented contract. - Neutral: no code change is required — the stubs were already correct. This ADR is documentation-only. The file-level comments in
dnn_api.canddnn_attach_api.cnow cross-reference this ADR.
References¶
core/src/dnn/dnn_api.clines 14–17 (existing stub-contract comment)core/src/dnn/dnn_attach_api.clines 14–24 (stub-contract comment added in this PR)- Same pattern in:
core/src/sycl/dmabuf_import.cpplines 529–588,core/src/mcp/mcp.c(scaffold stubs per ADR-0209),core/src/hip/common.c+kernel_template.c(scaffold stubs per ADR-0212),core/src/vulkan/common.c(scaffold stubs per ADR-0175),core/src/feature/metal/(scaffold stubs per ADR-0361). - Phase-A audit finding:
dnn_api.canddnn_attach_api.c-ENOSYSstubs flagged as "Phase-A-ish — needs clarification: intentional or real gaps?" Decision: intentional per this ADR. - req: "handle the 5 -ENOSYS stubs in dnn_api.c (and 1 in dnn_attach_api.c) that fire when -Denable_dnn=false ... are they intentional or real gaps?"