Yocto Programming with VSCode (2023)

DART-MX8M-MINI - Yocto Programming with Visual Studio Code

Visual Studio Code (VS Code) is a powerful, modern, open-source code editor that can be used to develop and debug C/C++ applications on Variscite System on Modules.

This guide demonstrates how to create and debug a C++ application using VS Code on the DART-MX8M-MINI.

Contents

  • 1 Create your rootfs with VS Code debug support
  • 2 Setup Host Computer Environment
    • 2.1 Install Dependencies
    • 2.2 Install VS Code
    • 2.3 Install VS Code Extensions
    • 2.4 Install Yocto Toolchain
  • 3 Create, cross compile, and run a new "Hello, World!" project
  • 4 Remote Debugging with VS Code
    • 4.1 Create var-deploy-gdb.sh
    • 4.2 Create launch.json
    • 4.3 Edit tasks.json
    • 4.4 Launch a Debugging Session
  • 5 Example Project Source Code

Debugging with VS Code requires your preferred SSH server (openssh, dropbear, etc), gdb, and gdbserver installed on the target device. Append the following to the conf/local.conf file in your Yocto build directory:

EXTRA_IMAGE_FEATURES = " \ tools-debug \ ssh-server-dropbear \ "

Now bitbake your image.

Please follow the steps below to prepare a fresh Ubuntu 20.04 installation for VS Code debugging:

2.1 Install Dependencies

$ sudo apt-get -y update$ sudo apt-get -y install build-essential gdb gdb-multiarch git

2.2 Install VS Code

$ sudo snap install --classic code

2.3 Install VS Code Extensions

VS Code has a graphical interface for installing and managing extensions. To learn more, please see Using extensions in Visual Studio Code

For this guide, we will install the required extensions using the command line:

$ code --install-extension ms-vscode.cpptools

2.4 Install Yocto Toolchain

A toolchain is necessary for cross compiling applications. To install the toolchain, follow Variscite's Yocto Toolchain installation guide.

Open a new terminal, create an empty project directory and open VS Code:

$ mkdir ~/var-hello-world$ cd ~/var-hello-world$ code .

This will launch VS Code with ~/var-hello-world as working directory (which is currently empty):

Next, we will create the following files:

main.cppSource code for the demo program hello.bin
MakefileMakefile to cross compile main.cpp to hello.bin
.vscode/settings.jsonVS Code file to configure global environment variables for the SDK/toolchain
.vscode/tasks.jsonVS Code file to override or add new tasks. Runs Makefile when VS Code build command is executed.
.vscode/c_cpp_properties.jsonVS Code file to configure include path for IntelliSense.

To create a new file or folder in VS Code, right click in the VS Code explorer view and select New File or New Folder:

Create a new file called main.cpp:

main.cpp:

#include <stdio.h>int main(int argc, char *argv[]) { printf("Hello, World!\n"); return 0;}

Create a new Makefile to build hello.bin:

Makefile:

all: main.cpp$(CXX) $(CXXFLAGS) -Og main.cpp -g -o hello.bin clean:rm -f hello.bin

Create a new folder named .vscode. Then, create a new file .vscode/settings.json

.vscode/settings.json:

{"VARISCITE": {/* Target Device Settings */"TARGET_IP":"192.168.0.141",/* Project Settings */"PROGRAM":"hello.bin",/* Yocto SDK Configuration */"ARCH":"aarch64-fslc-linux","OECORE_NATIVE_SYSROOT":"/opt/fslc-xwayland/3.3/sysroots/x86_64-fslcsdk-linux","SDKTARGETSYSROOT": "/opt/fslc-xwayland/3.3/sysroots/cortexa53-crypto-fslc-linux",/* Yocto SDK Constants */"CC_PREFIX": "${config:VARISCITE.OECORE_NATIVE_SYSROOT}/usr/bin/${config:VARISCITE.ARCH}/${config:VARISCITE.ARCH}-","CXX": "${config:VARISCITE.CC_PREFIX}g++ --sysroot=${config:VARISCITE.SDKTARGETSYSROOT}","CC": "${config:VARISCITE.CC_PREFIX}gcc --sysroot=${config:VARISCITE.SDKTARGETSYSROOT}",}}

The table below describes the global variables in settings.json. They can be accessed in other json files, for example ${config:VARISCITE.TARGET_IP}:

