Improvements to Accuracy and Performance of Linux IntelliSense

Erika

January 10th, 2020

This blog post was written by Paul Maybee, a Principal Software Engineer on the C++ Cross-Platform Team.

Accurate C++ IntelliSense requires access to the C++ headers that are referenced by C++ source files. For Linux scenarios the headers referenced by a Linux MSBuild or CMake project are copied to Windows by Visual Studio from the Linux device (or VM, or Docker container, or WSL system) being targeted for the build. Visual Studio then uses these headers to provide IntelliSense. If the headers are not the correct versions, for example they are gcc headers rather than clang headers, or C++11 headers rather than C++17 headers, then the IntelliSense may be incorrect, which can be very confusing to the user. Also, for some scenarios the number of headers can be very large and so the copy can take a long time. Visual Studio 2019 version 16.5 Preview 1 improves both the accuracy and the performance of the header copy, providing better IntelliSense for Linux projects.

Remote Connections

When making a new remote connection using the Visual Studio connection manager the old default behavior was to copy the headers from the remote Linux target to a local Windows cache location immediately after adding the connection. This is no longer done or necessary. Headers are now copied on demand when opening a Linux project or configuring CMake for a Linux target. The copy now occurs in the background.

The connection manager’s remote headers dialog has also changed. Caching for each connection can be explicitly enabled or disabled. The default for a new connection is to be enabled. The user may also select a connection and:

Press the Update button to on-demand download the headers for the connection.

Press the Delete button to delete the header cache for the connection.

Press the Explore button to open the connection’s cache location in the file browser.

Linux Project Properties

There are three new Linux project properties to help the user control header copying: Remote Copy Include Directories, Remote Copy Exclude Directories, and IntelliSense Uses Compiler Defaults.

Remote Copy Include Directories : a list of directories to copy (recursively) from the Linux target. This property affects the remote header copy for IntelliSense but not the build. It can be used when “IntelliSense Uses Compiler Defaults” is set to false. Use Additional Include Directories under the C/C++ General tab to specify additional include directories to be used for both IntelliSense and build.

: a list of directories to copy (recursively) from the Linux target. This property affects the remote header copy for IntelliSense but not the build. It can be used when “IntelliSense Uses Compiler Defaults” is set to false. Use under the C/C++ General tab to specify additional include directories to be used for both IntelliSense and build. Remote Copy Exclude Directories : a list of directories NOT to copy. Usually this is used to remove subdirectories of the include directories. For example, suppose /usr/include was to be copied. The copy would also contain /usr/include/boost if it were present. However, if the current project does not reference boost then copying it is a waste of time and space. Adding /usr/include/boost to the excluded list avoids the unnecessary copy.

: a list of directories NOT to copy. Usually this is used to remove subdirectories of the include directories. For example, suppose was to be copied. The copy would also contain if it were present. However, if the current project does not reference boost then copying it is a waste of time and space. Adding to the excluded list avoids the unnecessary copy. IntelliSense Uses Compiler Defaults: a Boolean value indicating whether the compiler referenced by this project (see below) should be queried for its default list of include locations. These are automatically added to the list of remote directories to copy. This property should only be set to false if the compiler does not support gcc-like parameters. Both gcc and clang compiler sets support querying for the include directories (e.g. “g++ -x c++ -E -v -std=c++11”).

Other C++ project properties also affect header copying:

C/C++ General tab: Additional Include Directories, C Compiler and C++ Compiler.

C/C++ Language tab: C Language Standard and C++ Language Standard

The paths found in the Additional Include Directories list are used for both IntelliSense and build. The (non-project) paths in the Additional Include Directories list are automatically added to the list of directories to copy. The compilers are normally filled out automatically by the selection of Platform Toolset in the General tab. However, in some cases a more precise specification of the compiler is necessary, for example specifying “clang8” when “clang” binds to clang version 6 on the Linux target. The compiler configured here is queried for its default include directory list. The C Language Standard and C++ Language Standard selected are passed as a parameters to the compiler (e.g. -std=c++11) when it is queried. In the past all headers for both c and clang were copied to the local cache. By making use of the compiler and standard selected in the project properties Visual Studio can identify exactly those headers that are necessary for the project and thus avoid copying unnecessary headers.

CMake Project Properties

CMake projects have similar settings to control headers copying under the “Advanced Settings” section of the CMake Settings Editor:

The paths in the list of remote include directories can be formatted with environment variables and ’~’, for example: ”/usr/include/clang8;$HOME/include;~/myinclude”. For CMake projects the compiler name and language standard are retrieved from the CMake cache. The value of MAKE_C_COMPILER (and CMAKE_CXX_COMPILER) are used to identify the compiler to query. The C_STANDARD (CXX_STANDARD) property are used to identify the standard in effect.

Copying the Headers

The set of directories to be copied is computed each time a project is opened or one of the project properties described above is modified.

In cases where the remote target is updated independently, for example a new version of gcc is installed, then Visual Studio’s cache will be out-of-date with respect to that target. Visual Studio will not detect that the remote headers have changed. In this case the user must request a cache scan by selecting Project > Scan Solution from the main Visual Studio menu, which will cause the directories to be sync’d with the remote target even if they had been previously copied.

Give us your feedback

Do you have feedback on our Linux tooling or CMake support in Visual Studio? We’d love to hear from you to help us prioritize and build the right features for you. We can be reached via the comments below, Developer Community, email (visualcpp@microsoft.com), and Twitter (@VisualC). The best way to suggest new features or file bugs is via Developer Community.