5

I noticed that for node.js there's a debugger "auto attach" feature, which I would like to use if it was possible. However, I don't think I can use "auto attach" to automatically fire up the debugger after I've re-compiled my program. I compile my program using C/C++/Fortran using makefiles (and similar) so after running "make" I get a normal (linux) executable. I then execute that binary and often want to debug it right away, after this. I have the full binary path set to an environment variable "$myprog=/home/user/my-dev/bin/myApp".

So what I do is to run debug using "Attach to process" and every time I have to find the proper process in the dropdown list, but I do it too many times each day, each hour, it's becoming tedious and would like something smarter, "more automatically":

Instead of "auto attach" (only for node.js, as I understand it) I would like to modify my launch.json so it extracts the process-id automatically, using e.g. the shell command: 'pgrep -x "$myprog"' and maybe optionally bind it to a keyboard-shortcut.

I'm guessing the line "processId": "${command:pickProcess}" needs to be modified, please see example configuration below:

{
    "name": "(gdb) Attach (any)",
    "type": "cppdbg",
    "request": "attach",
    "program": "/home/user/my-dev/bin/myApp",
    "processId": "${command:pickProcess}",
    "MIMode": "gdb",
    "miDebuggerPath": "/usr/bin/gdb"
},

Is it possible to modify the launch.json file so VS code understands that the variable "processId" should be substituted by the shell output from: pgrep -x "$myprog" (obviously this PID changes, after every compilation and execution of the program to be debugged)?

If so, I guess it is also possible to bind it to a keyboard-shortcut? Does anyone know how to achieve this?

KyleMit
  • 30,350
  • 66
  • 462
  • 664
Okay Dokey
  • 67
  • 8

2 Answers2

8

Yes, it is possible with the use of the Tasks Shell Input Extension. It provides a vscode command that can return the result of a shell command.

The relevant parts of my workspace looks like this.

"launch": {
    "configurations": [
        {
            ...
            "processId": "${input:FindVivadoPID}",
            ...
        }
    ],
    "inputs": [
        {
          "id": "FindVivadoPID",
          "type": "command",
          "command": "shellCommand.execute",
          "args": {
            "command": "pgrep 'ecold.*lnx64.g/vivado' -f",
            "description": "Select your Vivado PID",
            "useFirstResult": true,
          }
        }
    ]
}

Whenever I run Start Debugging, it automatically finds the relevant process and attaches.

See also using a shell command as VSCode task variable value which talks about the extension more generally.

KyleMit
  • 30,350
  • 66
  • 462
  • 664
cynthi8
  • 801
  • 3
  • 10
  • That was a fantastic answer, thanks a lot! And for others who need the extension but cannot see it from within VS code, I suggest use the link above to download the extension manually and "Install from VSIX..." - all seems working now, really nice, thanks! – Okay Dokey May 21 '21 at 13:29
0

If you can use LLDB and the Shell Input Extension doesn't work well for some reason, your program can also call Visual Studio Code with the debug information to ask it to connect as described here.

Rust:

#[cfg(debug_assertions)]
{
    let url = format!("vscode://vadimcn.vscode-lldb/launch/config?{{'request':'attach','pid':{}}}", std::process::id());
    std::process::Command::new("code").arg("--open-url").arg(url).output().unwrap();
    std::thread::sleep_ms(1000); // Wait for debugger to attach
}

C:

char command[256];
snprintf(command, sizeof(command), "code --open-url \"vscode://vadimcn.vscode-lldb/launch/config?{'request':'attach','pid':%d}\"", getpid());
system(command);
sleep(1); // Wait for debugger to attach

Or add this to launch.json:

    // This waits a second and calls VS code to attach lldb
    "preLaunchTask": "Attach LLDB Later"

And then add this to tasks.json:

{
    "label": "Attach LLDB Later",
    "type": "shell",
    "command": "/bin/bash",
    // Called from a preLaunchTask.  First wait for it to start up.
    // Then call VS code and tell it to attach with the LLDB debugger.
    "args": ["-c", "echo Waiting for launch...;sleep 2; code --open-url \"vscode://vadimcn.vscode-lldb/launch/config?{\\\"request\\\":\\\"attach\\\",\\\"pid\\\":$(pgrep --full --newest godot.\\*remote-debug)}\";echo LLDB attached."],
    "isBackground": true,
    // All this is needed so VSCode doesn't complain about the background task.
    "problemMatcher": [
        {
        "pattern": [
            {
            "regexp": ".",
            "file": 1,
            "location": 2,
            "message": 3
            }
        ],
        "background": {
            "activeOnStart": true,
            "beginsPattern": ".",
            "endsPattern": ".",
        }
        }
    ]
},

But change "pgrep --full --newest godot.\*remote-debug" to search for your process. I used this to debug two languages simultaneously on the same Godot executable. A Compound Launch with the GDScript debugger and Tasks Shell Input Extension tried to start both debuggers simultaneously, and wouldn't even start the executable I wanted the PID until after the LLDB launch was configured. The background preLaunchTask fixed this catch-22.

nathan
  • 412
  • 4
  • 8