vscode configuration c++ environment under mac

This article is reprinted from Using Clang in Visual Studio Code.

In this tutorial, you will configure Visual Studio Code on macOS to use the Clang/LLVM compiler and debugger.

After configuring VS Code, you will compile and debug a simple C++ program in VS Code. This tutorial will not teach you Clang or C++ languages. There are many good resources on the web for these topics.

If you encounter any issues, please feel free to submit an issue for this tutorial in the VS Code documentation repository.

Preparation

To successfully complete this tutorial, you must do the following:

  1. Install Visual Studio Code on macOS.
  2. Install the VS Code C++ extension. You can install C/C++ extensions by searching for “c++” in the extensions view (X).
    C/C++ extension

Make sure Clang is installed

Clang may already be installed on your Mac. To verify that it is, open a macOS Terminal window and enter the following command:

clang --version
  1. If Clang is not installed, enter the following command to install the command line developer tools:
xcode-select --install

Create Hello World

From the macOS terminal, create an empty folder named projects where you can store all your VS Code projects, then create a subfolder named helloworld, navigate to Go into it and open VS Code in that folder by entering the following command:

mkdir projects
cd projects
mkdir helloworld
cd helloworld
code.

The code . command opens VS Code in the current working folder, which will become your “workspace”. As you move through the tutorial, you will create three files in the .vscode folder in your workspace:

  • tasks.json (compiler build settings)
  • launch.json (debugger settings)
  • c_cpp_properties.json (compiler path and IntelliSense settings)

Add hello world source code file

In the File Explorer title bar, select New File and name the file helloworld.cpp.

New file title bar button

Paste the following source code:

#include <iostream>
#include <vector>
#include <string>

using namespace std;

int main()
{
    vector<string> msg {"Hello", "C++", "World", "from", "VS Code", "and the C++ extension!" };

    for (const string & amp; word : msg)
    {
        cout << word << " ";
    }
    cout << endl;
}

Now press ?S to save the file. Note that your files are listed in the FilesResourcesManager view (E) of the VS Code sidebar:

File Explorer

You can also enable automatic saving of file changes by checking AutoSave in the main File menu.

The activity bar on the edge of Visual Studio Code allows you to open different views such as Search, Source Code Management and Run & Debug. You’ll look at the Run view later in this tutorial. You can learn more about other views in the VSCode user interface documentation.

Note: When you save or open a C++ file, you may see a notification from the C/C++ extension about Insiders version availability, which allows you to test new features and fixes . You can ignore this notification by selecting X (Clear notification).

Intelligent sensingIntelliSense

In the helloworld.cpp file, hover over vector or string to see type information. After declaring the msg variable, start typing msg. just as you would when calling a member function. You should immediately see a completion list showing all member functions, and a window showing the msg object type information:

Statement completion IntelliSense

You can press the Tab key to insert selected members. Then, when you add the opening bracket, you will see information about the parameters required by the function.

Run helloworld.cpp

Remember that C++ extensions use the C++ compiler you have installed on your machine to build your program. Before trying to run and debughelloworldhelloworld.cpp in VS Code, make sure you have the C++ compiler installed.

  1. Open helloworld.cpp to make it the active file.

  2. Press the play button in the upper right corner of the editor.
    Screenshot of helloworld.cpp and play button

  3. SelectC/C++: clang++ Build and debug active files from the list of compilers detected on your system.
    Build task

    Only the first time you run helloworld.cpp will you be asked to select a compiler. This compiler will be set as the “default” compiler in the tasks.json file.

  4. After a successful build, your program output will appear in the integrated Terminal.
    Screenshot of program output

The first time you run your program, the C++ extension creates tasks.json, which you can find in your project’s .vscode folder. tasks.json stores build configuration.

Your new tasks.json file should look like the following JSON:

{
  // See https://go.microsoft.com/fwlink/?LinkId=733558
  // for the documentation about the tasks.json format
  "version": "2.0.0",
  "tasks": [
    {
      "type": "shell",
      "label": "C/C++ : clang++ build active file",
      "command": "/usr/bin/clang + + ",
      "args": [
        "-std=c + + 17",
        "-stdlib=libc + + ",
        "-g",
        "${file}",
        "-o",
        "${fileDirname}/${fileBasenameNoExtension}"
      ],
      "options": {
        "cwd": "${workspaceFolder}"
      },
      "problemMatcher": ["$gcc"],
      "group": {
        "kind": "build",
        "isDefault": true
      },
      "detail": "Task generated by Debugger."
    }
  ]
}

