Skip to content

Add automatic kit scanning functionality#351

Open
drook207 wants to merge 33 commits intoCivitasv:masterfrom
drook207:feature-add-kit-scanner
Open

Add automatic kit scanning functionality#351
drook207 wants to merge 33 commits intoCivitasv:masterfrom
drook207:feature-add-kit-scanner

Conversation

@drook207
Copy link
Copy Markdown

@drook207 drook207 commented Nov 1, 2025

Summary

This PR adds automatic CMake kit detection and scanning capabilities to
cmake-tools.nvim, making it easier to get started without manually
configuring compiler kits.

  • Automatically scans PATH for GCC and Clang compiler pairs
  • Detects compiler versions and finds matching C++ compilers
  • Discovers linkers (lld/ld) and toolchain files from environment
  • Saves discovered kits to ~/.config/cmake-tools/cmake-kits.json
  • Falls back to automatic scanning when no kits file exists
  • Adds CMakeScanForKits user command for manual scanning

Changes

  • New module: lua/cmake-tools/scanner.lua - Core kit scanning
    implementation with:

    • Compiler detection (GCC/Clang with version parsing)
    • Linker and toolchain file discovery
    • Custom JSON encoder for saving kits
    • PATH scanning and file utilities
  • Enhanced workflow: Automatic kit scanning when cmake-kits.json
    doesn't exist

  • User command: CMakeScanForKits for manual kit discovery

  • Default config: Set cmake_kits_path to ~/.config/cmake-tools/ by
    default

Test plan

  • Test automatic kit scanning on first run (no kits file)
  • Test manual CMakeScanForKits command
  • Verify GCC detection and version parsing
  • Verify Clang detection and version parsing
  • Check that generated kits file is valid JSON
  • Ensure linker and toolchain detection works correctly
  • Test with multiple compilers in PATH

Copy link
Copy Markdown
Collaborator

@lceWolf lceWolf left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like the idea, it replicates vscode's automatic kit detection 👍

Comment thread lua/cmake-tools/scanner.lua Outdated
Comment thread lua/cmake-tools/scanner.lua Outdated
Comment thread lua/cmake-tools/scanner.lua Outdated
Comment thread lua/cmake-tools/scanner.lua Outdated
Comment thread lua/cmake-tools/scanner.lua Outdated
Comment thread lua/cmake-tools/scanner.lua Outdated
Comment thread lua/cmake-tools/scanner.lua Outdated
Comment thread lua/cmake-tools/scanner.lua Outdated
Comment thread lua/cmake-tools/scanner.lua Outdated
Comment thread plugin/cmake-tools.lua
drook207 and others added 14 commits November 12, 2025 21:15
Tilde was not exapanded correctly, that results in creating the kits
file in creating the whole path in $PWD
- Add a test for kit scanning
- Add a test that checks if the file is present and if the kits could be
registered
- Complete reimplementation of the scanner functionality using nvim's
internal functions and a more generic approach.
- Add possibility to detect cross platform compiler
- Make the scanner more extensible
- Add unit tests for the new functions
@drook207
Copy link
Copy Markdown
Author

Hi guys, sorry that it took so long to continue, but as I got back to it i decided to start right from the beginning. I now use the nvim api for all the detection functions and I try to make it as extensible as possible. For now we are able to detect clang and gcc compiler on linux systems (And cross compilation compilers as well). I would suggest to do another PR for the WIndows MSVC and MinGW functionality.

@drook207 drook207 marked this pull request as ready for review April 11, 2026 08:20
@drook207
Copy link
Copy Markdown
Author

And one further question. Should we regenerate the cmake kits file entirely when the user command is triggered or should we append only new kits to the file?

Comment thread lua/cmake-tools/init.lua
-- if exists cmake-kits.json, kit is used to set
-- environmental variables and args.
local kits_config = kits.parse(const.cmake_kits_path, config.cwd)
local kits_config = kits.parse(const.cmake_config_path, config.cwd)
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this has to stay const.cmake_kits_path, right?

If so, do we need const.cmake_config_path at all?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The parse function expects not only a path but also the filename for the cmake kits. But I agree to leave the const.cmake_kits_path nil.
The questions is should we add the kits filename to the const table and concat the config path and the filename ?

