VSCode with CMake-Tools run multiple targets - c++

I have a rather complex CMake project-structure with must be executed in very specific way and I don't find any references on how to achieve this. First of all I am using the CMake-Tools extension which works fine for the build process for all my targets.
Although it is a little bit more complicated the problem is basically the following: I have a main target which is a virtual prototype (VP) of a u-controller and an external target which is an application the VP loads with an ELF-Loader and executes. The VP contains an implementation of GDBServer which works fine and allows me to attach gdb with the remote target option. The VP is build as an executable which takes the path of the application as an argument. The application self is build with a cross-compiler toolchain.
At the moment I have created a launch.json for the VP target which looks like follows:
{
"name": "vp my_app",
"type": "cppdbg",
"request": "launch",
// Resolved by CMake Tools:
"program": "${command:cmake.launchTargetPath}",
"args": [
"--input-file", "${workspaceFolder}/src/apps/my_app/build/src/my_app.elf",
"--intercept", //intercepts syscall in application
"--debug-mode" //starts gdbserver
],
"stopAtEntry": false,
"cwd": "${workspaceFolder}",
"environment": [
{
"name": "PATH",
"value": "$PATH:${command:cmake.launchTargetDirectory}"
},
],
"externalConsole": false,
},
There are multiple issues with this config:
It starts a gdb session for the VP which is not necessary. I am considering to create a task.json for this but I am not sure if this is the best way.
The argument --input-file points to a file which is build by another CMake project and as far as I know its path can't be describes by using vscode variables of CMake-tools because it is in a different target. One way could be to install the application outside the cmake-build but this is also not an optimal solutions.
For the target my_app i have also a launch.json :
{
"name": "(gdb) attach vp",
"type": "cppdbg",
"request": "attach",
// Resolved by CMake Tools:
"program": "${command:cmake.launchTargetPath}",
"miDebuggerServerAddress": "localhost:5005",
"MIMode": "gdb",
"miDebuggerPath": "/usr/local/bin/riscv-unknown-elf-gdb",
"setupCommands": [
{
"description": "Enable pretty-printing for gdb",
"text": "-enable-pretty-printing",
"ignoreFailures": true
}
]
Currently, I first execute the launch of the vp target and then the launch of the application target. CMake-Tools ensures that both targets are build properly before executing them. This is fine and I can work with it but I am interesting in merging both launches and I can't figure out how to handle the build-path of both cmake-targets without switching and how to ensure their build. Maybe a workspace-task or the command extensions with specific defined inputs can be used but I am open to any suggestions. In a perfect world I would like to have a single launch.json which ensures the build of both applications then starts the vp with the elf.file of the application as an argument and attaches a gdb-session without switching cmake-targets all the time.
Thx

Related

Debugging unable to open source files

Environment
Ubuntu 20.04.
VS Code 1.69.0 with extensions
VS Code launch.json:
{
"version": "0.2.0",
"configurations": [
{
"name": "Test debug",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceRoot}/bazel-bin/app/mp_test",
"stopAtEntry": false,
"cwd": "${workspaceFolder}",
"externalConsole": true,
"MIMode": "gdb",
"setupCommands": [
{
"description": "Enable pretty-printing for gdb",
"text": "-enable-pretty-printing",
"ignoreFailures": true
}
],
}
]
}
Note: I use bazel to build mediapipe and my app. Do not know if it matters or not.
bazel build --copt="-g" --strip="never" --define MEDIAPIPE_DISABLE_GPU=1 //app:mp_test
Problem description
I have a code:
mediapipe::CalculatorGraph graph;
graph.Initialize(config);
I set breakpoints on the second line. Start debugging. After F11 (step into) execution cursor stands on the line. I repeated several time F11 and at the end it goes into some standard library code (unique_ptr exactly). I tried to use Stack Trace and double click on one of its entries. Look at the screenshot. So, debugger cann't open the source file, because it looks into /proc/self/cwd/external folder which doesn't exists. Meanwhile IntelliSence can find the definition of the mediapipe::CalculatorGraph::Initialize in mediapipe project directory and my app was built successfully, means that compiler (linker) found everything. Why? How can I fix it?
Note: Folder /proc/self/cwd/ contains files from my app folder (BUILD, main.cpp, ...).