Note: You can learn more about tasks.json variables in the variable reference.

The command setting specifies the program to run. In this case "clang++" is a driver that causes the Clang compiler to expect C++ code and link to the C++ standard library.

The args array specifies the command line arguments that will be passed to clang++. These parameters must be specified in the order expected by the compiler.

This task tells the C++ compiler to compile the active file (

`

{file}), and in the current directory ($

f

i

l

e

D

i

r

n

a

m

e

) creates a file with the activity (

{fileDirname}`) creates a file with the active file (

fileDirname’) to create an output file (-o switch) with the same name as the active file (${fileBasenameNoExtension}), thereby creating helloworld.

The label value is what you will see in the task list. Name this whatever you want.

The detail value is a description of the task in your task list. It is strongly recommended to rename this value to distinguish it from similar tasks.

The problemMatcher value selects the output parser used to find errors and warnings in the compiler output. For clang++, you will get the best results if you use the $gcc issue matcher.

From now on, the play button will read from tasks.json to learn how to build and run your program. You can define multiple build tasks in tasks.json and the play button will use the task marked as default. If you need to change the default compiler, you can run Task: Configure default build task. Alternatively, you can modify the tasks.json file and remove the default value by replacing this section:

 "group": {
        "kind": "build",
        "isDefault": true
    },

use this:

 "group": "build",

Modify tasks.json

