Select Page

VSCode – Include Paths

This article will describe how to set up the Include Paths for C/C++ in Visual Studio Code to support ARM development. Visual Studio Code with the C/C++ plugin has many useful features while we are writing our code:

  • syntax highlighting,
  • error checking while we type, and
  • automatic code completion, where it guesses while we type.

This can help us reduce errors and write faster. However, if the plugin is not correctly set up, these features will not work correctly or at all.

In order for Visual Studio Code and the C/C++ language plugin to understand our code, it needs to be able to find all of the header files referenced in our program. A header can further reference other headers, so they may be needed even if you didn’t explicitly call them yourself.

In main.c, VSCode is complaining that it cannot open tm4c123gh6pm.h’ file’. The message is a little obscure, but it’s basically saying that it will interpret the file based on keywords and syntax, but can’t tell if things like function or variable names are correct.

So, how do we fix this? If the cursor is on the error, you will see the lightbulb to the left. Click that, and then Update “includePath” setting. VSCode will create and open a file called “c_cpp_properties.json”, in our project under a “.vscode” folder. By default this will contain configurations for Mac, Linux, and Win32. These include default includePaths suitable for desktop applications, but are not correct for ARM.

There are two sections with paths. The first, “includePath”, is where VSCode will look for headers for the purpose of checking our code. Unlike GCC, this is not recursive; we need to explicitly list each folder that contains headers that are referenced, directly or indirectly.

The second section with just “path” is used by IntelliSense to suggest things for us.

This is the initial c_cpp_properties.json file:

{
    "configurations": [
        {
            "name": "WIN32",
            "includePath": [
                "${workspaceFolder}/**",
                "E:\\ti\\TivaWare_C_Series-2.2.0.295"
            ],
            "defines": [
                "_DEBUG",
                "PART_TM4C123GH6PM"
            ],
            "compilerPath": "C:\\ProgramData\\chocolatey\\bin\\arm-none-eabi-gcc",
            "cStandard": "c99",
            "cppStandard": "gnu++17",
            "intelliSenseMode": "gcc-arm",
            "configurationProvider": "ms-vscode.cmake-tools"
        },
        {
            "name": "LINUX",
            "includePath": [
                "${workspaceFolder}/**",
                "/home/jshankar/ti/TivaWare_C_Series-2.2.0.295"
            ],
            "defines": [
                "_DEBUG",
                "PART_TM4C123GH6PM"
            ],
            "compilerPath": "/opt/toolchains/gcc-arm-none-eabi-10.3-2021.10/bin/arm-none-eabi-gcc",
            "cStandard": "c99",
            "cppStandard": "gnu++17",
            "intelliSenseMode": "gcc-arm",
            "configurationProvider": "ms-vscode.cmake-tools"
        }        
    ],
    "version": 4
}
  • name: arbitrary name for the configuration
  • includePath: list here all locations where IntelliSense shall search for header files. It automatically will use the ones located in the toolchain (compiler) installation. The ‘**’ notation means it will search recursively that folder
  • defines: list all the extra defines which shall be considered.
  • forcedInclude: if using the -include compiler option, make sure you list that file here
  • compilerPath: path to the compiler executable.
  • cStandard and cppStandard: the C and C++ standard to be used
  • intelliSenseMode: mode to be used. ‘gcc-arm’ is considered legacy, but not sure what to use otherwise for ARM?

But where is stdint.h? GCC has built-in include paths that are used even if compiler flags don’t specify them. GCC will list the defaults by running “arm-none-eabi-gcc -xc -E -v –“, and add those paths as well. Be sure to list all sub folders with headers for the includePath section.

References