Configure vscode to build and run c++ in one terminal

I installed mingw64 toolchain with MSYS2, and managed to successfully run my code from vscode. However, running it creates two terminals, one for building and one for running the generated file: C/C++: g++.exe build active file and cppdbg: main.exe.
cppdbg: main.exe leaves the text from the previous runs and "presentation" { "clear": true } in launch.json doesn`t help.
since build and run are not related, it's possible that the build will fail and the old .exe will be launched without me noticing it.
So I'm looking for a way to configure vscode to build and run the app in one terminal, or maybe redirect the compiler output to the output tab. Anything similar to how it's done in other languages.
Also, how can I configure it to run without debugging by default? In launch.json, "configurations" require a "type" parameter, which has only one option, "cppdbg" - why is there no release option?
You are asking two questions and I can answer both.
How do I build and debug the application, by making sure that it is launched only when the build is successful?
How do I configure it to run the application similarly?
Let me answer 2 first.
To solve this, you need the dependsOn property of tasks. For example, this is the content of my tasks.json file:
{
// See https://go.microsoft.com/fwlink/?LinkId=733558
// for the documentation about the tasks.json format
"version": "2.0.0",
"tasks":
[
{
"label": "Debug_Build",
"type": "shell",
"command": "g++ -g ./src/main.cpp -o ./bin/a.out",
},
{
"label": "Run main()",
"type": "shell",
"command": "./bin/a.out",
"dependsOn":"Debug_Build" //Previous task is run first, and then this one if previous was successful.
}
]
}
Notice that the second task (which is responsible for running the program) has dependsOn property which behaves exactly as you require: It will run only when the dependsOn task is successful (Which here is the build task)
To run the tasks, you can use the Command Palette to Run
Tasks>Run main()
to launch your task. Personally, I prefer using the extension Tasks, which creates a button for each task in the tasks.json file on the status bar of VS Code.
Now to answer 1, we use a similar property in the launch configuration json file: preLaunchTask
This will be exactly what you need: It will run the debugging only if the preLaunchTask was successful.
My launch.json file is as follows:
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "(gdb) Launch",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/bin/a.out",
"args": [],
"stopAtEntry": false,
"cwd": "${fileDirname}",
"environment": [],
"externalConsole": false,
"MIMode": "gdb",
"setupCommands": [
{
"description": "Enable pretty-printing for gdb",
"text": "-enable-pretty-printing",
"ignoreFailures": true
}
],
"preLaunchTask": "Debug_Build", //This is the part you need
}
]
}
So to summarize, you will need to create tasks.json and launch.json files in your workspace. In the tasks.json file, declare a "build" task, declare the "run" task which depends on the "build" task using the dependsOn property. Finally, in the launch.json file, refer the "build" task in the preLaunch property.

Error while debugging using gdb debugger on VS Code using Windows 10 and MINGW complier

I was following the documentation on https://code.visualstudio.com/docs/cpp/config-mingw to set up my C++ development environment on VS code.
I succesfully created my build task and ran my build task, but when i tried to set up my debugger (GDB debugger), i got the following output on the terminal.
C:\Users\Ayon\c++\helloworld> cmd /C "c:\Users\Ayon\.vscode\extensions\ms-vscode.cpptools-0.28.1\debugAdapters\bin\WindowsDebugLauncher.exe --stdin=Microsoft-MIEngine-In-shlwrnf5.x12 --stdout=Microsoft-MIEngine-Out-vg12hskh.c52 --stderr=Microsoft-MIEngine-Error-nrcvh0zz.0u0 --pid=Microsoft-MIEngine-Pid-m1nmxyvs.qk2 --dbgExe=C:\MinGW\bin\gdb.exe --interpreter=mi "
'cmd' is not recognized as an internal or external command,
operable program or batch file.
Im curious as to how the "cmd /" came about in the output. Please help me fix this error.
Thanks in advance.
For reference, here is my launch.json
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "g++.exe - Build and debug active file",
"type": "cppdbg",
"request": "launch",
"program": "${fileDirname}\\${fileBasenameNoExtension}.exe",
"args": [],
"stopAtEntry": false,
"cwd": "${workspaceFolder}",
"environment": [],
"externalConsole": false,
"MIMode": "gdb",
"miDebuggerPath": "C:\\MinGW\\bin\\gdb.exe",
"setupCommands": [
{
"description": "Enable pretty-printing for gdb",
"text": "-enable-pretty-printing",
"ignoreFailures": true
}
],
"preLaunchTask": "g++.exe build active file"
}
]
}
Did you add mingw64/bin to your system path? Here's how to do so:
Control panel -> Edit path -> Environment variables -> Path -> New
You can also find more guidance on
vscode official website.
I believe the problem is with the MinGW installation. I also faced this problem for a long time, solved it by doing the following:
Completely removing the current MinGW Video tutorial
Installing MinGW-w64 from the site mentioned in vscode documentation. installation video tutorial
After this, I followed the configuration mentioned in this video. The video is for c code, but you can make the required changes to c++ code. Now I'm able to debug in vscode.
By this way, you will also be able to use the latest versions of gdb and g++ available.

Visual Studio Code - Remote Debugging Bazel C++ - Unable to read file 'vscode-remote://dev- file

I'm trying to do remote debugging of bazel project in docker.
Local plugins: Remote Development
Docker plugins (defined in devcontainer.json): ms-vscode.cpptools
My launch.json
{
"version": "0.2.0",
"configurations": [
{
"name": "Debug",
"type": "cppdbg",
"MIMode": "gdb",
"request": "launch",
"args": [],
"stopAtEntry": true,
"cwd": "${workspaceFolder}",
"program": "/root/.cache/bazel/_bazel_root/e53bbb0b0da4e26d24b415310219b953/execroot/tf_serving/bazel-out/k8-dbg/bin/tensorflow_serving/fplugin/fserve_cc",
"externalConsole": false,
}
]
}
However I'm getting an error:
Unable to open 'fserve.cc': Unable to read file 'vscode-remote://dev-container+2f55736572732f6d67756d6f77736b2f776f726b2f6f766d732d63/proc/self/cwd/tensorflow_serving/fplugin/fserve.cc
In local development I would add sourceFileMap, however it doesn't seem to work for remote docker development. Any ideas?
when you try to compile with bazel, you will have 4 soft link(bazel-bin, bazel-{source-folder}, bazel-out, bazel-testlog)
modify this attribute wi
"cwd": "${workspaceFolder}/bazel-",
I'm not sure that your problem is due to remote debugging. I believe that the following info will work whether or not you're in a remote environment.
Bazel generates a few symlinks in your project's root folder that contain useful data (for more see the docs):
bazel-bin is a symlink to a folder in the output directory that contains generated code and binaries for the latest configuration of the build you've run.
bazel-{folder-name} is a symlink to the execRoot, which is how bazel sees your project's source code. {folder-name} is the name of the folder your project is in.
bazel-out is a symlink to bazel's output root.
bazel-testlog is a symlink to the outputs from test runs
If you're not using bazel's runfiles library
To provide VSCode with sources at the right location, modify the "cwd" attribute in launch.json to:
"cwd": "${workspaceFolder}/bazel-{folder-name}",`
If you are using runfiles
You're using runfiles if your program requires files in a data attribute in any of its dependencies
First, set "cwd" to the root of the runfiles tree for your binary, and then set "sourceFileMap" in a way that maps the current working directory to the execRoot symlink. For me (on linux), /proc/self/cwd maps correctly, but that might not be true for you. I was able to tell that I got it wrong because VSCode complained about being unable to read a file at /proc/self/cwd/external/external-project/src/file.cpp.
"cwd": "${workspaceFolder}/bazel-bin/path/to/executable/executable.runfiles/{workspace-name}`,
"sourceFileMap": {
"/proc/self/cwd": "${workspaceFolder}/bazel-{folder-name}`,
},
{workspace-name} can be found in WORKSPACE, it will look like workspace(name = "my-project"). If there is no workspace name defined in that file, it defaults to __main__.
I might also recommend changing the "program" attribute to a more convenient location. If the last thing you did was build your binary with bazel, you can find the built executable at bazel-bin/path/to/executable/executable
A full example:
{
"version": "0.2.0",
"configurations": [
{
"name": "(gdb) Launch Debug",
"type": "cppdbg",
"request": "launch",
// path to the most recently built version of executable
// this should be built with `bazel build -c dbg //path/to:executable`
"program": "${workspaceFolder}/bazel-bin/path/to/executable/executable",
"args": [],
"stopAtEntry": false,
"cwd": "${workspaceFolder}/bazel-bin/path/to/executable/executable.runfiles/{workspace-name}",
"environment": [],
"externalConsole": false,
"MIMode": "gdb",
"setupCommands": [
{
"description": "Enable pretty-printing for gdb",
"text": "-enable-pretty-printing",
"ignoreFailures": true
}
],
"sourceFileMap": {
"/proc/self/cwd": "${workspaceFolder}/bazel-{folder-name}"
}
}
]
}
Most of this is covered in this useful post (which also shows how to automatically build your executable using tasks.json):
https://shanee.io/blog/2019/05/28/bazel-with-visual-studio-code/

