CMakeParams
An editable view of the current CMakeCache, in the side bar, with the sections and the widgets you declare.

What this extension does
A CMake project exposes its options through the cache: BUILD_SHARED_LIBS, CMAKE_BUILD_TYPE, and the dozens of MYAPP_* switches you added yourself. Reaching them means either cmake-gui, a flat list of several hundred NAME=VALUE rows where your five interesting options are lost, or editing CMakeCache.txt by hand and hoping the reconfigure picks it up.
CMakeParams puts those options in a side bar view, organized the way your project is organized:
- you declare sections in your workspace settings, one per concern, Build, Features, Third party, whatever fits
- each parameter gets the widget that matches it, a checkbox for a boolean, a combo or a radio group for a list of choices, a slider for a bounded number, a file picker for a path
- you change values, the modifications stay staged and visible, nothing touches the build until you press Apply
- on apply,
CMakeCache.txt is patched and CMake Tools reconfigures the project with the kit or the preset you already selected
Everything you do not declare is still there, grouped by name prefix in collapsible sections, so the view never hides a variable from you. The reverse also holds: it never shows one that does not exist, so a section whose parameters are absent from the cache is simply not displayed.
Like CMakeGraph, CMakeParams never parses CMakeLists.txt. It reads the CMake File-Based API, so it shows what CMake itself reports, and falls back on a CMakeCache.txt parse when no API reply exists yet.
What it looks like
CMAKE PARAMS ⟳ 📁
┌──────────────────────────────────────────────┐
│ 12 / 333 parameters │
│ Filter parameters… X │
│ ☐ Advanced ☐ Internal ☑ Unlisted ☐ Auto │
│ BUILD /home/me/proj/build CONFIG Debug │
├──────────────────────────────────────────────┤
│ ▾ Build 2 1 mod. │
│ Build type │
│ [ Release ▾ ] ↺ │
│ Shared libraries │
│ [x] ON │
│ ▾ My application 3 │
│ Worker threads │
│ [======●=========] 8 │
│ Assets folder │
│ [ /home/me/proj/assets ] [ … ] │
│ ▸ CMAKE 47 │
├──────────────────────────────────────────────┤
│ 1 pending modification [ Apply ] [Discard] │
└──────────────────────────────────────────────┘
Features
- Side bar view: the panel lives in its own activity bar container, next to the explorer, and can be dragged to the bottom panel where it switches to a two column layout
- Your sections: declared in the settings, filled by an explicit list of parameters, by a regex, or by both
- Widgets:
checkbox, combo, radio, slider, number, text, textarea, path, file, color, readonly
- Automatic widgets: when you do not declare one, the cache entry decides.
BOOL becomes a checkbox, an entry carrying a STRINGS property becomes a combo, PATH and FILEPATH get a browse button, a numeric value gets a number field. CMAKE_BUILD_TYPE gets its usual four choices even though CMake does not declare them
- Staged modifications: shown in the section headers, in the view title bar and in the status bar, applied only when you ask
- Status bar: a parameter can be mirrored as a status bar button showing the label of its current value, clicking it offers its choices at the top of the window
- Filter: searches the name, the value and the help string of every parameter, cleared by the button at the right of the box or by Escape
- Advanced and internal entries: hidden by default, one toggle away
- Live sync: a configure run from anywhere else refreshes the view
Commands
| Command |
Description |
CMake Params: Focus the parameters view |
Reveal the view in the side bar |
CMake Params: Apply the modified parameters |
Write the pending values and configure (ctrl+alt+enter in the view) |
CMake Params: Discard the pending modifications |
Drop every staged edit |
CMake Params: Reload the CMake cache |
Read CMakeCache.txt again |
CMake Params: Edit the sections in settings.json |
Jump to CMakeParams.sections |
The title bar of the view keeps one of them, Reload. Apply and Discard are not there: they belong to the footer, which only exists while something is pending, so they show up exactly when they mean something. The rest stays in the command palette.
Settings example
Everything lives in CMakeParams.sections, in the .vscode/settings.json of your project. Here is a complete one, for an imaginary application whose options are prefixed MYAPP_.
{
"CMakeParams.sections": [
{
"title": "Build",
"params": [
{
"name": "CMAKE_BUILD_TYPE",
"label": "Build type",
"widget": "combo",
"options": ["Debug", "Release", "RelWithDebInfo", "MinSizeRel"]
},
{
"name": "BUILD_SHARED_LIBS",
"label": "Shared libraries",
"widget": "checkbox",
"description": "Build the libraries as shared objects"
},
{
"name": "CMAKE_INSTALL_PREFIX",
"label": "Install prefix",
"widget": "path"
}
]
},
{
"title": "My application",
"params": [
{
"name": "MYAPP_THREADS",
"label": "Worker threads",
"widget": "slider",
"min": 1,
"max": 32,
"step": 1
},
{
// Same list of choices, shown as three buttons instead of a drop down
"name": "MYAPP_LOG_LEVEL",
"label": "Log level",
"widget": "radio",
"options": [
{ "value": "0", "label": "Silent" },
{ "value": "1", "label": "Errors" },
{ "value": "2", "label": "Verbose" }
]
},
{
"name": "MYAPP_RENDERER",
"label": "Renderer",
"widget": "combo",
"options": ["opengl", "vulkan", "metal"]
},
{ "name": "MYAPP_ASSETS_DIR", "label": "Assets folder", "widget": "path" },
{ "name": "MYAPP_LOG_FILE", "label": "Log file", "widget": "file" },
{ "name": "MYAPP_THEME_COLOR", "label": "Theme color", "widget": "color" }
]
},
{
// No explicit list here, the regex takes every matching entry
"title": "Features",
"match": "^MYAPP_USE_"
},
{
"title": "Toolchain",
"collapsed": true,
"match": "^CMAKE_(C|CXX)_COMPILER$"
}
],
// The rest is optional, these are the defaults
"CMakeParams.applyMode": "configure",
"CMakeParams.autoApply": false,
"CMakeParams.showUnlisted": true,
"CMakeParams.showAdvanced": false
}
With that file, the view shows Build and My application with your labels and widgets, Features filled automatically with every MYAPP_USE_* switch as checkboxes, a collapsed Toolchain, then the rest of the cache grouped by prefix.
Choosing between a value in a list
Two widgets take the same options, so switching between them is a one word change:
| Widget |
Rendering |
Good for |
combo |
a drop down |
a long list, or a value you rarely change |
radio |
one button per choice, wrapping on several lines if needed |
two to four choices you want to read and switch at a glance |
{ "name": "MYAPP_LOG_LEVEL", "label": "Log level", "widget": "radio",
"options": [
{ "value": "0", "label": "Silent" },
{ "value": "1", "label": "Errors" },
{ "value": "2", "label": "Verbose" }
] }
Each choice carries the two things it needs:
| Key |
Role |
value |
what is written in CMakeCache.txt, so what CMake finally sees |
label |
the friendlier text shown in the panel, and on the status bar button by default |
statusBarLabel |
a shorter text for the button alone, where space is scarce |
A choice whose label is missing, empty or blank is displayed with its value, so { "value": "vulkan" } reads vulkan in the panel. When the two are the same for every choice, the short form says it in one line:
"options": ["opengl", "vulkan", "metal"]
A choice without a usable value is dropped rather than rendered broken, and a value is never trimmed, since it goes to the cache verbatim, while a label is.
When you omit options, both widgets fall back on the STRINGS property of the cache entry, the one you declare in CMake with:
set(MYAPP_RENDERER "vulkan" CACHE STRING "Rendering backend")
set_property(CACHE MYAPP_RENDERER PROPERTY STRINGS opengl vulkan metal)
With that property in place, the entry becomes a combo on its own, no settings needed. If neither options nor STRINGS gives a list, the widget degrades to a plain text field rather than showing you an empty control. And if the current cache value is outside the list, it is added as a last choice tagged not in the list, so a reconfigure never silently rewrites it.
Putting a parameter in the status bar
display says where a parameter shows up: in the view, in the VS Code status bar, or in both.
{
"name": "CMAKE_BUILD_TYPE",
"label": "Build type",
"statusBarLabel": "Build",
"widget": "radio",
"display": "both",
"options": [
{ "value": "Debug", "label": "Debug" },
{ "value": "RelWithDebInfo", "label": "Release with debug info", "statusBarLabel": "RelDbg" },
{ "value": "Release", "label": "Release", "statusBarLabel": "Rel" }
]
}
The button shows the label of the current value, never the variable name, which would eat the status bar for nothing. Clicking it opens the list of choices at the top of the window, the current one ticked; picking one stages it exactly as the view would, so the same Apply sends it to CMake. While a change is pending the button is highlighted and its text gains a *. A check and a cross then appear right after the buttons, to apply or discard the pending changes without opening the view; like the Apply of the view, they act on every pending change, those staged in the view included.
The name of the parameter and its help text live in the tooltip, where there is room for them.
Two levels of label
The status bar is cramped where the view is not, so both a parameter and an option take a second, shorter label. label serves everywhere by default, statusBarLabel overrides it on the button alone:
| Written |
In the view |
On the button |
"label": "Release with debug info" |
Release with debug info |
Release with debug info |
+ "statusBarLabel": "RelDbg" |
Release with debug info |
RelDbg |
On a parameter, statusBarLabel is a prefix rather than a replacement, since the button shows a value and a bare value can be cryptic:
| Written on the parameter |
Button |
| nothing |
RelDbg |
"statusBarLabel": "Build" |
Build: RelDbg |
The list opened by a click keeps the full labels, having the room the button lacks. Empty or blank, a statusBarLabel counts as absent and the label comes back.
| Value |
Where the parameter shows up |
pane |
in the view only, the default |
statusbar |
as a status bar button only, no row in the view |
both |
in the view and in the status bar |
Set on a section, display gives the default to every parameter it holds, the ones it lists and the ones its match collects, each one free to set its own. A parameter with no options gets an input box instead of a list, and a BOOL gets its two choices without declaring them.
Two cases are handled quietly: a parameter absent from the cache stays in the view, since a button with no value has nothing to offer, and a section whose parameters all went to the status bar no longer shows an empty box in the view.
Showing what the cache does not hold
By default the view hides what CMake does not report. alwaysShow says the opposite, on a parameter, on a whole section, or on both:
[
{
"title": "Not configured yet",
"alwaysShow": true, // the section stands even when empty,
"params": ["MYAPP_GPU", "MYAPP_CUDA_ARCH"] // and so do its parameters
},
{
"title": "Build",
"params": [
"CMAKE_BUILD_TYPE",
{ "name": "MYAPP_EXPERIMENTAL", "alwaysShow": true }, // this one only
{ "name": "MYAPP_LEGACY", "alwaysShow": false } // opts back out
]
}
]
A parameter kept this way reads as a greyed out row tagged not in cache. It carries the label and the description you gave it, has no value, and cannot be edited, since nothing backs it in CMakeCache.txt. It is there to tell you the option exists in your intent but not in this build, which is what a plain absence cannot say.
Set on a section, the flag does two things: the section survives with no parameter at all, and its listed parameters inherit the flag. A parameter can still opt back out with "alwaysShow": false.
A section
| Key |
Type |
Description |
title |
string |
Section title, also the key of its collapsed state |
collapsed |
boolean |
Initial collapsed state |
alwaysShow |
boolean |
Show the section even with nothing behind it, and pass the flag to its parameters |
display |
string |
pane, statusbar or both, the default for every parameter of the section |
match |
string |
Regex, every matching cache entry joins the section |
params |
array |
A cache variable name, or a widget definition |
params accepts a plain string when the defaults suit you, so "params": ["BUILD_TESTING", "BUILD_SHARED_LIBS"] is enough to get two checkboxes.
A parameter
| Key |
Type |
Description |
name |
string |
CMake cache variable name |
label |
string |
Shown instead of the variable name |
statusBarLabel |
string |
Short text prefixing the status bar button, as in Build: Rel |
description |
string |
Help text, defaults to the cache HELPSTRING |
alwaysShow |
boolean |
Show it whether the cache holds it or not, defaults to what the section says |
display |
string |
pane, statusbar or both, defaults to what the section says |
widget |
string |
One of the widgets listed above |
options |
array |
Choices of a combo or a radio, either plain strings or { value, label, statusBarLabel } objects, defaults to the cache STRINGS property |
min, max, step |
number |
Bounds of a slider or a number field |
Explicit params come first in the section, the match entries are appended after them.
Four rules are worth knowing:
- the view only ever shows what the cache really holds: a name absent from
CMakeCache.txt is not displayed, and a section left with nothing behind it disappears entirely rather than standing there empty. So a section can be declared for an option that only exists under some other configuration, and it simply shows up when that option does. alwaysShow reverses that for the cases where you would rather see the hole, see below
- a parameter listed explicitly is always shown when it exists, even when it is flagged
ADVANCED
- a
match section also shows the advanced entries, since you asked for that pattern yourself, but never the INTERNAL ones unless CMakeParams.showInternal is on
- a
match never takes a name an earlier section already holds, so two overlapping patterns stay predictable, and listing a parameter explicitly in an early section pulls it out of every later pattern
- two explicit
params lists may repeat the same name on purpose, which is how a Favourites section can show a parameter that also lives in its own section
The Advanced, Internal and Unlisted toggles of the toolbar drive what the automatic part of the view shows, never your own sections.
Which gives the Favourites idiom:
[
{ "title": "Favourites", "params": ["CMAKE_BUILD_TYPE", "MYAPP_THREADS"] },
{ "title": "Build", "match": "^CMAKE_" },
{ "title": "My app", "match": "^MYAPP_" }
]
CMAKE_BUILD_TYPE appears in Favourites and, since an explicit entry claims its name, no longer in Build. Repeat it explicitly in Build too if you want it in both.
All the settings
| Setting |
Default |
Description |
CMakeParams.sections |
[] |
The sections of the view |
CMakeParams.applyMode |
configure |
configure patches then reconfigures, cache only patches and lets the next configure pick the values up |
CMakeParams.autoApply |
false |
Apply on every widget change instead of waiting for the button |
CMakeParams.autoWidgets |
true |
Infer a widget from the cache entry type |
CMakeParams.showUnlisted |
true |
Show the entries not declared in a section |
CMakeParams.showAdvanced |
false |
Show the entries flagged ADVANCED |
CMakeParams.showInternal |
false |
Show the INTERNAL and STATIC entries |
CMakeParams.openOnStartup |
false |
Reveal the view on activation |
CMakeParams.collapsedSections |
{} |
Collapsed state, written by the view itself |
Requirements
- VS Code >= 1.80.0
- The CMake Tools extension, used to locate the build folder and to reconfigure
- A configured project, so a
CMakeCache.txt exists
License
MIT, see LICENSE.