D003 - Source inclusion over static archives for freestanding consumers
Status: decided Date: 2026-09-04
The SDK initially provided both source lists
(OOPS_SDK_C_SRCS) and a pre-built static archive
(liboops.a). Consumers were linking against
liboops.a. That straddled two distribution models and
introduced two severe technical hazards:
Freestanding flag-matching. On a freestanding target without a hosted C runtime, the SDK and its consumers must strictly agree on codegen flags (
-target x86_64-unknown-freebsd,-ffreestanding,-fno-builtin,-fno-stack-protector,-fPIC,-mno-sse, optimization levels). A.afreezes these flags at SDK build time. If a consumer adjusts codegen flags (for instance, to target a specific kernel ABI or firmware revision), a pre-built archive becomes silently stale, resulting in an ABI or codegen mismatch that links cleanly but crashes or misbehaves at runtime. Source inclusion makes the consumer's flags authoritative across the entire translation unit graph.Weak-symbol and member-selection hazards. Platform entry points across
oops-sdkare declared with__attribute__((weak))and guarded by null checks (e.g. dynamic backend dispatch between AGC and GNM). Traditional static archives (ar) pull an archive member only when it resolves an undefined strong symbol. Weak references or symbols reached indirectly through function pointers can be dropped during archive member selection, causing runtime null pointer dereferences on hardware. Source inclusion compiles each translation unit unconditionally, completely eliminating archive member-dropping.
Link-time dead-code elimination is not lost: consumers compile with
-ffunction-sections and -fdata-sections and
link with -Wl,--gc-sections, ensuring unused SDK functions
are pruned from final payloads and eboots.
oops-sdk.mk therefore defines only
OOPS_SDK_INCLUDE and OOPS_SDK_C_SRCS. The
Makefile's all target continues to build
liboops.a solely as a -Werror compile check
gate for ./bin/oops-sdk check, not for consumer
distribution.