This is a design document. Both
dowel migrate verifyanddowel migrate importare implemented (60-cli.md); the current shape is recorded in 91-implementation-status.md.
The decision is ADR-0005. In short: no static translation; dynamic extraction only.
Migration tools in the Node ecosystem work because the source of truth is
declarative data — package.json and lock files. CMake’s source of truth
is a program, and the actual configuration exists only after running it in a
particular environment.
Attempts to read CMakeLists.txt syntactically and translate it break down
without exception on if(WIN32), find_package, and user-defined macros;
the cost of fixing the output exceeds a rewrite.
The hooks for extracting execution results as structured data already exist.
| Source | Extraction point | What you get |
|---|---|---|
| CMake | File API (codemodel v2, JSON) | targets, sources, includes, defines, links, per configuration |
| Meson | meson introspect |
the same, in tidier form |
| Bazel | aquery --output=proto |
the action graph itself |
| autotools | none (compile_commands.json only) |
per-translation-unit flag lists; target structure is lost |
The CMake File API is the first-class interface IDEs actually use; reading from it is the only sensible path.
What can be extracted is one projection of a program: a snapshot under a specific OS, configuration, and dependency-resolution result. Conditionals are lost. The output is a draft, not a finished artifact.
Moreover, this system deliberately rejects things existing systems allowed (ABI mismatches become failures, and so on). A faithful migration can therefore produce a manifest that is legitimately rejected, and how that is handled needs to be settled as UX.
verifyA crude migration result can do harm. The worst path: a manifest is generated with every flag flattened and intent lost, gets committed as-is, and becomes a maintenance burden.
dowel migrate import # generate a draft from the File API (marked unverified)
dowel migrate verify # compare the existing system's compile_commands.json
# against our action set, and report the differences
verify is cheap to implement — the action graph already exists — and high
value. Migration becomes not a one-shot conversion but a continuous
equivalence check during incremental porting.
Being able to confirm mechanically that “this target is ported and generates compile arguments identical to the original environment” removes much of the psychological barrier to migrating.
Because dependency supply is delegated externally (ADR-0001), unported parts remain on the existing system and are consumed as external dependencies.
The unit of migration is therefore the target, not the whole project — which is what makes it incremental.
| Item | Cost | Value |
|---|---|---|
verify (compile_commands comparison) |
low | high |
| CMake File API import | medium | high |
| Meson introspect import | low | medium (Meson users have weak motivation to migrate) |
| Bazel aquery import | high | low (motivation exists but the scale assumptions differ) |
| Static translation | high | negative |
Start with verify; limit import to CMake.