Debugging c++ built with a makefile in Visual Studio Code

I have an existing code base that builds with a makefile and I'd like to use Visual Studio Code to run it.
I started by opening my project directory with Visual Studio Code.
Then, for building I created a task as per http://code.visualstudio.com/docs/languages/cpp :
{
"version": "0.1.0",
"command": "bash",
"isShellCommand": true,
"args":["-c", "cd build && make"]
}
which works fine. I then downloaded the C++ extension and created a launch.json:
{
"version": "0.2.0",
"configurations": [
{
"name": "C++ Launch",
"type": "cppdbg",
"request": "launch",
"targetArchitecture": "x64",
"program": "${workspaceRoot}/build/myProgram",
"args": [],
"stopAtEntry": false,
"cwd": "${workspaceRoot}",
"environment": [],
"externalConsole": true,
"linux": {
"MIMode": "gdb"
},
"osx": {
"MIMode": "lldb"
},
"windows": {
"MIMode": "gdb"
}
},
// attach here, which I don't care about
]
}
This launch file allows me to start my program using the built-in debugger. I know that it works because I see all the symbol files getting loaded and I can pause the program.
However, VS Code doesn't "see" my source files; when I pause it says
Source /Unknown Source is not available.
I also can't set breakpoints in the source. I see that some symbols get loaded though as I can see my function names on the call stack when I pause execution.
So what did I miss? Do I absolutely have to do as they say here ( http://code.visualstudio.com/docs/languages/cpp ) and make a g++ task where I'll have to manually input all my include paths and linker inputs? The point of using a makefile in the first place was to not have to do this tedious stuff...
Thanks a lot to anyone who knows how to wrangle VS code.
You should be able to debug by just using tasks.json and launch.json.
Are you sure you have the -g option set in your makefile?
Another thing - you can have your task be executed on launch by adding
"preLaunchTask": "bash" to your your launch.json.
Hope this helps!
At windows; Mingw, gdb and -g parameter at compilation of the executable are necessary with c/c++ extension. "preLaunchTask": "bash" is not necessary in launch.json.