TARGET_IPThe IP Address of the DART-MX8M-MINI target device
PROGRAMMust match the name of the binary generated by Makefile
ARCHArchitecture prefix for gcc, g++, gdb, etc. Align with CXX variable set by /opt/fslc-xwayland/3.3/environment-setup-cortexa53-crypto-fslc-linux
OECORE_NATIVE_SYSROOTAlign with OECORE_NATIVE_SYSROOT variable set by /opt/fslc-xwayland/3.3/environment-setup-cortexa53-crypto-fslc-linux
SDKTARGETSYSROOTAlign with SDKTARGETSYSROOT variable set by /opt/fslc-xwayland/3.3/environment-setup-cortexa53-crypto-fslc-linux
CC_PREFIXFull path to toolchain gcc, g++, etc binaries.
CXXPath to cross g++ binary and sysroot
CCPath to cross gcc binary and sysroot

Create a new file .vscode/tasks.json. tasks.json has three root objects:

  • options: Define CC and CXX environment variables for the Makefile.
  • presentation: Configures the behavior of VS Code's integrated Terminal for all tasks.
  • tasks: An array of task configurations. The example below creates a single 'build task that runs the Makefile when the VS Code build task is executed.

.vscode/tasks.json:

{ "version": "2.0.0", /* Configure Yocto SDK Constants from settings.json */ "options": { "env": { "CXX": "${config:VARISCITE.CXX}", /* Used by Makefile */ "CC": "${config:VARISCITE.CC}", /* Used by Makefile */ } }, /* Configure integrated VS Code Terminal */ "presentation": { "echo": false, "reveal": "always", "focus": true, "panel": "dedicated", "showReuseMessage": true, }, "tasks": [ /* Configure Build Task */ { "label": "build", "type": "shell", "command": "make clean; make -j$(nproc)", "problemMatcher": ["$gcc"] }, ]}

Create vscode/c_cpp_properties.json to configure the include path for IntelliSense.

.vscode/c_cpp_properties.json:

{ "configurations": [ { "name": "Linux", "includePath": [ "${workspaceFolder}/**", "${config:VARISCITE.SDKTARGETSYSROOT}/usr/include/**" ] } ], "version": 4}


Your workspace should look similar to this:

Cross compile the project by selecting Terminal->Run Build Task... or entering Ctrl+Shift+B and selecting Build:

