How to set up Visual Studio Code for Yocto Application Development using CMake
The following steps show how to set up Microsoft Visual Studio Code (VSCode) for developing Yocto applications that use CMake as build system and debug them on a remote target device. It is assumed that the reader has solid experience in developing C/C++ applications with CMake and a basic understanding of the VSCode IDE.
Requirements
This section shows how to create and install the Yocto Software Development Kit (SDK) and prepare VSCode.
Build an SDK Installer for Yocto
Follow the instructions from docs.yoctoproject.org/sdk-manual/appendix-obtain.html#building-an-sdk-installer to build and install the Standard SDK for Yocto. This SDK includes the appropriate cross-compiler and debugger for the target hardware, the complete root file system of the embedded Linux image, and other tools needed for Yocto application development.
Note: Call make sdk for building the SDK when using the FWK Yocto framework.
Install Visual Studio Code
Download and install VSCode from the official website. Also, install the C/C++ Extension Pack, which includes language support, tools, and themes for C/C++ and CMake.
Setting up the Development Environment
Before starting the VSCode IDE to develop or edit a Yocto application, you have to set up the development environment. Yocto has created a suitable shell script and placed it in the installation directory of the Yocto SDK. Source this script in the same shell in which you want to start VSCode.
source <path to SDK installation>/environment-setup-aarch64-xilinx-linux
By doing so, the shell environment will contain a variable (OE_CMAKE_TOOLCHAIN_FILE) that the CMake build tool already knows about and uses. The file referenced by this environment variable specifies the locations for compiler and tool chain utilities, as well as other target platform and compiler-related information.
Creating a Simple CMake Project
This section explains how to set up a simple C/C++ project based on CMake using VSCode. This project can be a good starting point for any sophisticated software development.
-
Create a new folder for the software project.
-
Open a shell terminal inside the project folder and set up the development environment for Yocto, as mentioned above.
-
Launch VSCode by calling
code .from the same terminal. -
After VSCode opens, go to the Command Palette (Ctrl+Shift+P) and type
CMake:Quick Startto start a wizard that will guide you through creating a CMake project:-
The tool will ask you to
Select a Kit for cmake-test. Here select[Unspecified], which will make CMake use the settings from the shell environment variable of the Yocto SDK. Note: If the tool does not ask you to select a kit, it has already been configured. In this case interrupt the wizard for now and select the kit manually. TypeCMake:Configurein the Command Palette (Ctrl+Shift+P), select[Unspecified]here and relaunch the quick start wizard. -
Since this is a new project, the tool will complain that no
CMakeLists.txtfile was found. PressCreateto let VSCode create one. -
Next, enter a name for the project and select
Executablefrom the drop-down menu. -
This will create a skeleton CMake project with some "Hello World" source code. Note: From the
./build/compile_commands.jsonfile it can be verified that CMake has indeed taken the environment variable from the Yocto SDK. If this is not the case, CMake is using the wrong kit.
-
-
Running
CMake:Buildfrom the Command Palette will cross-compile the source code for the target device.
Target-Debugging within Visual Studio Code
To debug software remotely on the target device, the GNU Debugger is used here together with the gdbserver. The compiled software is copied to the target and then launched using the gdbserver. Once the server runs, gdb is started on the host machine for remote debugging. These steps are integrated into VSCode in the following way.
Create a Debug Configuration
Select the main C/C++ file inside of the Explorer view of VSCode, to make it the active file. Open Command Palette (Ctrl+Shift+P), type C/C++: Add Debug Configuration, and select (gdb) Launch. This will generate a template launch.json file inside of the .vscode folder of the project root path. Make the following changes to this file.
{
"version": "0.2.0",
"configurations": [
{
"name": "(gdb) Launch",
"type": "cppdbg",
"request": "launch",
"program": "${command:cmake.launchTargetPath}",
"args": [],
"stopAtEntry": true,
"cwd": "${workspaceRoot}/build",
"MIMode": "gdb",
"miDebuggerPath": "${env:GDB}",
"miDebuggerServerAddress": "${config:debug_target_host_name}:${config:debug_target_gdb_port}",
"preLaunchTask": "Launch GDB Server",
"postDebugTask": "Close GDB Server",
"setupCommands": [
{
"description": "Enable pretty-printing for gdb",
"text": "-enable-pretty-printing",
"ignoreFailures": true
}
]
}
],
}
Note the variable miDebuggerPath. It specifies that the launcher should use the debugger from the Yocto SDK environment instead of the default debugger for the host machine. The two configuration variables used in the miDebuggerServerAddress node define the connection to the debug server for remote debugging.
Now, create a settings.json file inside of the .vscode folder and specify the two configuration variables for the debug server connection.
{
/* Project setting */
// Host name of remote debugging target
"debug_target_host_name": "target host name goes here",
// GDB Server port on remote debugging target
"debug_target_gdb_port": "2345"
}
Deploy and Launch Software
The variable preLaunchTask from the upper launch.json file specifies a task to be launched before a debug session starts. This is used to trigger the chain of tasks that deploys the binaries and starts the gdbserver on the remote device. Create a tasks.json inside of the .vscode folder, with the following content, for this purpose.
{
"version": "2.0.0",
"tasks": [
{
"label": "Deploy",
"type": "shell",
"command": "scp",
"args": [
"${command:cmake.launchTargetPath}",
"root@${config:debug_target_host_name}:/home/root"
]
},
{
"label": "Launch GDB Server",
"type": "shell",
"command": "ssh",
"args": [
"-t",
"root@${config:debug_target_host_name}",
"\"sh -c 'gdbserver :${config:debug_target_gdb_port} ${command:cmake.getLaunchTargetFilename}; exit 0' \""
],
"dependsOn": [
"Deploy",
],
"isBackground": true,
"problemMatcher": {
"base": "$gcc",
"background": {
"activeOnStart": true,
"beginsPattern": {
"regexp": "^Process .*"
},
"endsPattern": {
"regexp": "^Listening on port .*"
},
}
},
"presentation": {
"clear": true
}
},
{
"label": "Close GDB Server",
"type": "shell",
"command": "ssh",
"args": [
"root@${config:debug_target_host_name}",
"\"sh -c '/usr/bin/killall -q gdbserver; exit 0' \""
],
"presentation": {
"close": true,
"reveal": "never",
"revealProblems": "never",
}
}
]
}
This concludes the debugging configuration of VSCode. Switch to the Run and Debug view (Ctrl+Shift+D) and start the debug session.