|
Deki 0.19.0
Modular C++ 2D engine for embedded displays and desktop
|
A platform is one thing a project builds for: a board, the desktop simulator, a console. This page says what a platform is made of, where platforms come from, how a package ships boards, and what happens to a board once a project is using it.
A directory under the project's platforms/, named by the platform's id:
The JSON says what the editor needs to know and nothing about how to build:
| Key | Meaning |
|---|---|
| id, displayName | The id is also the directory name. |
| framework | Which build backend builds it (espidf, native, ...). No default: a platform that does not say has no backend, and the build says so. |
| frameworkOptions | That backend's own settings: chip, flash size, sdkconfig lines, pins. The editor carries them and does not read them; the backend validates them when it builds. |
| family | Descriptive only. Becomes the capability family:<x>. |
| screenWidth, screenHeight, colorFormat | The screen this target has. The editor previews it, the desktop simulator opens a window of it, and images set to Automatic are stored in colorFormat for it. A device renders at its display's own size and format; see screens.md. |
| externalMemorySize | Bytes of memory beyond the internal heap (PSRAM on a microcontroller). Grants packages memory:external. |
| provides | What the target can offer a package: wifi, spi, desktop-os, ... |
| requiresPackages | Packages the target always needs, whatever the scenes use. Its hardware abstraction layer, typically. |
| defines, cFlags, cxxFlags, linkFlags | Compiler settings for the game's own code. |
| bootScene | Path of the boot scene, relative to the project. |
| assetStorage | Where a build keeps the game's assets: internal (the default) or external. See below. |
The boot scene holds a Deki::PlatformSetupComponent whose setupComponents list names, in order, the setup steps that bring the hardware up: a power pin, the display, an I2C bus, touch. Each entry is {id, typeId}: the id of the child object holding the step, and the hash of the step's qualified class name (Deki::HashString). A wrong typeId does not fail; the step silently never runs. ShippedPlatformTemplates in the editor's tests checks every boot scene the packages ship.
A build keeps the game's assets in one of two places:
Only a platform that provides external-storage can choose external; the platform editor shows the choice (Storage > Assets on) only for those. Choose it only for a game too big for the flash: with external storage and no card in the slot, the game has no assets. The LilyGO T-Deck Plus can choose; it keeps its assets in its flash unless told otherwise.
project_data.bin records the choice, so the engine knows where to look.
A board whose backend has a simulator (QEMU for an ESP32 or ESP32-S3) can be built to run there: tick Simulate in QEMU in the Build panel, then Build and Run. From the command line:
The simulated build keeps every step of the board's boot scene and adds the simulator's own after them (the QEMU screen), in a copy under its build directory (generated/build/<platform>_qemu/simulation/boot.scene). Where the simulator has to run a step another way, the copy says so: an SD card wired for SPI goes on QEMU's SD host. The build log lists each change. The platform's boot.scene, its normal build and the firmware flashed to the board are not changed, and nothing the simulator needs is compiled into them.
The simulated board has an SD card, made fresh for each build in simulation/sd_card: the assets, as the SD Card Deploy panel would copy them, for a target that keeps them on the card; empty for one that keeps them inside.
A backend offers this with ITargetBuilder::SupportsSimulation, GetSimulatorName and MakeSimulationBootScene (with AddSimulationSteps from deki-editor/build/SimulationBootScene.h), and reads BuildOptions::simulate for the rest: its own build directory, the card, and what deploy does.
The Build panel's target list is three sources, later ones overriding earlier:
Installing or removing a package updates the list at once.
Put one directory per board in the package:
That is the whole mechanism. The package needs no code: no package.cmake, no entry point. Its package.json should list under requires the packages its boards' boot scenes use, so installing the boards installs them too, and each platform should repeat its hardware abstraction layer in requiresPackages.
Rules that are checked:
A package feature can name packages it needs on its own, in the feature's requires:
Those are not installed with the package. The board, or the project, that uses the feature brings them: deki-lilygo-boards requires deki-i2c and deki-gpio because the T-Deck has an I2C bus and pins, and that is what lets deki-input's keyboard and trackball build. A desktop project that installs deki-input gets neither.
A build pulls a feature's packages in only while a target uses the feature. A feature in use whose package is missing builds as a step that logs what to install, and the build warns. The feature's code checks for the package with __has_include so it compiles either way.
deki-lilygo-boards is the example to copy. deki-desktop-integration ships the simulator the same way, and deki-tactility-integration its two targets.
Choosing a package's platform - in the Build panel, with set_active_platform, or by building for it - copies its directory into the project's platforms/. From then on it is the project's file: edit it in the platform editor, open its boot scene like any scene, commit it. A project never builds from inside a package.
A platform the project already defines is never overwritten by an adoption, and files already in that directory are kept.
An adoption also writes origin.json beside the platform. It names the package and holds the template as adopted: the platform JSON, and a hash of every other file. Commit it with the rest.
With what was adopted, what the project has now, and what the package offers now all known, the Build panel shows under the target list:
What does not count as a modification: the editor re-saving the JSON in its own form (older files keep backend settings at the top level; a save nests them under frameworkOptions), and line endings changed by git.
A platform adopted before origins were recorded gets its record the next time it is used, if it still matches what the package offers. If it differs there is nothing to say whose change that was, so no baseline is invented: it shows as differs from the package and can be restored, not updated.
If the package is removed, the platform stays and still builds. The line reads (not installed) until the package is back.
Deleting an adopted platform puts it back on offer; choosing it again copies the package's current version in.
| Tool | Does |
|---|---|
| list_platforms (or --list-platforms) | Every target, with origin on the ones from a package: package, modified, updateAvailable, canUpdate, canRestore. |
| set_active_platform | Choose the project's default target, adopting it if needed. |
| create_platform, set_platform_provides | Make or change a platform of the project's own. set_platform_provides takes asset_storage and cxx_flags. |
| update_platform | Update from the package. Returns taken and kept. |
| restore_platform | Restore the package's version. Returns taken. |
deki-editor/build/PlatformConfig.h is the platform and the registry. deki-editor/build/PlatformTemplates.h is everything on this page about packages: finding offers, adopting, the origin record, update and restore. Both are in the editor's SDK, so a package's build backend can use them.