casaroli opened a new issue, #19549:
URL: https://github.com/apache/nuttx/issues/19549
### Description
# NuttX CMake vs. Make Build-System Gap Analysis
Keeping this here for visibility and so that we can AI-fix this quickly soon.
## Scope
This document records a static comparison of the NuttX CMake and GNU Make
build systems in this workspace.
- **Make** is treated as the compatibility-complete reference implementation.
- **CMake** has a substantial working core, but is not feature- or
coverage-complete.
- No files were changed while conducting the analysis.
- No configuration-specific build was run: `nuttx/.config` was absent in
this checkout. Findings are based on the build graph, configuration code, and
mechanical directory inventory.
## What CMake already supports
The CMake implementation has an established core:
- Out-of-source configuration from a board `defconfig`.
- Kconfig value export into CMake.
- Architecture toolchain selection before `project()`.
- Kernel, system, and application library graphs with link grouping.
- Flat and protected build handling, including `nuttx_user`.
- Standard firmware output formats (`bin`, `hex`, `srec`, disassembly).
- Linker-script preprocessing, maps, manifest generation, and board-specific
post-build hooks.
- CMake configuration targets including `menuconfig`, `qconfig`,
`olddefconfig`, `resetconfig`, `distcleanconfig`, and `savedefconfig`.
The principal issue is not the absence of a CMake foundation; it is
incomplete compatibility coverage compared with Make.
## Confirmed gaps
| Priority | Gap | Evidence and impact |
|---|---|---|
| P0 | **11 architectures are Make-only** | `nuttx/arch/CMakeLists.txt:41`
always enters `arch/${CONFIG_ARCH}`. The following architectures have
`src/Makefile` but no `CMakeLists.txt`: `avr`, `ceva`, `hc`, `mips`, `misoc`,
`or1k`, `renesas`, `sparc`, `x86`, `z16`, and `z80`. `arch/avr` has no CMake
toolchain implementation either. Those configurations cannot be built through
CMake. |
| P0 | **Board coverage is incomplete** | The CMake top level rejects a
selected board when neither the board directory nor its `../common` directory
has a `CMakeLists.txt` (`nuttx/CMakeLists.txt:269-272`). For example,
`boards/arm/at32/at32f437-mini` has 12 Make-supported defconfigs and no CMake
files; its parent has no `common/CMakeLists.txt`. Its configurations cannot be
configured via CMake. |
| P0 | **119 application directories have Make rules but no CMake
counterpart** | Inventory: `apps` has 643 Makefile directories, 535 CMake
directories, and 119 Make-only directories. `nuttx_add_subdirectory()` only
descends into child directories that contain `CMakeLists.txt`
(`nuttx/cmake/nuttx_add_subdirectory.cmake:31-49`), so those apps are not
visible to CMake. |
| P0 | **Database/SQLite is absent from CMake** | Make supports
`apps/database` through `Directory.mk` (`apps/database/Makefile:23-25`).
`apps/CMakeLists.txt:49-81` does not add `database`, and neither
`apps/database` nor `apps/database/sqlite` contains a `CMakeLists.txt`. SQLite
cannot be selected or built through CMake. |
| P0 | **External-tree Kconfig integration is disabled** | CMake hard-codes
`EXTERNALDIR=dummy` and `DRIVERS_PLATFORM_DIR=dummy`
(`nuttx/CMakeLists.txt:223-228`; `nuttx/cmake/menuconfig.cmake:26-29`). Make
detects `external/Kconfig` and uses `EXTERNALDIR=external` when present
(`nuttx/tools/Unix.mk:78-86`). External Kconfig/source integration has no
equivalent in CMake. |
| P1 | **Custom board/chip support is unfinished** | CMake explicitly labels
the current behavior “Unsupported custom board/chips yet, workaround”
(`nuttx/CMakeLists.txt:344-349`). `boards/CMakeLists.txt:23-33` leaves
custom-board Kconfig handling as TODO/commented logic. |
| P1 | **No generic CMake equivalent of deployment/export targets** | Make
provides generic `flash`/`download`, `bootloader`, `clean_bootloader`, and
`export` targets (`nuttx/tools/Unix.mk:606-637`, `:810-819`). Some individual
CMake ports define similar board-specific targets, but no generic extension
mechanism matches Make’s `FLASH` abstraction, and no general export target
exists. Kernel export is explicitly TODO (`nuttx/CMakeLists.txt:940-943`). |
| P1 | **Configuration target coverage is smaller** | Make supports
`config`, `oldconfig`, `olddefconfig`, `menuconfig`, `nconfig`, `qconfig`,
`gconfig`, and `savedefconfig` (`nuttx/tools/Unix.mk:732-807`). CMake has
`menuconfig`, `qconfig`, `olddefconfig`, reset/clean helpers, and
`savedefconfig`, but no equivalents for `config`, `oldconfig`, `nconfig`, or
`gconfig`. |
| P1 | **Protected combined HEX is known broken** | CMake states that
`nuttx_combined.hex` “does not seem to be generating a functional hex file”
(`nuttx/CMakeLists.txt:926-935`). This needs repair and a regression test. |
| P2 | **U-Boot deployment behavior differs** | Both systems generate
`uImage`; Make optionally copies it to writable `/tftpboot`
(`nuttx/tools/Unix.mk:590-597`). CMake leaves this as a TODO
(`nuttx/CMakeLists.txt:740-752`). An explicit opt-in deployment target would
preserve out-of-tree safety while restoring functionality. |
| P2 | **CMake documentation is effectively absent** |
`Documentation/components/cmake.rst:5-6` says CMake documentation will be added
“in the future.” There is no support matrix, target reference,
known-incompatibilities list, or migration guide. |
| P2 | **Known configurations are documented as Make-only** |
`rv-virt:python` is documented as not working with CMake
(`Documentation/applications/interpreters/python/index.rst:29-36`), as is
`sim/wamr` (`Documentation/applications/interpreters/wamr/index.rst:17-24`). |
## Application coverage details
The 119 Make-only application directories include notable groups such as:
- Audio / benchmarks / crypto: `audioutils/morsey`, `audioutils/rtttl-c`,
`benchmarks/sd_bench`, `crypto/wolfssl`.
- Database: `database`, `database/sqlite`.
- Games: `NXDoom`, `brickmatch`, `match4`, `snake`.
- Graphics: `ft80x`, `libjpeg`, `nxglyphs`, `nxwidgets`, `nxwm`, `pdcurs34`,
`screenshot`, `slcd`, `tiff`, `twm4nx`.
- Interpreters: `duktape`, `ficl`, `luajit`, Python, `toywasm`, `wasm3`, and
Lua modules.
- ML / DSP: CMSIS, Darknet, NNabla Runtime, Liquid DSP.
- Networking: `bare`, `cwebsocket`, `mdns`, `nanopb`, `thttpd/cgi-src`, and
`xedge`.
- System: `libffi`, `psmq`, `settings`, and `smf`.
- Wireless: `gs2200m` and `iwpan`.
- Language-specific examples: several Rust, Zig, Swift, D, and Nim examples.
Some entries are nested tests or helpers. Each should be triaged before
being declared unsupported, but all have Make build metadata without a CMake
equivalent.
## Root cause: different discovery models
Make discovers applications dynamically through `apps/Make.defs` and
per-directory `Make.defs`/`Kconfig` metadata. CMake uses a fixed category list
in `apps/CMakeLists.txt:49-81`, then descends only into directories with a
`CMakeLists.txt`.
Consequences:
1. Adding a Make app is often sufficient for Make discovery.
2. Adding a CMake app requires a `CMakeLists.txt` at every necessary level.
3. Parent CMake lists must include the subtree.
4. Kconfig generation must include the subtree.
5. Special behavior must be ported: generated code, ROMFS, builtins,
modules, external dependencies, or non-C language compilation.
This is the primary cause of continuing CMake coverage drift.
## Recommended remediation sequence
### 1. Establish a support contract and coverage reporting
- Define CMake support levels: configure, compile, link, artifact creation,
deployment, and export.
- Add an automated report for selectable architectures, boards, and
applications that have Make metadata but no CMake path.
- Publish a CMake support matrix and classify intentionally unsupported
configurations.
### 2. Restore configuration/discovery parity
- Implement `EXTERNALDIR` and platform-driver discovery.
- Complete custom board/chip Kconfig and source integration.
- Add missing top-level app categories, beginning with `database`.
### 3. Close architecture and board coverage incrementally
- Port complete vertical slices: toolchain, architecture sources, chip
selection, linker scripts, a representative board, and a build test.
- Prioritize actively maintained hardware rather than attempting every
historical port at once.
- For intentionally unsupported targets, fail early with a precise message
and a Make fallback instruction.
### 4. Port applications by reusable feature family
- Start with high-value components: SQLite, WolfSSL, Python/WAMR, popular
graphics stacks, and language-specific application support.
- Create reusable CMake abstractions for recurring Make-only behavior before
porting each individual application.
### 5. Restore operational parity
- Define a generic board extension API for `flash`, `download`, bootloader
build/clean, and post-build packaging.
- Implement export packaging or document its supported replacement.
- Repair `nuttx_combined.hex` and add a regression test.
### 6. Add Make-vs-CMake parity tests
For each supported `board:config`, compare:
- successful configuration and final link;
- final artifact set;
- enabled builtin registrations and modules;
- Kconfig visibility;
- flat, protected, and kernel build modes where applicable.
## Best first deliverable
The highest-value initial project is an automated **board / architecture /
application CMake coverage report**, paired with a maintained support matrix.
This gives the project an objective baseline, allows prioritization, and
prevents new Make-only additions from silently expanding the gap.
### Verification
- [x] I have verified before submitting the report.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]