Open a new VS Code terminal by selecting Terminal->New Terminal or entering Ctrl+Shift+`.

Deploy hello.bin to the target device using SCP:

$ scp hello.bin root@<ip addr>:/home/root/

Launch hello.bin on the target device:

# ./hello.bin Hello, World!

After verifying hello.bin runs on the target device, we can now setup VS Code for remote debugging.

The working directory should currently have these files:

variscite@ubuntu:~/var-hello-world$ find .vscode/settings.json.vscode/tasks.json./Makefile./main.cpp./hello.bin

To enable debugging, we will edit .vscode/tasks.json to add a var-deploy-gdb debug task and add two additional files to the project:

var-deploy-gdb.shGeneric script to deploy and launch gdbserver
.vscode/launch.jsonVS Code file to configure debug settings. Runs var-build-and-debug in tasks.json
.vscode/tasks.jsonEdit to call var-deploy-gdb.sh prior to debugging.

4.1 Create var-deploy-gdb.sh

First, add a generic script deploy a program and launch gdbserver. The script requires two arguments:

  1. TARGET_IP: The IP Address of the target device
  2. PROGRAM: The name of the binary executable, hello.bin in this example

In the end, tasks.json will run this script at the beginning of each debug session.

var-deploy-gdb.sh:

#!/bin/bashreadonly TARGET_IP="$1"readonly PROGRAM="$2"readonly TARGET_DIR="/home/root"# Must match startsPattern in tasks.jsonecho "Deploying to target"# kill gdbserver on target and delete old binaryssh root@${TARGET_IP} "sh -c '/usr/bin/killall -q gdbserver; rm -rf ${TARGET_DIR}/${PROGRAM} exit 0'"# send the program to the targetscp ${PROGRAM} root@${TARGET_IP}:${TARGET_DIR}# Must match endsPattern in tasks.jsonecho "Starting GDB Server on Target"# start gdbserver on targetssh -t root@${TARGET_IP} "sh -c 'cd ${TARGET_DIR}; gdbserver localhost:3000 ${PROGRAM}'"

4.2 Create launch.json

VS Code has a powerful built in debugger capable of debugging many programming languages. In this step, we will add a configuration for debugging using the C/C++ extension:

.vscode/launch.json:

{ "version": "0.2.0", "configurations": [{ "name": "GDB debug", "type": "cppdbg", "request": "launch", "program": "${config:VARISCITE.PROGRAM}", "args": [], "stopAtEntry": true, "cwd": "${workspaceFolder}", "environment": [], "console": "integratedTerminal", "MIMode": "gdb", "targetArchitecture": "arm64", "preLaunchTask": "var-deploy-gdb", "setupCommands": [{ "description": "Enable pretty-printing for gdb", "text": "-enable-pretty-printing", "ignoreFailures": true }], "miDebuggerPath": "/usr/bin/gdb-multiarch", "miDebuggerServerAddress": "${config:VARISCITE.TARGET_IP}:3000", }]}

See the table below for important details regarding launch.json variables:

miDebuggerServerAddressMust match the IP Address of the target device
programMust match the name of the binary generated by the the Makefile
preLaunchTaskMust match the name of the task in .vscode/tasks.json in the following step

4.3 Edit tasks.json

In launch.json, we created a preLaunchTask to run a task named var-deploy-gdb at the beginning of each debugging session. This task is configured by adding a new task var-deploy-gdb to .vscode/tasks.json:

.vscode/tasks.json:

{ "version": "2.0.0", /* Configure Yocto SDK Constants from settings.json */ "options": { "env": { "CXX": "${config:VARISCITE.CXX}", "CC": "${config:VARISCITE.CC}", } }, /* Configure integrated VS Code Terminal */ "presentation": { "echo": false, "reveal": "always", "focus": true, "panel": "dedicated", "showReuseMessage": true, }, "tasks": [ /* Configure launch.json (debug) preLaunchTask Task */ { "label": "var-deploy-gdb", "isBackground": true, "problemMatcher":{ "base": "$gcc", "background": { "activeOnStart": true, "beginsPattern": "Deploying to target", "endsPattern": "Starting GDB Server on Target" } }, "type": "shell", "command": "sh", "args": [ "var-deploy-gdb.sh", "${config:VARISCITE.TARGET_IP}", "${config:VARISCITE.PROGRAM}" ], "dependsOn": ["build"], }, /* Configure Build Task */ { "label": "build", "type": "shell", "command": "make clean; make -j$(nproc)", "problemMatcher": ["$gcc"] }, ]}


The following table summarizes the var-deploy-gdb configuration in tasks.json:

labelMust match preLaunchTask in launch.json
typeThis task will launch a shell
commandLaunch sh, with arguments var-build-and-debug.sh 192.168.0.136 hello.bin

4.4 Launch a Debugging Session

After following the steps above, the working directory should now have these files:

~/var-hello-world$ find.vscode/c_cpp_properties.json.vscode/launch.json.vscode/settings.json.vscode/tasks.json./Makefile./var-deploy-gdb.sh./main.cpp./hello.bin

A new debugging session can be started by selecting Run->Start Debugging or by pressing 'F5' on the keyboard. VS Code will switch to the debug perspective and launch a gnome-terminal running gdbserver on the target device:

The source code for this example is available from Variscite's Github repository:

$ git clone https://github.com/varigit/var-demos$ cd var-demos/vscode-demos/hello-world

Launch VS Code:

$ code .

Configure the target device IP Address and SDK variables in .vscode/settings.json

Finally, start a debugging session by selecting Run->Start Debugging or pressing 'F5' on the keyboard.

Top Articles
Latest Posts
Article information

Author: Francesca Jacobs Ret

Last Updated: 02/07/2023

Views: 6360

Rating: 4.8 / 5 (68 voted)

Reviews: 91% of readers found this page helpful

Author information

Name: Francesca Jacobs Ret

Birthday: 1996-12-09

Address: Apt. 141 1406 Mitch Summit, New Teganshire, UT 82655-0699

Phone: +2296092334654

Job: Technology Architect

Hobby: Snowboarding, Scouting, Foreign language learning, Dowsing, Baton twirling, Sculpting, Cabaret

Introduction: My name is Francesca Jacobs Ret, I am a innocent, super, beautiful, charming, lucky, gentle, clever person who loves writing and wants to share my knowledge and understanding with you.