Project

General

Profile

VScode tasks and launch

Visual Studio Code uses a file named <project_root>/.vscode/tasks.json to define a set of tasks which can be executed by the user. A common task is to build the application. Variations for cleaning the project or building specifically in debug or release modes can also exist.

A different file named <project_root>/.vscode/launch.json is used when starting a debug session. When starting a debug session, there are two steps.

  • First, start gdbserver on the target and tell it to listen to a port (usually 10000) for a remote host.
  • Second, start gdb-multiarch on the development host and tell it to connect to a target at port 10000.

The information in launch.json provides the details on how to connect to the gdbserver running on the target. The information includes the target name or address and the port to connect to.

This wiki page describes how to set up both the tasks.json and launch.json files. This is only one way of using these files. You may prefer other ways of using these files.

tasks.json

We will describe one way of using tasks for a variety of uses. The code in the tasks.json file will do a bare minimum and will call a script named build.sh to perform the details of the different tasks. The tasks.json file will be in <project_root_dir>/.vscode/tasks.json and the build.sh script will be in <project_root_dir>.

A sample tasks.json with a single task could look like this:

{
    // See https://go.microsoft.com/fwlink/?LinkId=733558
    // for the documentation about the tasks.json format
    "version": "2.0.0",
    "tasks": [
        {
            "label": "build",
            "type": "shell",
            "command": "./build.sh",
            "problemMatcher": [ "$gcc" ],
            "group": {
                "kind": "build",
                "isDefault": false
            }
        }
    ]   
}

This is the default build task and just calls the build.sh script with no arguments.

You can have multiple tasks like this:

{
    // See https://go.microsoft.com/fwlink/?LinkId=733558
    // for the documentation about the tasks.json format
    "version": "2.0.0",
    "tasks": [
        {
            "label": "build",
            "type": "shell",
            "command": "./build.sh",
            "problemMatcher": [ "$gcc" ],
            "group": {
                "kind": "build",
                "isDefault": false
            }
        },
        {
            "label": "build debug",
            "type": "shell",
            "command": "./build.sh debug",
            "problemMatcher": [ "$gcc" ],
            "group": {
                "kind": "build",
                "isDefault": false
            }
        },
        {
            "label": "build release",
            "type": "shell",
            "command": "./build.sh release",
            "problemMatcher": [ "$gcc" ],
            "group": {
                "kind": "build",
                "isDefault": false
            }
        },
        {
            "label": "clean debug",
            "type": "shell",
            "command": "./build.sh debug-clean",
            "problemMatcher": [ "$gcc" ],,
            "group": {
                "kind": "build",
                "isDefault": false
            }
        },
        {
            "label": "clean release",
            "type": "shell",
            "command": "./build.sh release-clean",
            "problemMatcher": [ "$gcc" ],
            "group": {
                "kind": "build",
                "isDefault": false
            }
        },
        {
            "label": "clean all",
            "type": "shell",
            "command": "./build.sh clean",
            "problemMatcher": [ "$gcc" ],
            "group": {
                "kind": "build",
                "isDefault": false
            }
        }
    ]
}

Note that all of the isDefault values are false. When you enter ctrl-shift-B to start a build task, VScode won't know which task to perform so it will show the list of possible tasks and you can pick the one you want. If you mark one task with isDefault: true, then entering ctrl-shift-B will start that one task. If multiple tasks have isDefault: true, then again, VScode won't know which you want and you will see the list. If you enter ctrl-shift-P and type TASKS: Run Task, then you will always get the list of tasks whether any task has been marked isDefault: true or not.

Here is a sample build.sh that could be called by the above tasks. This script sets up the environment for the cross-compilation tools, ensures that the makefile has been generated, and then uses "make" to build the desired target.

#!/bin/bash

# toolchain information to setup the environment with appropriate variables so the cross-compiler is used 
TOOLCHAIN=~/ti-processor-sdk-linux-am62xx-evm-08.06.00.42/linux-devkit/environment-setup #-aarch64-linux
source $TOOLCHAIN

