C/C++ extension for Visual Studio Code

Post updated on 10/26/2016 to add a section about how to use task extensibility to build your C++ code
Post updated on 8/29/2016, Aug release of C++ extension. Introduced support for debugging Windows apps and improvements to Clang format
Post updated on 7/26/2016, July release of C++ extension. Introduced support for lldb for Mac and other debugging improvements
File issues on our GitHub repo. We monitor this daily!

Today is an exciting day for all of us on the C++ team here at Microsoft! We love that we offer the great development experience C and C++ developers enjoy in Visual Studio on Windows, but at the same time we realize that some of you, for your own reasons, have chosen Linux or OS/X as your primary development platform, so you cannot utilize Visual Studio for your development needs. Today we are announcing a Preview of a product for your C/C++ editing and debugging needs on Linux and OS/X: the C/C++ extension to Visual Studio Code.

C_Cpp_icons

For those of you who are not aware of Visual Studio Code, Visual Studio Code is a new choice of tool in the Visual Studio family of products which combines the simplicity of a code editor with what developers need for their code-edit-debug cycle. The current Visual Studio Code experience only provides basic syntax highlighting support via the C/C++ text made bundle, this preview version of the C/C++ extension introduces a better language service experience with support for code-navigation and the ability to debug C/C++ applications but given this is a preview release there are a few caveats to this experience!

In the rest of this post I will assume that you have downloaded and configured Visual Studio Code, and also the preview of the C/C++ extension that we are announcing here. This post has the following sections, feel free to jump to the one that interests you most.

Using the C/C++ code-editing aids in Visual Studio Code

As soon as a folder containing C/C++ sources is loaded into Visual Studio Code the language service engine kicks in and the tag-parser starts parsing the source directory generating an offline database to store symbol information (browse.VC.db file). Look for the flaming red platform icon (Win32 in the figure below) which denotes parsing in progress.

parsing

Once the symbol data base population is complete you are ready to try out the preview experience of the language services portion of this extension. The preview experience for the language service experience currently introduces support for code navigation through the following feature set.

Navigate to a particular symbol within the same source file (Ctrl + P, @Symbol Name)

Symbol@

