ADR-010: Platforms reuse component build files through shared build interfaces

Date: 2026-07-28

Status: Accepted

Context

The ESP-IDF build needed the frontend-neutral components to produce embedded build evidence for E21. Those components already own their sources, language standard, and dependencies in one CMakeLists.txt each, but every one of them links pet::warnings, pet::sanitisers, and pet::coverage, and those interface targets were created by the root project only.

The embedded build was therefore unable to add a component directory, and it had already restated the Core source list and warning flags in platforms/esp_idf/cmake/pet_core.cmake to work around the same gap. Restating a component would repeat that drift for four more directories.

Decision

cmake/pet_build_interfaces.cmake owns the shared interface targets and is the entry point a platform includes before it adds any project directory. It is guarded, so the root project and a platform build reach the same targets by the same path.

A platform composes the project by adding the directories it selected. It does not restate sources, language standards, warning flags, or dependencies, and a component stays the single source of its own build.

PET_ASSETS_STDIO_READER follows the same rule for the one component that carried a hosted assumption. The desktop reader lives in components/assets/src/desktop/reader_stdio.c, the option defaults off when CMAKE_CROSSCOMPILING is set, and the declaration in pet_assets/reader.h stays available everywhere so the contract is testable without the definition.

Consequences

The ESP-IDF build adds components/manifest, components/assets, components/presentation, and components/layout directly, and their compile lines carry the project warning contract with -Werror and C99 without any per-platform flag list.

The Core and firmware app entries lost their duplicated warning lists and link pet::warnings instead. The Core source list in the ESP-IDF platform glue remains duplicated, because Core is generated and configured by the root build for hosted compositions. Removing that duplication is a separate decision.

A platform-specific implementation of a component contract becomes a directory that the platform selects rather than a preprocessor branch inside the component. Adding a platform costs one include and the directories it wants.

Alternatives considered

Restate component sources and flags per platform. Rejected because the source list, the C99 setting, and the warning contract would drift silently between the hosted and embedded builds.

Guard the interface links inside every component with if(TARGET ...). Rejected because the warning contract would then be optional, and an embedded build could quietly compile with fewer checks than the hosted one.

Select the desktop reader with preprocessor branches in one file. Rejected because platform knowledge would move into a frontend-neutral component and the include boundary check could no longer observe the separation from the source text.

References