CC_PREFIX=aarch64-none-linux-gnu

# this script assumes there is a makefile in the same directory as this script and that the 
# working directory when executing this script is the directory containing this script. 
#
# In addition, this script assumes there is a Qt project file used to generate the makefile.
# 

# comment out if not using Qt project file
PRO_FILE=hello.pro

# this script can be called with an argument which is the target for the call to make 
# Possible values for the argument include 
#
# debug
# release 
# clean
# debug-clean
# release-clean
# all

MAKE_TARGET=release
if [ "$1" != "" ] 
then
    MAKE_TARGET=$1
fi

#uncomment for script debugging
#set -e
#set -x

# Build app
COMPILEDB=
if command -v compiledb &> /dev/null
then
    # Use compiledb to generate a compile_commands.json file for vscode
    COMPILEDB="compiledb" 
fi

(
    # make sure that if there is a PRO_FILE (meaning that Qt and qmake are being used) then
    # the Makefile exists and that the PRO_FILE is older than the Makefile
    # if the Makefile does not exist or the PRO_FILE is not older than the Makefile
    # then call qmake to generate the Makefile
    #
    # note that the Makefile itself does some checks about whether the Makefile is up to date
    # but it won't catch the Makefile not existing or if PRO_FILE and Makefile have the
    # same date/time. The checks below are intended to make sure the PRO_FILE is older
    # than the Makefile

    if [ "$PRO_FILE" != "" ]
    then
        if [[ ! -e Makefile ]] ||  [[ !  "$PRO_FILE" -ot Makefile  ]]
        then
            echo Generating Makefile from $PRO_FILE
            qmake "$PRO_FILE" 
        fi
    fi
    $COMPILEDB make -j$(nproc) $MAKE_TARGET
)

launch.json

As noted above, the launch.json file specifies how gdb-multiarch should connect to a specific target. Multiple targets can be listed and when starting a debug session, you can select which target you want to connect to.

Here is a sample launch.json for a single target.

{
    "configurations": [
     {
        "type": "gdb",
        "request": "attach",
        "name": "Attach to target_62x",
        "executable": "Debug/hello",
        "target": "localhost:10000",
        "stopAtEntry": true,
        "remote": true,
        "cwd": "${workspaceRoot}",
        "valuesFormatting": "prettyPrinters",
        "gdbpath": "/usr/bin/gdb-multiarch" 
    }]
}

The target to connect to is specified as localhost:10000. It is assumed you have a ~/.ssh/config file set up so that port forwarding is being done to forward traffic sent to localhost:10000 on the development host to port 10000 on the 62x target. see ssh_target_naming_and_port_forwarding

If you have multiple targets, additional entries can be added.

{
    "configurations": [
     {
        "type": "gdb",
        "request": "attach",
        "name": "Attach to target_62x",
        "executable": "Debug/hello",
        "target": "localhost:10000",
        "stopAtEntry": true,
        "remote": true,
        "cwd": "${workspaceRoot}",
        "valuesFormatting": "prettyPrinters",
        "gdbpath": "/usr/bin/gdb-multiarch" 
    },
    {
        "type": "gdb",
        "request": "attach",
        "name": "Attach to target_62x_1",
        "executable": "Debug/hello",
        "target": "localhost:10001",
        "stopAtEntry": true,
        "remote": true,
        "cwd": "${workspaceRoot}",
        "valuesFormatting": "prettyPrinters",
        "gdbpath": "/usr/bin/gdb-multiarch" 
    }]
}

Note that the second entry has a different name and uses a different port for the target. Presumably, the ~/.ssh/config file also has an entry for a different target which will forward traffic intended for port 10001 on the host to port 10000 on the target.

The "names" of the entries will appear in a selection list when trying to start a debug session. You can select the desired target from the list.

Go to top
Add picture from clipboard (Maximum size: 1 GB)