1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
[]
= "m5stack-core"
= "0.6.1"
= "2024"
= "1.96"
= "MIT OR Apache-2.0"
= "Board support crate for M5Stack Fire27 and CoreS3 (ESP32/ESP32-S3)"
= "https://github.com/emobotics-dev/m5stack-core"
# Self-hosted rustdoc, built by .forgejo/workflows/docs.yml. docs.rs runs the
# stock rust-lang toolchain, which has no Xtensa backend, so it cannot build
# this crate for either board — see the docs section in README.md.
= "https://emobotics-dev.github.io/m5stack-core"
= "README.md"
= ["esp32", "m5stack", "embedded", "bsp", "embassy"]
= ["embedded", "no-std", "hardware-support"]
# An allow-list, not the `exclude` it replaces: cargo packages every
# untracked-but-unignored file, so a blocklist must name each tool directory
# that might ever appear — and `.claude/` shipped in 0.5.0 because it did not
# (#59). Unknown files now fail closed, loudly, and `.cargo/credentials.toml`
# cannot ship at all since only `config.toml` is named.
= [
"/src/**/*.rs",
"/tools/**",
"/docs/**",
"/build.rs",
"/Cargo.toml",
"/README.md",
"/CHANGELOG.md",
"/LICENSE-MIT",
"/LICENSE-APACHE",
"/hil.toml.example",
"/rust-toolchain.toml",
"/.cargo/config.toml",
"/.gitignore",
]
[]
= false
= false
[]
# The `esp-bootloader-esp-idf?/<chip>` arms only bite when the optional dep is
# already on (via `heap`) — `init_heap`'s `#[ram(reclaimed)]` region needs the
# esp-idf bootloader crate in the graph; a heap-free build never pulls it.
= ["esp-hal/esp32", "esp-radio/esp32", "esp-sync/esp32", "esp-bootloader-esp-idf?/esp32", "esp-rtos?/esp32"]
= ["esp-hal/esp32s3", "esp-radio/esp32s3", "esp-sync/esp32s3", "esp-bootloader-esp-idf?/esp32s3", "esp-rtos?/esp32s3"]
# Enables the masked 1-Wire ROM search (driver::onewire::Search::new_with_mask),
# constraining enumeration to addresses matching fixed bits under a mask.
= []
# HIL serial-cmd driver — exposes a Read endpoint over UART0 (fire27) or
# USB-Serial-JTAG (cores3). Paired with `alternator-regulator/serial-cmd`.
= []
# Bench regression only: injects `M5_TEST_AW_NACK` simulated AW9523B "not ready"
# results into `board::cores3::power_display_reset`, so the cold-boot retry
# recovery (issue #3 companion) is testable without a power cycle (the rig can't
# switch USB VBUS). No effect unless the env var is set at build time; never
# enable in production.
= []
# Export the `#[panic_handler]` symbol from the BSP (body = io::console::on_panic
# — RTC breadcrumb + best-effort print + halt). Off by default so a consumer can
# provide its own; a binary opts in instead of hand-rolling the one-line wrapper.
= []
# Multicore app-core harness (board::run_app_core): parks + starts the APP core
# on an esp-rtos InterruptExecutor with the waiti idle loop, encapsulating the
# park_core JTAG-reset workaround. Pulls esp-rtos (its embassy InterruptExecutor).
= ["dep:esp-rtos"]
# Console serial transport (UART0 / USB-Serial-JTAG): the TX drain + RX half +
# `console::install`'s `Some(serial)` path + the panic transport print. With it
# OFF (R9 production backstop) none of those symbols link: `log!` is a no-op into
# the ring, `install` can only register the backend, and `on_panic` still writes
# the RTC breadcrumb and halts (RWDT recovers) — just with no serial surface.
= []
# esp-idf application descriptor (`app_desc!`, `app_elf_sha256()`): a fixed,
# ELF-mapped struct (project name/version/build time/ELF content hash) that a
# host can read straight off flash without booting the board. Decoupled from
# `heap` — reading/emitting the descriptor touches no allocator — so a board
# that wants identity reporting but no global heap doesn't have to pull in
# esp-alloc just to get it.
= ["dep:esp-bootloader-esp-idf"]
# Enforced firmware build identity: `app_desc!()`'s version field becomes the
# consumer's own build-time git descriptor (`M5STACK_CORE_BUILD_MARK`, set by
# the consumer's own `build.rs` — see the `m5stack-core-build` crate) instead
# of plain `CARGO_PKG_VERSION`. The call site never changes; forgetting the
# `build.rs` wiring is a compile error (a missing `env!()`), not a silent gap.
# Off by default — `app_desc!()` keeps today's plain-version behavior.
= ["app-desc"]
# Global-heap ownership (the `mem` module): `mem::init_heap(profile, psram)`
# declares the esp-alloc DRAM regions (HIL-proven per-board sizes) so a binary
# never calls `esp_alloc::heap_allocator!` itself. PSRAM-free, so a board with
# no external RAM (or that just doesn't want it) enables only this.
= ["dep:esp-alloc", "dep:allocator-api2", "app-desc"]
# External PSRAM heap support (the PSRAM region + the `psram_box`/`psram_vec`
# checked allocators). Implies `heap`. Enabling it activates a build-time guard
# requiring opt-level > 0 (build.rs) and the compile-time `PsramSafe` atomic
# check (uses the `esp` nightly auto-trait features).
= ["heap"]
# On-board ILI9342C panel bring-up (board::display) and the display/SD-card
# device construction on the shared SPI2 bus (board::spi2::Spi2Parts::finish).
= ["dep:lcd-async", "dep:embassy-embedded-hal"]
# Debounced front-panel button driver (io::buttons::Buttons, Fire27 hardware).
# The unified ButtonEvent types and the CoreS3 touch emulation need no feature.
= ["dep:async-button", "dep:embassy-time-04"]
# --- Radio (driver::radio) — orthogonal to the chip features; combine per app.
# The radio is shared, so `coex` is required to run BLE and WiFi at once.
= ["esp-radio/ble"] # driver::radio::ble (BleRadio → BleConnector)
= ["esp-radio/wifi"] # driver::radio::wifi (controller + scan)
= ["wifi", "dep:embassy-net"] # STA + DHCP embassy_net::Stack
= ["wifi", "dep:embassy-net"] # reserved for AP mode (not yet implemented)
= ["esp-radio/coex", "wifi", "ble"] # software WiFi/BLE coexistence (extra RAM)
# --- Example-only (`ex-*`) — never enable these in an application ------------
# They exist because `required-features` can only *gate* an example, never turn
# anything on: the examples in `examples/` need library features (and chip
# features on the dev-dependencies) that no application should inherit. `ex-*`
# forces `panic-handler` and `console-serial` on, which a real application
# provides itself — enabling them downstream is a duplicate-symbol error, not a
# preference.
#
# They gate *code*, not dependencies: Cargo forbids optional dev-dependencies,
# so oxivgl/sdspi/trouble-host are built for any example target regardless.
# That is why building even a light example pays the LVGL C build once.
# `esp-rtos/esp-radio` is what registers the `esp_rtos_semaphore_*` symbols that
# oxivgl's blocking flush wait links against — without it every example fails to
# link, not just the LVGL ones, because oxivgl is an unconditional dev-dep.
= [
"display", "psram", "wifi-sta", "console-serial", "panic-handler", "app-desc",
"dep:esp-rtos", "esp-rtos/embassy", "esp-rtos/esp-radio",
"esp-alloc/internal-heap-stats",
]
= [
"ex-common", "fire27", "buttons",
"esp-rtos/esp32", "esp-sync/esp32", "esp-bootloader-esp-idf/esp32",
]
= [
"ex-common", "cores3",
"esp-rtos/esp32s3", "esp-rtos/log-04",
"esp-sync/esp32s3", "esp-sync/log-04",
"esp-bootloader-esp-idf/esp32s3",
"embassy-executor/log", "embassy-time/log",
]
# Per-example extras, named by `required-features` on the [[example]] entries.
= []
= []
= ["coex"]
= ["multicore"]
= []
# Scheduling variants of the lvgl_sched harness (#63) — see docs/lvgl-ui-performance.md.
= []
= ["ex-ui-thread"]
= ["ex-ui-flush-thread"]
[]
# esp-hal family — stock crates.io versions so the crate publishes. The whole
# family is version-locked together, so they are pinned exactly; local and
# example builds are redirected to the emobotics fork (a coherent snapshot of
# the same versions, plus SPI/DMA patches the examples need) via the rev-pinned
# [patch.crates-io] below, which `cargo publish` ignores.
= { = "=0.10.0", = true }
= { = "=1.1.2", = ["unstable"] }
= { = "=0.18.0", = ["esp-alloc", "unstable"] }
= { = "=0.2.1" }
# Bootloader integration — needed only by the `heap` feature: `init_heap`'s
# `#[ram(reclaimed)]` region requires the esp-idf bootloader crate in the graph
# (it also backs the future `app_desc!`). Stock for publish; patched to the fork
# below for local/example builds so it unifies with the examples' copy (a
# `links` crate must resolve to a single version).
= { = "=0.5.0", = true }
# Multicore harness only (board::run_app_core): esp-rtos's embassy
# InterruptExecutor. Stock for publish, patched to the fork below for local
# builds so it unifies with the examples' copy.
= { = "=0.3.0", = true, = ["embassy"] }
# Pinned (and referenced via `use esp_rom_sys as _` in lib.rs so it survives
# `cargo package`): esp-hal 1.1.0 calls esp_rom_sys::init_syscall_table, added
# in 0.1.4, but only constrains it to ~0.1 — without this pin a stock resolve
# drifts to 0.1.1 (which lacks the function) and esp-hal fails to compile.
= { = "=0.1.4" }
# embedded-hal family
= "1.0.0"
# Async SPI traits. Already an implicit dependency — `SpiDeviceWithConfig`
# implements them — but `board::spi2`'s fair device wrapper names them directly,
# so the edge has to be explicit rather than borrowed from a dev-dependency.
= "1"
= "0.7.0"
# Embassy
= { = "0.10.0", = ["nightly"] }
= "0.1"
= { = "0.9.1", = true, = false, = ["dhcpv4", "proto-ipv4", "medium-ethernet", "tcp", "udp", "dns"] }
= "0.8"
= "0.5.1"
# misc
# Held at 0.3: esp-alloc 0.10 implements allocator-api2 0.3's `Allocator` for its
# Internal/ExternalMemory; 0.4 is a different trait version → tied to the esp stack.
= { = "0.3.0", = false, = ["alloc"], = true }
= { = "0.2.0", = true }
# async-button 0.2 pins embassy-time 0.4; alias it so we can name that `Duration`
# to build `ButtonConfig` timings from milliseconds (the BSP itself is on 0.5).
= { = "embassy-time", = "0.4", = true }
= { = "0.6.0", = true, = ["time"] }
# Held at 1.29: 1.30+ requires `az ~1.3`, conflicting with embedded-graphics 0.8's
# `az ~1.2` pin.
= "1.29.0"
= { = "0.1.3", = true }
= { = "0.9.3", = ["nightly"] }
= "0.4"
= { = "2.1.1", = ["nightly"] }
= "2.0.2"
# Local/example builds only: redirect the esp-hal family the library declares
# (stock, above) to the emobotics fork at a pinned rev — a coherent snapshot of
# those versions with the SPI/DMA patches the examples need. Pinned to a rev,
# not the floating `local` branch, so builds are reproducible. `cargo publish`
# ignores [patch], so downstream consumers resolve the stock crates.io versions.
[]
= { = "https://github.com/emobotics-dev/esp-hal.git", = "04646b65e3ef94d60f5e08cb24fed9e3cd77f9d0" }
= { = "https://github.com/emobotics-dev/esp-hal.git", = "04646b65e3ef94d60f5e08cb24fed9e3cd77f9d0" }
= { = "https://github.com/emobotics-dev/esp-hal.git", = "04646b65e3ef94d60f5e08cb24fed9e3cd77f9d0" }
= { = "https://github.com/emobotics-dev/esp-hal.git", = "04646b65e3ef94d60f5e08cb24fed9e3cd77f9d0" }
= { = "https://github.com/emobotics-dev/esp-hal.git", = "04646b65e3ef94d60f5e08cb24fed9e3cd77f9d0" }
= { = "https://github.com/emobotics-dev/esp-hal.git", = "04646b65e3ef94d60f5e08cb24fed9e3cd77f9d0" }
= { = "https://github.com/emobotics-dev/esp-hal.git", = "04646b65e3ef94d60f5e08cb24fed9e3cd77f9d0" }
# oxivgl's `rtos-sem` asks for the crates.io release; the examples use the fork.
# Without this they resolve to two crates and the semaphore handle oxivgl returns
# is a different type from the one esp-rtos registers.
= { = "https://github.com/emobotics-dev/esp-hal.git", = "04646b65e3ef94d60f5e08cb24fed9e3cd77f9d0" }
[]
# `m5stack-core-build` is a HOST crate, and a member — including an implicit one,
# which a path dependency otherwise becomes — is built for the workspace's
# target. So every `--workspace` command carrying a board target compiled it for
# Xtensa and died on missing `std`; rust-analyzer's build-script pass is one such
# command, and reported it only as "failed to run build scripts". Excluding it
# costs nothing: this crate still uses it as an optional build-dependency, and
# build dependencies are compiled for the host regardless.
= ["m5stack-core-build"]
# Shared example dependencies — referenced by the example crates via
# `<dep>.workspace = true` so the esp-hal fork rev (and the rest) is stated
# once. Chip features (esp32/esp32s3) and `optional` are applied per-member.
# The library itself (above) does NOT use these — it depends on stock crates.io
# esp-hal redirected by [patch.crates-io]; the examples pull fork crates that
# are not on the patch list (esp-rtos, esp-bootloader-esp-idf, esp-backtrace,
# esp-println), so they declare the fork explicitly.
# --- Example targets ---------------------------------------------------------
# Auto-discovery finds every `examples/*.rs` and `examples/*/main.rs`;
# `examples/common/` has no `main.rs`, so cargo ignores it and it serves as the
# shared framework (each example pulls it in with `#[path] mod common;`).
# These entries exist only to add `required-features` — the paths are the ones
# cargo would infer anyway.
#
# Every example additionally needs a board aggregate on the command line:
# cargo build --examples --features ex-fire27
# cargo build --examples --no-default-features --features ex-cores3 \
# --target xtensa-esp32s3-none-elf
[[]]
= "display"
= "examples/display.rs"
[[]]
= "i2c_scan"
= "examples/i2c_scan.rs"
[[]]
= "m5go"
= "examples/m5go.rs"
[[]]
= "wifi_sta"
= "examples/wifi_sta.rs"
[[]]
= "psram_split"
= "examples/psram_split.rs"
[[]]
= "onewire"
= "examples/onewire.rs"
= ["fire27"]
[[]]
= "lvgl"
= "examples/lvgl/main.rs"
= ["ex-lvgl"]
[[]]
= "lvgl_threads"
= "examples/lvgl_threads.rs"
= ["ex-lvgl"]
[[]]
= "lvgl_sched"
= "examples/lvgl_sched/main.rs"
= ["ex-lvgl"]
[[]]
= "sd"
= "examples/sd.rs"
= ["ex-sd"]
[[]]
= "coex"
= "examples/coex.rs"
= ["ex-coex"]
[[]]
= "multicore"
= "examples/multicore.rs"
= ["ex-multicore"]
[[]]
= "probe_sd_read"
= "examples/probe_sd_read.rs"
= ["ex-probes", "ex-sd"]
[[]]
= "probe_spi_cmd"
= "examples/probe_spi_cmd.rs"
= ["ex-probes"]
[[]]
= "probe_pps"
= "examples/probe_pps.rs"
= ["ex-probes"]
[[]]
= "probe_gdma_eof"
= "examples/probe_gdma_eof.rs"
= ["ex-probes", "cores3"]
[[]]
= "probe_spi2_gdma_fault"
= "examples/probe_spi2_gdma_fault.rs"
= ["ex-probes", "cores3"]
[[]]
= "probe_dma_int"
= "examples/probe_dma_int.rs"
= ["ex-probes", "cores3"]
[[]]
= "probe_nack"
= "examples/probe_nack.rs"
= ["ex-probes", "ex-coex"]
# --- Examples ---------------------------------------------------------------
# Everything under `examples/`. These are stripped from the published manifest
# (cargo drops dev-dependencies that carry no `version` key), so the git forks
# here never reach a consumer — verified with `cargo package`.
#
# Cargo forbids `optional = true` on a dev-dependency, so these cannot be
# feature-gated: any example target builds all of them. See the `ex-*` features.
[]
# Only what the library does not already depend on — a name may not resolve to
# two different sources, and examples can use the package's own [dependencies].
= { = true }
= { = true }
= { = true }
# SD: the sdspi/embedded-fatfs fork is git-only (not on crates.io). Examples
# only — it must never reach [dependencies] or the crate stops publishing.
= { = "https://github.com/emobotics-dev/embedded-fatfs.git", = "4565a3e3358e1b03c12b7f1b8c04483facbc45b9", = ["log"] }
= { = "https://github.com/emobotics-dev/embedded-fatfs.git", = "4565a3e3358e1b03c12b7f1b8c04483facbc45b9", = false, = ["alloc", "lfn", "log"] }
= { = "https://github.com/emobotics-dev/embedded-fatfs.git", = "4565a3e3358e1b03c12b7f1b8c04483facbc45b9" }
= { = "https://github.com/emobotics-dev/embedded-fatfs.git", = "4565a3e3358e1b03c12b7f1b8c04483facbc45b9" }
= "0.4.2"
= "1"
= { = true }
= { = true }
[]
# esp-hal family (emobotics fork, pinned rev)
= { = "https://github.com/emobotics-dev/esp-hal.git", = "04646b65e3ef94d60f5e08cb24fed9e3cd77f9d0", = ["internal-heap-stats"] }
= { = "https://github.com/emobotics-dev/esp-hal.git", = "04646b65e3ef94d60f5e08cb24fed9e3cd77f9d0", = ["panic-handler", "custom-halt", "colors", "println"] }
= { = "https://github.com/emobotics-dev/esp-hal.git", = "04646b65e3ef94d60f5e08cb24fed9e3cd77f9d0" }
= { = "https://github.com/emobotics-dev/esp-hal.git", = "04646b65e3ef94d60f5e08cb24fed9e3cd77f9d0", = ["unstable"] }
= { = "https://github.com/emobotics-dev/esp-hal.git", = "04646b65e3ef94d60f5e08cb24fed9e3cd77f9d0", = ["log-04", "colors", "timestamp"], = false }
= { = "https://github.com/emobotics-dev/esp-hal.git", = "04646b65e3ef94d60f5e08cb24fed9e3cd77f9d0", = ["embassy", "esp-radio"] }
# Native threads and semaphores. esp-rtos exposes neither on its own surface —
# these are the primitives esp-radio's WiFi/BT internals use, registered by
# `esp_rtos::start()`. Examples only: the library must stay crates.io-resolvable.
= { = "https://github.com/emobotics-dev/esp-hal.git", = "04646b65e3ef94d60f5e08cb24fed9e3cd77f9d0" }
= { = "https://github.com/emobotics-dev/esp-hal.git", = "04646b65e3ef94d60f5e08cb24fed9e3cd77f9d0" }
# CoreS3 logging/panic (USB-Serial-JTAG)
= "1.0.0"
= { = "0.6.2", = ["log"] }
# Embassy
= { = "0.6.0", = ["time"] }
= { = "0.10.0", = ["nightly"] }
= "0.1"
= { = "0.9.1", = false, = ["dhcpv4", "proto-ipv4", "medium-ethernet", "tcp", "udp", "dns"] }
= "0.8"
= "0.5.1"
# Display
= "0.8.2"
= "0.1.3"
# BLE (coex). Held at 0.6 because esp-radio 0.18's BleConnector implements the
# bt-hci **0.8** traits while trouble-host 0.7 requires **0.9**. Verified by
# attempting the bump AND porting the demo, rather than by reading:
#
# - cargo resolves 0.7 happily and compiles bt-hci 0.8.1 and 0.9.0 side by
# side (semver-incompatible, so coexisting is legal). It is NOT a
# resolution failure, which is what makes this worth writing down.
# - the first errors are trouble-host 0.7's own API changes, and they are a
# red herring: `HostResources` gained the controller as its FIRST generic
# (`<C, P, CONNS, CHANNELS, ADV_SETS = 1, BONDS = 10>`), so the old
# `HostResources<DefaultPacketPool, 1, 1>` put the pool in the controller
# slot and produced a bogus `StaticPacketPool: ControllerCmdSync` error.
# - with the port applied (`HostResources<_, DefaultPacketPool, 1, 1>`,
# `.build()` → `Stack`, then `stack.runner()` / `stack.central()` instead
# of destructuring a `Host`), the REAL blocker appears and is unambiguous:
# BleConnector<'_>: bt_hci::transport::Transport is not satisfied
# BleConnectorError: From<bt_hci::FromHciBytesError> is not satisfied
# help: expected `bt_hci::FromHciBytesError`,
# found `bt_hci::FromHciBytesError`
# Identical paths on both sides is the two-versions-of-one-crate signature.
#
# So the bump is gated on esp-radio moving to bt-hci 0.9 — nothing on our side
# unblocks it, and the ble.rs port above is the whole of the other half.
#
# And it is esp-RADIO that gates it, not esp-hal: esp-radio 0.18.0 asks for
# `esp-hal ~1.1.0-rc.0`, which 1.1.2 already satisfies. Re-checked 2026-08-22,
# **no published esp-radio uses bt-hci 0.9** — 0.18.0 is the newest stable and
# even the 1.0.0-beta.0 prerelease still requires `bt-hci ^0.8.0` (and
# `esp-hal ~1.1.0`). There is nothing newer to move to yet; re-check esp-radio,
# not esp-hal, when revisiting this.
= { = "0.6.0", = ["default-packet-pool-mtu-255", "scan", "derive"] }
# LVGL (lvgl feature, demos only). Taken as a matched pair from one source:
# oxivgl-sys emits `oxivgl_render_scratch_*` C→Rust hooks whose Rust side lives in
# oxivgl, so resolving the two halves separately drifts them apart and the lvgl
# example fails to link (Cargo.lock is gitignored → every fresh resolve).
#
# On crates.io now that 0.8.0 carries `Ui`/`RenderConfig`/`FlushSync` — the git
# pin was only ever a bridge until that release existed. Pinned exactly and as a
# pair: 0.8.0 asks for oxivgl-sys 0.2.4, and the two halves must come from one
# source or the `oxivgl_render_scratch_*` hooks drift apart and the lvgl example
# fails to link.
= { = "=0.8.0", = ["esp-hal", "log-04", "rtos-sem"] }
= { = "=0.2.4", = false }
# misc
= "1.0.0"
= "0.9.3"
= "0.4"
= { = "2.1.1", = ["nightly"] }
[]
= "s"
[]
= 1
= 2
= false
= false
= "fat"
= "s"
= true