microsoft / microsoft/vscode-cmake-tools
[Bug] CMake Tools doesn't apply environment overrides when using presets
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 1.7k
- Forks
- 546
- Avg merge
- 2d 16h
- Merged PRs (30d)
- 32
Description
Brief Issue Summary
CMake Tools is not applying environment overrides when reading CMake presets.
Yes, I found closed issues on the same subject, but they were closed without any action taken to correct this.
Example:
Having the preset:
{
"version": 6,
"cmakeMinimumRequired": {
"major": 3,
"minor": 26
},
"configurePresets": [
{
"name": "env-read",
"binaryDir": "dummy",
"generator": "Unix Makefiles",
"cacheVariables": {
"MY_TEST_VAR": "$env{MY_ENV_VAR}",
"MY_OTHER_VAR": "$env{MY_LOCAL_EVAR}",
"MY_ANOTHER_VAR": "$env{MY_DIRECT_EVAR}"
},
"environment": {
"MY_LOCAL_EVAR": "$env{MY_ENV_VAR}",
"MY_DIRECT_EVAR": "direct-value"
}
}
]
}
and the CMakeLists.txt:
cmake_minimum_required(VERSION 3.26)
project(dummy CXX)
message("MY_TEST_VAR: ${MY_TEST_VAR}")
message("MY_OTHER_VAR: ${MY_OTHER_VAR}")
message("MY_ANOTHER_VAR: ${MY_ANOTHER_VAR}")
message("ENV: MY_LOCAL_EVAR: $ENV{MY_LOCAL_EVAR}")
message("ENV: MY_ENV_VAR: $ENV{MY_ENV_VAR}")
message("ENV: MY_DIRECT_EVAR: $ENV{MY_DIRECT_EVAR}")
The CLI command to run the configure is this:
cmake --configure --preset=env-read
which gives this output:
Preset CMake variables:
MY_ANOTHER_VAR="direct-value"
MY_OTHER_VAR=""
MY_TEST_VAR=""
Preset environment variables:
MY_DIRECT_EVAR="direct-value"
MY_LOCAL_EVAR=""
MY_TEST_VAR:
MY_OTHER_VAR:
MY_ANOTHER_VAR: direct-value
ENV: MY_LOCAL_EVAR:
ENV: MY_ENV_VAR:
ENV: MY_DIRECT_EVAR: direct-value
If the command runs with a modified environment, it will be reflected:
MY_ENV_VAR="test" cmake --configure --preset=env-read
The output now becomes:
Preset CMake variables:
MY_ANOTHER_VAR="direct-value"
MY_OTHER_VAR="test"
MY_TEST_VAR="test"
Preset environment variables:
MY_DIRECT_EVAR="direct-value"
MY_LOCAL_EVAR="test"
MY_TEST_VAR: test
MY_OTHER_VAR: test
MY_ANOTHER_VAR: direct-value
ENV: MY_LOCAL_EVAR: test
ENV: MY_ENV_VAR: test
ENV: MY_DIRECT_EVAR: direct-value
However, Cmake Tools will not run the:
cmake [optional preset type argument] --preset=<preset name>
command (where the first argument denotes the type of the preset, if absent - configure), but instead will interpret the presets on its own and build the actual cmake command itself, thus ignoring environment set in the Settings | Cmake: Environment.
Environment overrides are ignored, because that environment is applied onlyto the final, constructed command AND NOT the process that constructs it.
For example:
- File | Preferences | Settings, section "Cmake: Environment", "Add Item", add: Item: MY_ENV_VAR, Value: from-settings
- Select the "env-read" preset in Cmake extension as a configure preset
- Run configure
Output:
[main] Configuring project: cmake-test
[driver] NOTE: You are configuring with preset env-read, but there are some overrides being applied from your VS Code settings.
[proc] Executing command: /usr/bin/cmake -DMY_TEST_VAR= -DMY_OTHER_VAR= -DMY_ANOTHER_VAR=direct-value -G "Unix Makefiles"
[cmake] MY_TEST_VAR:
[cmake] MY_OTHER_VAR:
[cmake] MY_ANOTHER_VAR: direct-value
[cmake] ENV: MY_LOCAL_EVAR:
[cmake] ENV: MY_ENV_VAR: from-settings
[cmake] ENV: MY_DIRECT_EVAR: direct-value
[cmake] -- Configuring done (0.0s)
[cmake] -- Generating done (0.0s)
[cmake] -- Build files have been written to:
Note that the environment was applied to the CMakeLists.txt (which is being processed via cmake, with the modified environment), but NOT to the preset (which is being read and processed by the extension, and the extension only sees the environment as it was known at the time of launching VS Code.
It is incorrect as it gives different results from IDE versus when running the way it was intended by cmake.
I understand this somehow is by design, as the preset can use VS Code variables, but it must apply defined environment overrides already during reading presets, and not only when running a constructed cmake command.
Files:
CMake Tools Diagnostics
{
"os": "linux",
"vscodeVersion": "1.98.2",
"cmtVersion": "1.20.53",
"configurations": [
{
"folder": "/home/dss-dev/cmake-test",
"cmakeVersion": "3.26.5",
"configured": true,
"generator": "Unix Makefiles",
"usesPresets": true,
"compilers": {
"CXX": "/opt/rh/gcc-toolset-13/root/usr/bin/c++"
}
}
],
"cpptoolsIntegration": {
"isReady": true,
"hasCodeModel": false,
"activeBuildType": "",
"buildTypesSeen": [
""
],
"requests": [],
"responses": [],
"partialMatches": [],
"targetCount": 0,
"executablesCount": 0,
"librariesCount": 0,
"targets": []
},
"settings": [
{
"communicationMode": "automatic",
"useCMakePresets": "always",
"configureOnOpen": false
},
{
"communicationMode": "automatic",
"useCMakePresets": "always",
"configureOnOpen": false
}
]
}
Debug Log
[main] Configuring project: cmake-test
[main] Saving open files before configure/build
[driver] Start configure
[driver] Running pre-configure checks and steps
[driver] NOTE: You are configuring with preset env-read, but there are some overrides being applied from your VS Code settings.
[cmakefileapi-driver] Configuring using preset
[cmakefileapi-driver] Invoking CMake /usr/bin/cmake with arguments ["-DMY_TEST_VAR=","-DMY_OTHER_VAR=","-DMY_ANOTHER_VAR=direct-value","-S<home folder>/cmake-test/cmake-local","-B<home folder>/cmake-test/cmake-local/dummy","-G","Unix Makefiles"]
[proc] Executing command: /usr/bin/cmake -DMY_TEST_VAR= -DMY_OTHER_VAR= -DMY_ANOTHER_VAR=direct-value -S<home folder>/cmake-test/cmake-local -B<home folder>/cmake-test/cmake-local/dummy -G "Unix Makefiles"
[proc] with environment: {"HOSTNAME":"","OLDPWD":"<home folder>","KUBERNETES_PORT_443_TCP_PROTO":"tcp","KUBERNETES_PORT_443_TCP_ADDR":"<IP removed>","container":"oci","KUBERNETES_PORT":"tcp://<IP removed>:443","PWD":"<home folder>/.vscode-server/bin/<ID removed>","HOME":"<home folder>","KUBERNETES_SERVICE_PORT_HTTPS":"443","KUBERNETES_PORT_443_TCP_PORT":"443","KUBERNETES_PORT_443_TCP":"tcp://<IP removed>:443","SHELL":"/bin/bash","TERM":"xterm","SHLVL":"2","KUBERNETES_SERVICE_PORT":"443","PATH":"<home folder>/.vscode-server/bin/<ID removed>/bin/remote-cli:<home folder>/.local/bin:<home folder>/bin:/opt/rh/gcc-toolset-13/root/usr/bin:/usr/share/Modules/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin","KUBERNETES_SERVICE_HOST":"<IP removed>","_":"/usr/bin/cat","VSCODE_CWD":"<home folder>/.vscode-server/bin/<ID removed>","VSCODE_NLS_CONFIG":"{\"userLocale\":\"en\",\"osLocale\":\"en\",\"resolvedLanguage\":\"en\",\"defaultMessagesFile\":\"<home folder>/.vscode-server/bin/<ID removed>/out/nls.messages.json\",\"locale\":\"en\",\"availableLanguages\":{}}","VSCODE_HANDLES_SIGPIPE":"true","VSCODE_ESM_ENTRYPOINT":"vs/workbench/api/node/extensionHostProcess","VSCODE_HANDLES_UNCAUGHT_ERRORS":"true","LD_LIBRARY_PATH":"/opt/rh/gcc-toolset-13/root/usr/lib64:/opt/rh/gcc-toolset-13/root/usr/lib","MODULES_RUN_QUARANTINE":"LD_LIBRARY_PATH LD_PRELOAD","LANG":"C.utf8","HISTCONTROL":"ignoredups","REMOTE_CONTAINERS_SOCKETS":"[\"/tmp/.X11-unix/X5\",\"<home folder>/.gnupg/S.gpg-agent\"]","PCP_DIR":"/opt/rh/gcc-toolset-13/root","which_declare":"declare -f","MODULES_CMD":"/usr/share/Modules/libexec/modulecmd.tcl","USER":"<user ID>","CMAKE_C_COMPILER_LAUNCHER":"ccache","REMOTE_CONTAINERS_IPC":"/tmp/vscode-remote-containers-ipc-<GUID removed>.sock","CMAKE_BUILD_PARALLEL_LEVEL":"10","LOADEDMODULES":"","MAIL":"/var/spool/mail/<user ID>","CTEST_PARALLEL_LEVEL":"16","MANPATH":"/opt/rh/gcc-toolset-13/root/usr/share/man::","MODULEPATH":"/etc/scl/modulefiles:/usr/share/Modules/modulefiles:/etc/modulefiles:/usr/share/modulefiles","LOGNAME":"<user ID>","MODULEPATH_modshare":"/usr/share/Modules/modulefiles:2:/etc/modulefiles:2:/usr/share/modulefiles:2","MODULESHOME":"/usr/share/Modules","PKG_CONFIG_PATH":"/opt/rh/gcc-toolset-13/root/usr/lib64/pkgconfig","INFOPATH":"/opt/rh/gcc-toolset-13/root/usr/share/info","HISTSIZE":"1000","CMAKE_CXX_COMPILER_LAUNCHER":"ccache","CPU_VCORES_AVAIL":"11","LESSOPEN":"||/usr/bin/lesspipe.sh %s","BASH_FUNC_which%%":"() { ( alias;\n eval ${which_declare} ) | /usr/bin/which --tty-only --read-alias --read-functions --show-tilde --show-dot $@\n}","BASH_FUNC_module%%":"() { unset _mlshdbg;\n if [ \"${MODULES_SILENT_SHELL_DEBUG:-0}\" = '1' ]; then\n case \"$-\" in \n *v*x*)\n set +vx;\n _mlshdbg='vx'\n ;;\n *v*)\n set +v;\n _mlshdbg='v'\n ;;\n *x*)\n set +x;\n _mlshdbg='x'\n ;;\n *)\n _mlshdbg=''\n ;;\n esac;\n fi;\n unset _mlre _mlIFS;\n if [ -n \"${IFS+x}\" ]; then\n _mlIFS=$IFS;\n fi;\n IFS=' ';\n for _mlv in ${MODULES_RUN_QUARANTINE:-};\n do\n if [ \"${_mlv}\" = \"${_mlv##*[!A-Za-z0-9_]}\" -a \"${_mlv}\" = \"${_mlv#[0-9]}\" ]; then\n if [ -n \"`eval 'echo ${'$_mlv'+x}'`\" ]; then\n _mlre=\"${_mlre:-}${_mlv}_modquar='`eval 'echo ${'$_mlv'}'`' \";\n fi;\n _mlrv=\"MODULES_RUNENV_${_mlv}\";\n _mlre=\"${_mlre:-}${_mlv}='`eval 'echo ${'$_mlrv':-}'`' \";\n fi;\n done;\n if [ -n \"${_mlre:-}\" ]; then\n eval `eval ${_mlre} /usr/bin/tclsh /usr/share/Modules/libexec/modulecmd.tcl bash '\"$@\"'`;\n else\n eval `/usr/bin/tclsh /usr/share/Modules/libexec/modulecmd.tcl bash \"$@\"`;\n fi;\n _mlstatus=$?;\n if [ -n \"${_mlIFS+x}\" ]; then\n IFS=$_mlIFS;\n else\n unset IFS;\n fi;\n unset _mlre _mlv _mlrv _mlIFS;\n if [ -n \"${_mlshdbg:-}\" ]; then\n set -$_mlshdbg;\n fi;\n unset _mlshdbg;\n return $_mlstatus\n}","BASH_FUNC_switchml%%":"() { typeset swfound=1;\n if [ \"${MODULES_USE_COMPAT_VERSION:-0}\" = '1' ]; then\n typeset swname='main';\n if [ -e /usr/share/Modules/libexec/modulecmd.tcl ]; then\n typeset swfound=0;\n unset MODULES_USE_COMPAT_VERSION;\n fi;\n else\n typeset swname='compatibility';\n if [ -e /usr/share/Modules/libexec/modulecmd-compat ]; then\n typeset swfound=0;\n MODULES_USE_COMPAT_VERSION=1;\n export MODULES_USE_COMPAT_VERSION;\n fi;\n fi;\n if [ $swfound -eq 0 ]; then\n echo \"Switching to Modules $swname version\";\n source /usr/share/Modules/init/bash;\n else\n echo \"Cannot switch to Modules $swname version, command not found\";\n return 1;\n fi\n}","BASH_FUNC_scl%%":"() { if [ \"$1\" = \"load\" -o \"$1\" = \"unload\" ]; then\n eval \"module $@\";\n else\n /usr/bin/scl \"$@\";\n fi\n}","BASH_FUNC_ml%%":"() { module ml \"$@\"\n}","DISPLAY":":5","REMOTE_CONTAINERS_DISPLAY_SOCK":"/tmp/.X11-unix/X5","REMOTE_CONTAINERS":"true","BROWSER":"<home folder>/.vscode-server/bin/<ID removed>/bin/helpers/browser.sh","ELECTRON_RUN_AS_NODE":"1","VSCODE_IPC_HOOK_CLI":"/tmp/vscode-ipc-<GUID removed>.sock","VSCODE_L10N_BUNDLE_LOCATION":"","MY_LOCAL_EVAR":"","MY_DIRECT_EVAR":"direct-value","MY_ENV_VAR":"from-settings","GCC_COLORS":""}
[cmake] MY_TEST_VAR:
[cmake] MY_OTHER_VAR:
[cmake] MY_ANOTHER_VAR: direct-value
[cmake] ENV: MY_LOCAL_EVAR:
[cmake] ENV: MY_ENV_VAR: from-settings
[cmake] ENV: MY_DIRECT_EVAR: direct-value
[cmake] -- Configuring done (0.0s)
[cmake] -- Generating done (0.0s)
[cmake] -- Build files have been written to: <home folder>/cmake-test/cmake-local/dummy
[cmakefileapi-parser] Read reply folder: <home folder>/cmake-test/cmake-local/dummy/.cmake/api/v1/reply
[cmakefileapi-parser] Found index files: ["cache-v2-3d764781a7727628ddaf.json","cmakeFiles-v1-b919a90970c95c6760e0.json","codemodel-v2-b2665e6746614fc67ee4.json","directory-.-f5ebdc15457944623624.json","index-2025-04-03T07-24-01-0270.json","toolchains-v1-33d48a7908c5ad2bff7c.json"]
[cache] Reading CMake cache file <home folder>/cmake-test/cmake-local/dummy/CMakeCache.txt
[cache] Parsing CMake cache string
[extension] [5388] cmake.configure finished (returned 0)
[cache] Reading CMake cache file <home folder>/cmake-test/cmake-local/dummy/CMakeCache.txt
[cache] Parsing CMake cache string
Additional Information
No response
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the attached CMakePresets.json and CMakeLists.txt and reproduce the difference between cmake --configure --preset=env-read and configuring through CMake Tools with the CMake: Environment setting. Then trace the preset configure path that emits the logged CMake arguments. Done means environment overrides affect preset expansion as well as the final CMake process, with behavior matching direct CMake invocation.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- cmake, typescript, vscode
- Domain
- build-system, developer-experience, tooling
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 38/100