Thomas Willson

Software Engineering Project Blog

IAR + VSCode + CMake

September 21, 2021

While the IAR compiler is a reasonable choice for an embedded compiler, especially when a functional safety certification is required, the IDE and provided build system leave a lot to be desired. This post documents how these IAR, VSCode, & CMake can be made to work together.

CMake Project for IAR

Recent versions of CMake have good support for the IAR compiler built-in. All the standard CMake commands work. The best way to select the IAR compiler in CMake is with a toolchain file. Here’s an example:

if (NOT DEFINED ENV{IAR_ARM})
    message(FATAL_ERROR "IAR_ARM variable is not defined!")
endif()

set(IAR_INSTALL $ENV{IAR_ARM})

find_program(CMAKE_ASM_COMPILER iasmarm.exe PATHS "${IAR_INSTALL}/bin" NO_DEFAULT_PATH)
find_program(CMAKE_C_COMPILER iccarm.exe PATHS "${IAR_INSTALL}/bin" NO_DEFAULT_PATH)
find_program(CMAKE_CXX_COMPILER iccarm.exe PATHS "${IAR_INSTALL}/bin" NO_DEFAULT_PATH)

set(CMAKE_SYSTEM_NAME Generic)
set(CMAKE_SYSTEM_PROCESSOR arm)
set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)

set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)

The above toolchain file assumes you have an environment variable IAR_ARM configured that points at your IAR install.

If configuring from the command line, pass the toolchain file to CMake with arg: -D CMAKE_TOOLCHAIN_FILE="iar_ewarm_toolchain.cmake"

However, I recommend using CMake Tools with VSCode. Use the .vscode/cmake-kits.json file to configure CMake Tools to pass the toolchain:

[
  {
    "name": "IAR",
    "toolchainFile": "${workspaceRoot}\\iar_ewarm_toolchain.cmake",
    "preferredGenerator": {
      "name": "Ninja"
    }
  }
]

Additionally, you’ll want to enable CMake Tools’ IAR output parser in order for IAR compiler messages to shown up in the problems pane. This can be configured in the .vscode/settings.json file:

"cmake.enabledOutputParsers": [
    "cmake",
    "iar"
] // Requires https://github.com/microsoft/vscode-cmake-tools/pull/2131, scheduled for release in v1.9.0.

When opening the folder, select the IAR kit in the status bar.

VSCode Intellisense Configuration

In order to get accurate intellisense results, some macros need to be defined for VSCode’s parsing to roughly match that of the IAR compiler.

The approach I took is to create two header files that could be “force included” in each translation unit (as far as intellisense is configured). The first can be generated by invoking the IAR compiler using a blank input file:

iccarm.exe --IDE3 --NCG <path to blank input file> --predef_macros iar_predefined_macros.h <compile flags>

The above command will produce a header file named iar_predefined_macros.h in the current directory — this is the first of the headers. The only compile flag that I’m aware of that makes an important difference in the output is -c++ — it should be provided if the project is compiled in C++ mode.

The second header is a little more manual to generate. Find the $IAR_ARM\config\syntax_icc.cfg file, which will look similar to:

__arm
__thumb
__interwork
__swi
__irq
__fiq
__ramfunc
__no_init
__root
__nested
__task
__noreturn
__absolute
__big_endian
__little_endian
__packed
__stackless
__weak
__nounwind

Copy the contents into a new header file and prefix each line with #define, which should leave you with something like:

#define __arm
#define __thumb
#define __interwork
#define __swi
#define __irq
#define __fiq
#define __ramfunc
#define __no_init
#define __root
#define __nested
#define __task
#define __noreturn
#define __absolute
#define __big_endian
#define __little_endian
#define __packed
#define __stackless
#define __weak
#define __WEAK
#define __nounwind
#define __intrinsic

Take these two header files and place them somewhere in your project directory. I like to place them in the .vscode directory since they’re only used for intellisense.

Now, create a .vscode/c_cpp_properties.json file in your project directory and set the following configuration:

{
  "configurations": [
    {
      "name": "IAR",
      "cppStandard": "c++17",
      "configurationProvider": "ms-vscode.cmake-tools",
      "compilerPath": "",
      "mergeConfigurations": true, // Requires https://github.com/microsoft/vscode-cpptools/pull/8174, scheduled for initial release in 1.7.0-insiders3.
      "forcedInclude": [
        "${workspaceFolder}/.vscode/iar_compatibility.h",
        "${workspaceFolder}/.vscode/iar_predefined_macros.h"
      ]
    }
  ],
  "version": 4
}

Debugging in VSCode with Cortex-Debug

The quick debug shortcut provided by CMake Tools doesn’t provide enough configuration in order to debug an embedded target. I recommend using the wonderful Cortex-Debug extension. Below is an example configuration:

{
  "version": "0.2.0",
  "configurations": [
    {
      "type": "cortex-debug",
      "request": "launch",
      "name": "cppdbg",
      "servertype": "jlink",
      "executable": "${command:cmake.launchTargetPath}",
      "armToolchainPath": "${env:GCC_INSTALL}/bin", // Requires a GCC installation at the provided path.
      "cwd": "${workspaceFolder}",
      "device": "XMC4700-1536", // Specify device here.
      "interface": "swd",
      "svdFile": "${workspaceFolder}/Tools/RegisterDescriptions/XMC4700.svd", // Specify SVD file here.
      "preLaunchTask": "build all"
    }
  ]
}

See the Cortex-Debug documentation for more configuration guidance.

Complete Example

For a complete project example that incorporates the above guidance, see willson556/sample-cmake-iar-vscode.

References / Further Reading

Share This Post