Navigate to a particular symbol across source files (Ctrl + P, #Symbol Name)

Symbol2hash

Go to definition (F12)

GoToDef#1

Peek definition (Alt + F12)

peek

Cntrl + Hover

cntrl_hover

Given that this is indeed a preview experience there are a few caveats. While Go to definition and Peek definition will work for most part it’s currently not wired up to work for locals. This is primarily because the tag-parser currently does not parse function bodies. Also given there is currently no semantic analysis that is performed, Go to definition and Peek definition as  only some-what accurate as they are based upon text parsing and matching of symbols. We are working hard to make this happen.

While the current language service experience is designed to provide you value out-of-the-box, one can further improve the experience by  providing a little more information about include paths not in your working directory opened in Visual Studio Code. In the future we will use the same mechanism to ask for more details to drive other language service features such as Auto-Complete.

As you traverse through your source code you will notice some headers are squiggled. The reason why these headers are squiggled is because we were not able to find them in the current source or sub source folders opened in Visual Studio Code. Hovering over these squiggles a light bulb action will appear which will allow you to specify the path on disk for these headers in a properties file known as the ‘c_cpp_properties.json’ file as shown in the figure below.

path

Adding your include directories to the “includePath” property in this file for the specific configuration you are interested in will help drive a more complete and accurate language service experience.

Fuzzy Auto-Complete for C/C++ code

This C/C++ extension in Visual Studio Code also introduces a preview version of a fuzzy Auto-Complete for C/C++ code. It’s based on an enhanced tag-parser approach, in other words no semantic analysis, so while it is not quite accurate it will still provide you more than what single-file intellisense provides you today. Additionally, this fuzzy intellisense approach will work pretty well for straight up C code so try it out and let us know what you think!

intellij

Code formatting with clang-format

You can now format your C/C++ code with clang-format from inside Visual Studio Code. Currently clang-format needs to be
installed manually and the path for clang-format needs to be added to user settings in Visual Studio Code. You can learn more here about how to setup clang-format for your code-formatting experience.

formating

Debugging your C/C++ application in Visual Studio Code

This extension also introduces great support for debugging your C++ program with Visual Studio Code. You’ll be able to use all of the standard debugging capabilities that you’re familiar with, including setting and hitting breakpoints, stepping, inspecting variables, and viewing the call stack. Beyond that, you’ll also able to take advantage of some advanced debugging capabilities, including function breakpoints, expression evaluation, conditional breakpoints, and core dump debugging.

The extension currently supports Windows MinGW/Cygwin debugging, Linux and Mac debugging with both LLDB and GDB debug engines.

debugging all up

The debugging experience currently only works out-of-the-box for Linux – Ubuntu 14.04 (x64). We are working on OS X support as well, the current experience requires manual installation steps and has some limitations. Debugging on windows with VSCode for C/C++ code is currently not supported.

Getting set up

Before you can get started debugging C++ code in Visual Studio Code, you’ll need to set a few things up. Navigate to the Debug View by clicking on the debug icon on far left toolbar. Hit the “Settings” gear icon in the debug pane and select “C++ Launch (GDB).” This will bring up the launch.json file.

The launch.json file defines a set of configurations that tell the debugger how to interact with your built application. We include two configurations by default—one which shows the properties necessary for launching the application from VS Code, and the other which shows the properties necessary for attaching to an already running process. Hovering over a property name will show a tooltip that describes the property and possible values, but minimally you will need to update the “program” property to have the program name and path. You can learn more about the properties in the launch.json file and how to use them by reading the VS Code debugging documentation.

Once your launch.json file is properly configured, you’re ready to debug a C++ program. Note that VS Code will not build your program (but simply debug the built program) unless you also create a task.json file and set it to the preLaunchTask property in the launch.json file.

Function Breakpoints

Function breakpoints enable you to break execution at the beginning of a function rather than on a particular line of code. To set a function breakpoint in VS Code, right click in the breakpoints pane and click “Add Function Breakpoint,” then type the name of the function on which you’d like to break.

function breakpoint

Expression Evaluation

Debugging C++ code often requires more than simply viewing the value of variables at a breakpoint. The C++ extension for VS Code has support for evaluating expressions in several spaces. You can type an expression into the Watch pane, and it will be evaluated when a breakpoint is hit. Note that this has side effects—an expression that modifies the value of a variable will modify that value for the duration of program execution. If you’d like to view the value of an expression that is a part of your code, you can hover over any expression in the editor while stopped at a breakpoint and the data tip will show the evaluated expression. If you only want to evaluate an expression once (rather than having it in the Watch pane), you can simply type the expression in the Debug Console.

expression evaluation

Conditional Breakpoints

Right clicking on a breakpoint and selecting “Edit breakpoint” will open a peak window in your editor. Type a condition (eg. “i > 15”) and that breakpoint will only activate and break execution when that condition evaluates to true. Conditional breakpoints are indicated by a breakpoint symbol that has the black equals sign. Hovering over a conditional breakpoint will show its value.

conditional breakpoint

Core Dump Debugging

The extension also offers the ability to debug using a memory dump. To do this, add the “coreDumpPath” property to the C++ Launch configuration in your launch.json file and set it to the path to your core dump. This will even work for multi-threaded programs and x86 programs being debugged on a x64 machine.

GDB, LLDB and MI commands

You can also use the debug console with the “-exec” command to execute GDB, LLDB commands directly (be careful though—executing LLDB, GDB commands directly in the debug console is untested and may crash VS Code in some cases). A full introduction to debugging in VS Code is available here.

Process Picker to attach the debugger to a running process easily

VS Code now enables you to select a process from a list of running processes rather than needing to manually enter the process id into the launch.json. To use the process picker:

  • Enter the path to the executable in the “program” field of the launch.json file.
  • If you are using an existing launch.json file, you will need to enter ${command.pickProcess} in the “processId” field.
  • If you allow VS Code to generate the launch.json, it set processId to ${command.pickProcess} by default.

    PROC

  • When you start debugging, focus will go to the VS Code quick launch bar, and a list of running processes will appear. You can filter the list by typing the name of the process you want to attach to, and hit enter  to select it.

    PROC2

Building your C++ application with Visual Studio Code

The task extensibility in Visual Studio Code exists to automate tasks like building, packaging, testing and deploying. This post is going to demonstrate how using task extensibility in Visual Studio Code you can call compilers, build systems and other external tasks through the help of the following sections:

Installing C/C++ build tools

In order to build your C++ code you need to make sure you have C/C++ build tools (compilers, linkers and build systems) installed on your box. If you can already build outside Visual Studio Code you already have these tools setup, so you can move on to the next section.

To obtain your set of C/C++ compilers on Windows you can grab the Visual C++ build tools SKU. By default these tools are installed at ‘C:\Program Files (x86)\Microsoft Visual C++ Build Tools’. You only need to do this if you don’t have Visual studio installed. If you already have Visual Studio installed, you have everything you need already.

If you are on a Linux platform which supports apt-get you can run the following commands to make sure you grab the right set of tools for building your C/C++ code.

sudo apt-get install g++
sudo apt-get install clang

On OS X, the easiest way to install the C++ build tools would be to install Xcode command line tools. You can follow this article on the apple developer forum. I would recommend this instead of installing clang directly as Apple adds special goodies to their version of the clang toolset. Once installed you can run these commands in a terminal window to determine where the compiler and build tools you need were installed.

xcodebuild -find make
xcodebuild -find gcc
xcodebuild -find g++
xcodebuild -find clang
xcodebuild -find clang++

Creating a simple Visual Studio Code task for building C/C++ code

To follow this specific section you can go ahead and download this helloworld C++ source folder. If you run into any issues you can always cheat and download the same C++ source folder with a task pre-configured.

If you are just picking up C++ and want to understand different components involved in performing a simple build you can review this guide.

In Visual Studio Code tasks are defined for a workspace and Visual Studio Code comes pre-installed with a list of common task runners. In the command palette (Ctrl+Shift+P (Win, Linux), ⇧⌘P (Mac)) you can type tasks and look at all the various task related commands.

commands

On executing the ‘Configure Task Runner’ option from the command palette you will see a list of pre-installed tasks as shown below, in the future we will grow the list of task runners for popular build systems but for now go ahead and pick up the others template from this list.

preinstalledtasks

This will create a tasks.json file in your .vscode folder with the following content:

{
    // See https://go.microsoft.com/fwlink/?LinkId=733558
    // for the documentation about the tasks.json format
    "version": "0.1.0",
    "command": "echo",
    "isShellCommand": true,
    "args": ["Hello World"],
    "showOutput": "always"
}
Setting it up for Windows

The easiest way to setup Visual Studio Code on Windows for C/C++ building is to create a batch file called ‘build.bat’ with the following commands:

@echo off
call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" x64     
set compilerflags=/Od /Zi /EHsc
set linkerflags=/OUT:hello.exe
cl.exe %compilerflags% helloworld.cpp /link %linkerflags%

Please note that the location of vcvarsall.bat file which sets up the right environment for building could be different on your machine. Also if you are using the Visual C++ build SKU, you will need to call the following command instead:

call “C:\Program Files (x86)\Microsoft Visual C++ Build Tools\vcbuildtools.bat” x64

Once the build script is ready you can then modify your tasks.json to directly call your batch file on Windows by making the following changes to the automatically generated tasks.json file.

{  
   // See https://go.microsoft.com/fwlink/?LinkId=733558
   // for the documentation about the tasks.json format
   "version": "0.1.0",
   "windows": {
      "command": "build.bat",
      "isShellCommand": true,
      "showOutput": "always"
   }

Initiate a build by bringing up the command palette again and executing the ‘Run Build Task’ command.

build

This should initiate the build for our C++ application and you should be able to monitor the build progress in the output window.

output

Now even though this is a Windows specific example you should be able to re-use the same series of steps to call a build script on other platforms as well.

Calling Clang and GCC from Visual Studio Code task for building C/C++ code

Alright let us now see how we can achieve building our C/C++ application without calling an external batch file using some popular toolsets like GCC and Clang directly without a build system in play.

To follow this specific section you can go ahead and download this helloworld C++ source folder. If you run into any issues you can always cheat and download the same C++ source folder with a task pre-configured.

Tasks.json allow you to specify qualifiers like the one below for ‘OS X’. These qualifiers similar will allow you create specific build configurations for your different build targets or as shown in this case for different platforms.

  "OS X": {
        "command": "clang++",
        "args": [
            "-Wall",
            "helloWorld.cpp",
            "-v"
          ],
        "isShellCommand": true,
        "showOutput": "always",
        "problemMatcher": {
            "owner": "cpp",
            "fileLocation": [
                "relative",
                "${workspaceRoot}"
            ],
            "pattern": {
                "regexp": "^(.*):(\\d+):(\\d+):\\s+(warning|error):\\s+(.*)$",
                "file": 1,
                "line": 2,
                "column": 3,
                "severity": 4,
                "message": 5
            }
  }

Another thing to highlight in this snippet is the ‘problemMatcher’ section. Visual Studio Code ships with some of the most common problem matchers out of the box but many compilers and other tools define their own style of errors and warnings. Need not worry you can create your own custom problem matcher as well with Visual Studio Code. This site which helps test out regex online might also come in handy.

The pattern matcher here will work well for Clang and GCC toolsets so just go ahead and use them. The figure below shows them in effect when you initiate the show problems command in Visual Studio Code (Cntrl+Shift+M (Win, Linux), ⇧⌘M (Mac)).

error

Calling Makefiles using Visual Studio Code task extensibility

Similar to the manner how you configure tasks.json to call the compiler, you can do the same for makefiles. Take a look at the sample tasks.json below, the one new concept in this tasks.json file is the nesting of tasks. Both ‘hello’ and ‘clean’ are tasks in the makefile where as ‘compile w/o makefile’ is a separate task but this example should show you how you can setup tasks.json in cases where there are
multiple build systems at play. You can find the entire sample here.

Note this is an OSX, Linux specific example but to obtain the same behavior on Windows you can replace ‘bash’ with ‘cmd’ and ‘args’ with ‘/C’.

{
    // See https://go.microsoft.com/fwlink/?LinkId=733558
    // for the documentation about the tasks.json format
   "version": "0.1.0",
    "osx": {
        "command": "bash",
        "args": ["-c"],
        "isShellCommand": true,
        "showOutput": "always",
        "suppressTaskName": true,
        "options": {
            "cwd": "${workspaceRoot}"
        },
        "tasks": [
            {
                "taskName": "hello",
                "args": [
                    "make hello"
                ],
                "isBuildCommand": true
            },
            {
                "taskName": "clean",
                "args": [
                    "make clean"
                ]
            },
            {
                "taskName": "compile w/o makefile",
                "args": [
                    "clang++ -Wall -g helloworld.cpp -o hello"
                ],
                "echoCommand": true
            }
        ]
    }
}

Two more things to mention here is that whichever task you associate the ‘isBuildCommand’ with becomes your default build task in Visual Studio Code. In this case that would be the ‘hello’ task. If you would like to run the other tasks bring up the command palette and choose ‘Run Task’ option.

task1

task2

Then choose the individual task to run e.g. ‘clean’ task. Alternatively, you can also wire the build task as a different key binding. For doing so bring up File -> Preferences -> Keyboard shortcuts and add the following key binding to your task. Bindings currently only exist for build and test tasks but an upcoming fix in the October release will allow bindings for individual tasks as well.

[
  {
        "key": "f7",
       "command": "workbench.action.tasks.build"
    }
]

Calling MSBuild using Visual Studio Code task extensibility

MSBuild is already a pre-installed task that Visual Studio Code comes with. Bring up the command palette and choose MSBuild, this will create the following task.json it should be easy then to add your MSBuild solution, project name to the ‘args’ section and get going.

{
 // See https://go.microsoft.com/fwlink/?LinkId=733558
// for the documentation about the tasks.json format
  "version": "0.1.0",
  "command": "msbuild",
  "args": [
        // Ask msbuild to generate full paths for file names.
        "/property:GenerateFullPaths=true"
    ],
    "taskSelector": "/t:",
    "showOutput": "silent",
    "tasks": [
    {
            "taskName": "build",

            // Show the output window only if unrecognized errors occur.
            "showOutput": "silent",
           
            // Use the standard MS compiler pattern to detect errors, warnings and infos
           "problemMatcher": "$msCompile"
        }
    ]
}

Calling CMake using Visual Studio Code extensibility

There are currently two Visual Studio Code extensions in the Visual Studio Code marketplace. The first extension provides the language service support for CMake the latter will allow for building your CMake targets. For a good CMake experience in Visual Studio Code install both extensions.

extensions

Once configured you should be able to build specific CMake targets and perform other CMake actions as illustrated in the figure below.

cmake

A quick demo demonstrating  the C/C++ experience:


You can watch the higher quality full channel 9 discussion on VS Code here.

Help us get better!

This particular release of the C/C++ extension for Visual Studio Code is a start and we’ll need your help to make this a full experience. If you’d like to help us build the best C/C++ experience on any platform, you can join our Cross-Platform C++ Insiders group where you’ll be able to talk directly to the product team and influence our investment in this area. We also recognize that there are some immediate asks you’re likely to have, so please go ahead and add them to  Visual Studio Code user-voice and we would love your help in prioritizing them just right.

Thank you for reading to the end, I look forward to seeing the bugs you report, and the requests you want us to consider. If you have any questions or comments that don’t fit a bug or a feature request, please drop me a comment below – our team is monitoring this blog comments and of-course don’t forget to go download the C/C++ extension for VS Code.