Fix IntelliSense in projects with compiler arguments in CMAKE_<LANG>_COMPILER #4627
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
This changes visible behavior
The following changes are proposed:
The purpose of this change
Fix IntelliSense in projects with compiler arguments in
CMAKE_<LANG>_COMPILERby passing those arguments, newly exposed in the file API by CMake 4.3, to cpptools so it can properly determine system include paths and built-in preprocessor macro definitions.Other Notes/Information
Problem
In CMake, the
CCor similar environment variables as well as theCMAKE_<LANG>_COMPILERvariables set by toolchain files can, in addition to the compiler path, contain mandatory command line arguments that must be passed to every invocation of the compiler. Previously, these arguments were not exposed in the File API, therefore CMake Tools as an IntelliSense configuration provider had no way to pass them on tocpptools, thereforecpptoolswould call the compiler without them when trying to determine system include paths and built-in preprocessor macro definitions, potentially resulting in non-working code navigation.For example, for building for embedded systems with different CPU architectures we use toolchain files with lines like
where the referenced config file contains arguments like
--target,--sysroot,-stdlib++-isystemthat influence include paths and definitions. Currently, Visual Studio Codecpptoolscalls the compiler without these arguments when trying to determine the include paths and definitions, and gets back wrong values related to the host platform instead of the embedded system.Steps to Reproduce
Making a generic minimal reproducing example is a bit tricky because CMake expects working compilers (including sysroots). Here is something that works for me on an x86_64 Linux system with Clang 18 installed (Ubuntu 20.04,
clang-18package from official archive.ubuntu.com/security.ubuntu.com):CMakeLists.txt:
toolchain.cmake:
CMakePresets.json:
{ "version": 6, "configurePresets": [ { "name": "Test", "generator": "Ninja", "binaryDir": "${sourceDir}/output", "toolchainFile": "toolchain.cmake" } ] }main.c:
/usr/include/i386-linux-gnu/something.h:
Steps to reproduce
./output/test; echo $?to get the expected result42.file output/testconfirms that it was compiled for i386.Actual result
#include <something.h>has red squiggly underlines. Ctrl-clicking on it does nothing.helloshows no tooltip.hellodoes work and takes me to its definition in …/i386-linux-gnu/something.h. I would expect it to fail as well.-target i386-linux-gnuarguments have made it from CMake to cpptools, in particular the C/C++ diagnostics show the wrongsystem include: /usr/include/x86_64-linux-gnufor main.c.Expected result
helloshows a tooltip “int hello”.<something.h>orhelloopens …/i386-linux-gnu/something.h."compilerFragments": ["-target i386-linux-gnu"]for main.c.system include: /usr/include/i386-linux-gnufor main.c.Proposed Solution
CMake has just merged an addition to the file API to expose these arguments, to be released in CMake 4.3. I therefore propose the attached commits to retrieve them from the file API and pass them on to cpptools.
Only the last two commits are part of this change, the rest are #4620, which is required to actually be able to test with CMake 4.3 (so don’t use the combined diff for review, but the individual commits). But if there are objections to that, I will of course rework it. This change does not strictly depend on #4620, some of the added tests will just be skipped without it.
An update to vscode-cmake-tools-api is required, submitted in microsoft/vscode-cmake-tools-api#15, so there is a dependency version bump in package.json. CONTRIBUTING.md tells me to ping “our team” in that case, but I don’t know who that is (maybe @gcampbell-msft?).
Open Questions
I am not sure what to do about the use of
shlex.split(), see comments in cpptools.ts:471. Possible options:shlex.splitto be what I would expect and what is needed here. However I fear that would break other things, because presumably the current behavior, which is explicitly tested for in test/unit-tests/shlex.test.td, was introduced for a reason in support parsing substring and also substrings with single quote and space #1663.Any preferences? Any comment from @elahehrashedi who wrote that behavior?