Imported from sunzhen222/convert-keil-to-cmake (
SKILL.md). Install upstream withnpx skills add sunzhen222/convert-keil-to-cmake. Copyright stays with the author.
Convert Keil to CMake
Create a maintainable CMake build that preserves the selected Keil target's firmware behavior while separating compiler-specific implementation details.
Workflow
- Locate
.uvprojx,.uvoptx, startup files, scatter files, linker scripts, device packs, and existing build scripts. Do not edit generated IDE output directories. - Ask for a target only when the project contains multiple materially different targets and the requested target cannot be inferred. Otherwise select the single target or the clearly named production target and state the choice.
- Run
python scripts/inspect_uvprojx.py <project.uvprojx> [--target <name>]from this skill directory. Treat its JSON as an inventory, then verify paths and target/file overrides against the XML. Pay particular attention toruntime,memory_regions,existing_outputs,keil_build, andsource_usage. - Read references/conversion-reference.md before translating toolchain, CPU/FPU/ABI, optimization, scatter, library, startup, assembly, or RTOS settings.
- Copy assets/cmake/check_build_env.py into the project root as
check_build_env.py, then tailor its required and optional tools to the selected generator, languages, toolchain, artifact steps, and existing project conventions. When Python is not a viable project prerequisite, generate an equivalentcheck_build_env.baton Windows orcheck_build_env.shon POSIX instead. Generate one appropriate checker, not every variant. - Run the project-local checker before configuring. It must only inspect and report: it must not download software, invoke an installer or package manager, modify
PATH, or change machine-wide state. Never install missing prerequisites without the user's explicit authorization. - If required tools are missing, or the user requests no build, continue with generation-only, unverified mode when static project information is sufficient. Generate and statically review the migration files, but do not claim configure, compile, link, artifact, ELF, or parity validation. Report every missing prerequisite and the exact later verification commands.
- Reuse assets/cmake/ as a starting point when the repository has no stronger CMake convention. Use
stm32-flash.ld.inonly for a simple single-Flash/single-RAM layout. Replace every@...@placeholder; remove unused sections instead of leaving speculative code. - Generate a root
CMakeLists.txt, a GNU Arm toolchain file, and a small host build wrapper only when useful. Follow the repository's established naming and directory organization. - In normal validation mode, configure from a new build directory with
CMAKE_EXPORT_COMPILE_COMMANDS=ON, build, and compare sources, defines, includes, artifacts, memory layout, and size with Keil. Fix errors rather than suppressing warnings globally. - Run
python scripts/validate_conversion.py <project.uvprojx> <build/compile_commands.json> --elf <build/firmware.elf>after a successful link. Pass each intentional compiler-specific replacement as--source-substitution <keil-path>=<gnu-path>. - After generation and any available validation, create a concise project-root
CMAKE_BUILD.mdfrom assets/cmake/CMAKE_BUILD.md.in. Write every user-facing section in both Chinese and English, replace all placeholders, and ensure commands and artifact paths exactly match the generated project. Do not report the migration complete until this handoff document exists.
Authorization and Completion Status
- Treat software installation as a separate, state-changing action. Detecting a missing command does not authorize installing or downloading it. Ask for explicit authorization before using an installer or package manager, changing
PATH, or modifying machine-wide configuration; state the proposed tool, source, scope, and command first. - Do not make an installation quiet, unattended, or hidden merely to keep the migration moving. If authorization is not given, preserve the diagnostic result and use generation-only mode when possible.
- Report validated only after the project checker passes, a clean configure and build succeeds, the firmware links, expected artifacts exist, and
validate_conversion.pypasses. - Report generated, unverified when CMake files and the project checker were generated and statically reviewed but any required configure, build, link, artifact, ELF, or parity check was not completed. This is a usable handoff state, not a validated migration.
- If even generation cannot be completed because essential project data or a parsing runtime is unavailable, report the concrete blocker instead of labeling the result generated or validated.
User Handoff Document
- Keep
CMAKE_BUILD.mdshort and task-oriented. Include only status, prerequisites/environment check, exact configure/build commands, primary artifacts, and important validation limits or remaining differences. - Present Chinese first and English immediately after it within each section. Do not create separate language files, duplicate long logs, narrate the migration history, or paste full source/define/include inventories.
- State either 已验证 / validated or 已生成、未验证 / generated, unverified prominently. In unverified mode, name the missing tools and unperformed checks without implying successful compilation.
- Describe each primary artifact by path and purpose, normally
.elf,.bin,.hex,.map, and any project-specific packaged image that is actually generated. Do not document hypothetical outputs. - Use commands that can be copied from the repository root. Include the project-local environment checker command before configure/build, and document optional clean, flash, or package commands only when those actions exist.
Conversion Rules
- Make the Keil target the source of truth for source membership and preprocessor settings. Make the MCU datasheet, pack files, startup code, and scatter file the source of truth for architecture and memory layout.
- Preserve source groups as readable CMake module lists. Use explicit lists for startup, HAL/LL drivers, middleware ports, syscall stubs, and other mutually exclusive implementations. Use
GLOBonly where the repository already accepts automatic discovery. - Keep compiler-specific files separate. Select GNU startup/assembly, GCC RTOS ports, and GCC syscall implementations; never compile Arm Compiler and GCC variants together.
- Prefer target-scoped CMake commands. Keep CPU flags identical across C, C++, assembly, and link steps. Enable ASM explicitly.
- Translate the scatter file deliberately. Reuse an existing validated GNU
.ldscript when present; otherwise create one from the actual memory regions and section rules. Never infer flash origin from total device capacity alone. - Preserve optimization and debug intent, but do not mechanically copy Arm Compiler flags into GCC. Record any semantic mismatch that cannot be reproduced exactly.
- Avoid conflicting CMake build-type flags such as an implicit
-O3followed by a target-Os. Control or document the effective final optimization and do not addNDEBUGunless it matches the selected Keil target. - Map Keil MicroLIB deliberately. Inspect
printf, floating-point formats,fputc,_write, semihosting markers, and available Flash before selecting newlib, newlib-nano,_printf_float,nosys, or a GCC syscall implementation. - Generate
.elf,.bin,.hex,.map, and a size report. Preserve additional packaging, signing, OTA, flashing, or simulator steps only when they already belong to the project or the user requests them. - Keep the project-local environment checker diagnostic-only and version-controlled with the generated build files. Required tools must match the normal build path; deployment/debug tools should be optional unless the requested build inherently requires them.
- Do not change application C/C++ code merely to make migration easier unless a genuine compiler portability issue is found. Keep such fixes small and explain them.
- Do not delete or rewrite the Keil project unless explicitly requested. A migration should remain auditable.
Required Validation
- Confirm every intended Keil source is represented once and every excluded or alternate-toolchain source remains excluded.
- Confirm defines and include directories, including file/group overrides where relevant.
- Confirm MCU core, instruction set, FPU, float ABI, startup object, interrupt vectors, linker entry point, and memory origin/length.
- Confirm the selected RTOS, CMSIS, HAL/LL, USB, filesystem, C library, and syscall variants.
- Classify diagnostics as migration errors, pre-existing application warnings, or expected runtime/toolchain warnings. Do not hide behavior-affecting warnings.
- In validated mode, build from a clean directory and require successful configure and link. Inspect the map and size output; verify
.binand.hexgeneration. In generation-only mode, mark all of these checks unperformed. - When Keil CLI is available, build the same target and compare error count, warnings that affect behavior, code/data size, and key symbols. If hardware is available and flashing is authorized, perform the project's normal smoke check.
- Report what was migrated, validation performed, remaining differences, and exact build command.
- Verify
CMAKE_BUILD.mdis bilingual, concise, free of template placeholders, and consistent with the actual generator, toolchain file, target name, build directory, and artifact paths. - Compare Flash load bytes and RAM components separately. State whether reported RAM includes
.data,.bss, heap, stack, retained sections, or runtime state.
Repository Style Baseline
When no local convention exists, use the style derived from the reference project:
- one readable root build definition with named directory variables and module source collections;
- Ninja out-of-source builds with
arm-none-eabi-gcc,objcopy, andsize; - a dedicated simulator/host branch only if the original repository already supports it;
- explicit device definitions, GCC middleware ports, startup assembly, and linker script;
- post-build firmware formats and map/size diagnostics;
compile_commands.json, linker-scriptLINK_DEPENDS, and declared post-build byproducts;- a thin wrapper for clean, build, package, copy, or flash actions, keeping optional deployment actions separate from compilation.