You can use "${workspaceFolder}/*.cpp" instead of ${file} and other parameters to modify your tasks.json to build multiple C++ files. This will build all .cpp files in your current folder. You can also do this by changing "${fileDirname}/${fileBasenameNoExtension}" to a hardcoded filename (for example, "${workspaceFolder}/myProgram.out" code>Modify the output file name.

Debug helloworld.cpp

To debug your code,

  1. Returns helloworld.cpp, making it the active file.
  2. Set a breakpoint by clicking in the editor margin or using F9 on the current line. Screenshot of helloworld.cpp breakpoint
  3. From the drop-down menu next to the play button, select Debug C/C++ files. Screenshot of the play button drop-down menu
  4. Select the clang++ build and debug active file from the list of compilers detected on your system (you will only be asked to select helloworld.cpp the first time you run or debug translater). C++ debug configuration drop-down menu

The play button has two modes: Run C/C++ files and Debug C/C++ files. It will default to the last used mode. If you see a debug icon in a play button, simply select the play button you want to debug instead of selecting the drop-down menu item.

Debugging

Before you start looking at the code, let’s take a moment to note a few changes to the user interface:

  • The integrated terminal appears at the bottom of the source code editor. In the Debug Output tab, you’ll see output indicating that the debugger is up and running.

  • The editor emphasized the first statement in the main method. This is a breakpoint that the C++ extension automatically sets for you:

    Initial breakpoint

  • The Run and Debug view on the left displays debugging information. You’ll see an example later in the tutorial.

  • At the top of the code editor, a debugging control panel appears. You can move it around the screen by grabbing the dot on the left.

Step through the code

Now you’re ready to start exploring the code.

  1. Click or press the Step over icon in the debug control panel to highlight the for (const string & amp; word : msg) statement.
    cross button
    The Step Over command skips all internal functions in the vector and string classes that are called when creating and initializing the msg variable transfer. Notice the changes in the Variables window. The contents of msg are visible because the declaration has been completed.
  2. Press Step over again to advance to the next statement (skipping all internal code executed to initialize the loop). The Variables window now displays information about the loop variables.
  3. Press Step over again to execute the cout statement. Note: As of the March 2019 version of the extension, no output will be displayed in the debug console until the last cout has completed.

Set up a watch

You may want to track the value of a variable as your program executes. You can do this by setting up a watch on the variable.

  1. Place the insertion point inside the loop. In the Watch window, click the plus sign, and then type word in the text box, which is the name of the loop variable. Now, as you move through the loop, look at theWatch window.

    Watch Window

  2. To quickly see the value of any variable while execution is paused, you can hover over it with your mouse pointer.

    Mouseover

Use launch.json to customize debugging

The C++ extension creates dynamic debug configurations in real time when you use the play button or F5 to debug.

In some cases, you want to customize the debugging configuration, such as specifying parameters passed to the program at run time. You can define custom debugging configurations in the launch.json file.

To create launch.json, select Add debug configuration from the play button drop-down menu.

Add debug configuration play button menu

You will then see a drop-down menu of various predefined debug configurations. Select clang++ Build and Debug Active Files. C++ debug configuration drop-down menu

VS Code creates a launch.json file that looks like this:

{
  // Use IntelliSense to learn about possible attributes.
  // Hover to view descriptions of existing attributes.
  // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
  "version": "0.2.0",
  "configurations": [
    {
      "name": "C/C++ : clang++ build and debug active file",
      "type": "cppdbg",
      "request": "launch",
      "program": "${fileDirname}/${fileBasenameNoExtension}",
      "args": [],
      "stopAtEntry": true,
      "cwd": "${workspaceFolder}",
      "environment": [],
      "externalConsole": false,
      "MIMode": "lldb",
      "preLaunchTask": "C/C++ : clang++ build active file"
    }
  ]
}

The program setting specifies the program you want to debug. Here it is set to the active folder ${fileDirname} and the active filename ${fileBasenameNoExtension} if helloworld.cpp is active The file will be helloworld. The args attribute is an array of arguments passed to the program at runtime.

By default, the C++ extension does not add any breakpoints to your source code and the stopAtEntry value is set to false.

Change the stopAtEntry value to true to cause the debugger to stop on the main method when starting debugging.

Make sure the preLaunchTask value matches the build task label in the tasks.json file.

From now on, when launching your program for debugging, the play button and F5 will be read from your launch.json file.

C/C++ configuration

For more control over C/C++ extensions, create a c_cpp_properties.json file that allows you to change the path to the compiler, including the C++ standard path to compile (such as + 17) and other settings.

View the C/C++ configuration UI by running the command **C/C++:** from the Command Palette (P) Edit Configuration (UI).

Command Palette

This opens the C/C++ Configuration page.

C++ Configuration

Visual Studio Code places these settings in .vscode/c_cpp_properties.json. If you open the file directly, it should look like this:

{
  "configurations": [
    {
      "name": "Mac",
      "includePath": ["${workspaceFolder}/**"],
      "defines": [],
      "macFrameworkPath": [
        "/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/System/Library/Frameworks"
      ],
      "compilerPath": "/usr/bin/clang",
      "cStandard": "c11",
      "cppStandard": "c++17",
      "intelliSenseMode": "clang-x64"
    }
  ],
  "version": 4
}

You only need to modify the Include Path setting if your program includes header files that are not in the workspace or standard library path.

Compilation path

compilerPath is an important configuration setting. This extension uses it to infer the path to C++ standard library header files. When an extension knows where to find these files, it can provide useful features like smart completion and Go to Definition navigation.

The C/C++ extension attempts to populate the default compiler location for compilerPath based on what it finds on the system. compilerPathThe search order is:

  • The path to your known compiler name. The order in which the compilers appear in the list depends on your path.
  • Then search for the hardcoded Xcode path, such as /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/

Mac framework path

On the C/C++ configuration screen, scroll down and expand Advanced Settings and make sure that Mac Framework Path points to the system header files. For example: /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/System/Library/Frameworks

Reuse your C++ configuration

VS Code is now configured to use Clang on macOS. This configuration applies to the current workspace. To reuse the configuration, simply copy the JSON file to the .vscode folder in your new project folder (workspace) and change the names of the source and executable files as needed.

Troubleshooting

Compiler and linker errors

The most common causes of errors are when helloworld.cpp is not the active file when you start a build or start debugging (such as undefined _main, or attempting to link with file built for unknown-unsupported file format, etc.) will appear. This is because the compiler is trying to compile something that is not source code, such as your launch.json, tasks.json, or c_cpp_properties.json files .

If you see build errors mentioning “C++11 extension”, you may not have updated your tasks.json build task to use the clang++ parameter --std=c++17 . By default, clang++ uses the C++98 standard, which does not support the initialization used in helloworld.cpp. Please make sure to replace the entire contents of the tasks.json file with the code block provided in the Run helloworld.cpp section.

Terminal will not start input

On macOS Catalina and onwards, you might have an issue where you are unable to enter input, even after setting "externalConsole": true. A terminal window opens, but it does not actually allow you type any input.

This issue is currently tracking #5079.

The solution is to let VS Code launch the terminal once. You can do this by adding and running this task in tasks.json:

{
  "label": "Open Terminal",
  "type": "shell",
  "command": "osascript -e 'tell application "Terminal"\\
do script "echo hello"\\
end tell'",
  "problemMatcher": []
}

You can use TerminalRun Task to run this specific task and then select Open Terminal.

Once you accept the permission request, the external console should appear while you are debugging.

Reference materials

Configure VS Code for Clang/LLVM on macOS