Comment thread lua/cmake-tools/const.lua Outdated
Comment thread lua/cmake-tools/init.lua
cmake.register_autocmd()
cmake.register_autocmd_provided_by_users()
cmake.register_scratch_buffer(config.executor.name, config.runner.name)
if not vim.uv.fs_stat(const.cmake_kits_path) then
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maye we should add an option like we did for the presets to enable kit usage?

I think it might be worth keeping const.cmake_kits_path = nil as default and not change existing behaviour 🤔

Comment thread lua/cmake-tools/init.lua
cmake.register_autocmd_provided_by_users()
cmake.register_scratch_buffer(config.executor.name, config.runner.name)
if not vim.uv.fs_stat(const.cmake_kits_path) then
scanner.scan_for_kits()
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is a synchronous which can block the ui on startup. I think it is work running async, right?

Comment thread lua/cmake-tools/scanner.lua Outdated
end

local function get_path_executables()
local path_dirs = vim.split(vim.env.PATH or "", ":", { plain = true })
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this will break on windows

local seen = {}
local chains = {}

for exe in pairs(executables) do
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this filtering could be moved to the point of searching the paths variable

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't get what you mean, sorry. Could you maybe give a further explenation?

Comment thread lua/cmake-tools/scanner.lua Outdated
return {
c = (prefix or "") .. c_name,
cxx = (prefix or "") .. companions.cxx,
linker = (prefix or "") .. companions.linker,
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok thanks again for the docs. So should we maybe take out the linker detection complety? Becaus if I get it correct, vscode's cmake-tools does not add the linker at all. It is again a manual step.

Comment thread lua/cmake-tools/scanner.lua Outdated
Comment thread lua/cmake-tools/scanner.lua Outdated
kit.compilers.C = get_executable_path(tc.c)

if has_cxx then
kit.compilers.CXX = get_executable_path(tc.cxx)
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this can be called unconditionally. vim.fn.exepath should yield the correct result

@lceWolf
Copy link
Copy Markdown
Collaborator

lceWolf commented Apr 14, 2026

Hi guys, sorry that it took so long to continue, but as I got back to it i decided to start right from the beginning. I now use the nvim api for all the detection functions and I try to make it as extensible as possible. For now we are able to detect clang and gcc compiler on linux systems (And cross compilation compilers as well). I would suggest to do another PR for the WIndows MSVC and MinGW functionality.

No worries. Thats quite the topic to tackle and you are moving in a good direction! :)

I would suggest to do another PR for the WIndows MSVC and MinGW functionality.

Maybe I missed a detail, but I think the PR might break existing setups on windows since the PATH parsing does only work for Unix systems

@lceWolf
Copy link
Copy Markdown
Collaborator

lceWolf commented Apr 14, 2026

And one further question. Should we regenerate the cmake kits file entirely when the user command is triggered or should we append only new kits to the file?

How does the VS Code extension handle it?
I think stale kits should be removed

@drook207
Copy link
Copy Markdown
Author

And one further question. Should we regenerate the cmake kits file entirely when the user command is triggered or should we append only new kits to the file?

How does the VS Code extension handle it? I think stale kits should be removed

No they add and update only.
docs

I'm with you, stale kits should be cleaned if one triggers scan for kit manually

@drook207
Copy link
Copy Markdown
Author

Hi guys, sorry that it took so long to continue, but as I got back to it i decided to start right from the beginning. I now use the nvim api for all the detection functions and I try to make it as extensible as possible. For now we are able to detect clang and gcc compiler on linux systems (And cross compilation compilers as well). I would suggest to do another PR for the WIndows MSVC and MinGW functionality.

No worries. Thats quite the topic to tackle and you are moving in a good direction! :)

I would suggest to do another PR for the WIndows MSVC and MinGW functionality.

Maybe I missed a detail, but I think the PR might break existing setups on windows since the PATH parsing does only work for Unix systems

Yes you were right, did not see that. I fixed the path separator so the plugin should continue to work on windows. But I will ensure that tomorrow with my work PO

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants