Friday, June 3, 2022

[SOLVED] VSCode, C++ and CMake - One launch configuration per target

Issue

I use Visual Studio Code and the CMake extension to work on a big project. The project consists of some libraries and executables which all are available as separate cmake build targets.

I configured VSCode / tasks.json to build the selected target with its default build.task:

{
  "version": "2.0.0",
  "tasks": [
    {
      "label": "CMake build",
      "type": "cmake",
      "command": "build",
      "problemMatcher": [],
      "group": {
        "kind": "build",
        "isDefault": true
      }
    }
  ]
}

Now the selected build target is build whenever I hit <Ctrl-Shift-b>.

Then I created a launch configuration by creating a launch.json file:

{
  "version": "0.2.0",
  "configurations": [
    {
      "name": "(gdb) Launch",
      "type": "cppdbg",
      "request": "launch",
      "program": "${command:cmake.launchTargetPath}",
      "args": ["--serialPort","/dev/ttyS0"],
      "stopAtEntry": false,
      "cwd": "${command:cmake.launchTargetDirectory}",
      "environment": [],
      "externalConsole": false,
      "MIMode": "gdb",
      "setupCommands": [
        {
          "description": "Enable pretty-printing for gdb",
          "text": "-enable-pretty-printing",
          "ignoreFailures": true
        }
      ]
    }
  ]
}

Now, whenever I hit F5 the gdb debugger is started with the selected launch target.

This works fine except, that only one of the launch targets needs the "args": ["--serialPort","/dev/ttyS0"] that I provided. Some of the others refuse to start with this args given.

So, is there a way to have separate args for separate targets in VSCode with cmake?


Solution

You can use the extension Command Variable v1.17.0

If you use the command extension.commandvariable.file.fileAsKey you can use the command variable ${command:cmake.launchTargetPath} to get the path that is used for matching keys (file path parts) to command line arguments.

The chosen default value (-v0) is a command option that is accepted by the other programs but does not do a major thing. -v is often chosen to select a debug log level.

{
  "version": "0.2.0",
  "configurations": [
    {
      "name": "(gdb) Launch",
      "type": "cppdbg",
      "request": "launch",
      "program": "${command:cmake.launchTargetPath}",
      "args": ["${input:arg1}", "${input:arg2}"],
      "stopAtEntry": false,
      "cwd": "${command:cmake.launchTargetDirectory}",
      "environment": [],
      "externalConsole": false,
      "MIMode": "gdb",
      "setupCommands": [
        {
          "description": "Enable pretty-printing for gdb",
          "text": "-enable-pretty-printing",
          "ignoreFailures": true
        }
      ]
    }
  ],
  "inputs": [
    {
      "id": "arg1",
      "type": "command",
      "command": "extension.commandvariable.file.fileAsKey",
      "args": {
        "@useCommand": "${command:cmake.launchTargetPath}",
        "@default": "-v0",
        "proj1": "--serialPort"
      }
    },
    {
      "id": "arg2",
      "type": "command",
      "command": "extension.commandvariable.file.fileAsKey",
      "args": {
        "@useCommand": "${command:cmake.launchTargetPath}",
        "@default": "-v0",
        "proj1": "/dev/ttyS0"
      }
    }
  ]
}

Edit

In version 1.18.1 I have added debug logs to the fileAsKey command.

  1. Add the following line to the args property:

    "@debug": true
    
  2. Open the Developer tools of VSC: Help > Toggle Developer Tools

  3. Clear the console

  4. Launch the debug session with F5

In the console you find a lot of text and you should find the following messages if fileAsKey executes without error:

[Extension Host] commandvariable.file.fileAsKey: debug logs enabled
[Extension Host] commandvariable.file.fileAsKey: use command variable: ${command:cmake.launchTargetPath}
[Extension Host] commandvariable.file.fileAsKey: execute command: cmake.launchTargetPath
[Extension Host] [CMakeTools] [debug] [extension] [6927] cmake.launchTargetPath started
[Extension Host] [CMakeTools] [debug] [cache] Reading CMake cache file C:/Projects/cmakeQuickStart/build/CMakeCache.txt
.....
[Extension Host] [CMakeTools] [debug] [extension] [6927] cmake.launchTargetPath finished (returned "C:\\Projects\\cmakeQuickStart\\build\\helloAll.exe")
[Extension Host] commandvariable.file.fileAsKey: execute command result: C:\Projects\cmakeQuickStart\build\helloAll.exe
[Extension Host] commandvariable.file.fileAsKey: path used: C:/Projects/cmakeQuickStart/build/helloAll.exe
[Extension Host] commandvariable.file.fileAsKey: default value: -v0
[Extension Host] commandvariable.file.fileAsKey: try key: helloAll
[Extension Host] commandvariable.file.fileAsKey: before variable substitution: /dev/ttyS0
[Extension Host] commandvariable.file.fileAsKey: after variable substitution: /dev/ttyS0


Answered By - rioV8
Answer Checked By - Mary Flores (WPSolving Volunteer)