Visual Studio Code Debug: source and then launch on same shell - c++

My current workflow for a project is the following:
build the project (via catkin)
source a setup.sh script (generated by catkin, which I wouldn't like to modify) setting environment variables and the names needed by my executable.
Run "MyProgram", which is only available after sourcing the "setup.sh" script.
I would like to be able to debug my project in Visual Studio Code. To do this, I have defined a task building the executable via catkin, named "catkin build all", and I have defined a second task as:
{
"type": "shell",
"label": "load programs",
"command": "source /some_folder/setup.sh",
"group": "build",
"dependsOn": ["catkin build all"]
}
Which is the "preLaunchTask" of my lanuch.json launch configuration.
Launching debug will correctly compile the project, but execution fails with error "launch: program myProgram does not exist". Indeed program MyProgram can not be found if setup.sh is not sourced, but is should be sourced by the "preLaunchTask".
In my launch.json i can also set "program" to "/full/path/to/myProgram" instead of "myProgram", but in this case shared libraries are not found, as setup.sh would take care of that.
I have also tried to source setup.sh on a shell and then launch visual studio code from the same shell, but this did not solve the "launch: program myProgram does not exist" problem.
Do tasks run on different shells? How can I have the preLaunchTask running in the same shell as the subsequent program code? Or any other hint on how to get my workflow working?

My solution is to use a env_file
In one terminal, source your file such as: source /opt/ros/melodic/setup.bash
Recover the changes by using: printenv | grep melodic
Create a .env file in your repo with the environment variables; (except PWD)
LD_LIBRARY_PATH=/opt/ros/melodic/lib
ROS_ETC_DIR=/opt/ros/melodic/etc/ros
CMAKE_PREFIX_PATH=/opt/ros/melodic
ROS_ROOT=/opt/ros/melodic/share/ros
PYTHONPATH=/opt/ros/melodic/lib/python2.7/dist-packages
ROS_PACKAGE_PATH=/opt/ros/melodic/share
PATH=/opt/ros/melodic/bin:/home/alexis/.nvm/versions/node/v8.16.1/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin
PKG_CONFIG_PATH=/opt/ros/melodic/lib/pkgconfig
ROS_DISTRO=melodic
Add the following line to your launch.json task: "envFile": "${workspaceFolder}/.env"
Note: this could be automated in a prerunTask using:
command: "source /opt/ros/melodic/setup.bash; printenv | grep melodic > ${workspaceFolder}/.env"

Perhaps this might help after a zoom.
Got that info from here

Related

Compiling a cpp file with vscode, in Ubuntu

I'm trying to follow this link on how to get started with c++ and vscode in ubuntu.
I have gcc already installed with the latest version.
Running sudo apt-get install build-essential gdb gives:
Reading package lists... Done
Building dependency tree
Reading state information... Done
build-essential is already the newest version (12.8ubuntu1.1).
build-essential set to manually installed.
gdb is already the newest version (9.2-0ubuntu1~20.04.1).
gdb set to manually installed.
0 upgraded, 0 newly installed, 0 to remove and 2 not upgraded.
However, when I get to the stage of creating the config file, I have no option for C/C++: g++ build active file. I only have
So, I choose /usr/bin/cpp.Then I build the file, and get the success message.
However, when run the newly created executable file, I get several error messages:
./helloworld: line 17: namespace: command not found
./helloworld: line 23: syntax error near unexpected token `('
./helloworld: line 23: ` typedef decltype(nullptr) nullptr_t;'
the strange thing is that the lines with code in the helloworld file end on line 16, so I think there's something wrong with the compiler...
Its best to get GCC working in your commandline, then get it working using VS Code tasks.
I suggest that you create the most simplistic project structure you can. Use only a project directory, and a single file named main.cpp.
Something that looks like this:
PROJECT (dir) // path = ./
│
└──> main.cpp (file) // path = ./main.cpp
Once you have a directory with main.cpp do 1 of 2 things:
Use the following command to add a Hello World example to your main.cpp file.
$> echo -e "\n#include <iostream>\n\nusing namespace std;\n\nint main()\n{\n cout << \"Hello World\!\" << endl;\n}" > main.cpp
Or copy and paste the code below into main.cpp
#include <iostream>
using namespace std;
int main()
{
cout << "Hello World!" << endl;
}
FYI: You should be doing this from the command-line not vscode (not until you create the vscode task which I will show bellow)
Another thing to note, is your commandline should be pointed to your project directory, the directory you created with main.cpp in it.
From inside your project directory execute the following command.
$> g++ ./main.cpp -o build
if your file compiled & built your executable correctly you should be able to use the ls command to see a new file named build in your project directory.
If all went well, the new build file is an executable. Execute it by entering...
$> ./build
and you should see "Hello World!"
At this point use the following command...
$> code .
VS Code should open to your projects directory.
Now using vscode create another directory, and name it ./.vscode
Then add a file to the ./.vscode directory named tasks.json
The files full pathname will be: ./.vscode/tasks.json
then you will want to add the following to your tasks file
"version": "2.0.0",
"tasks": [
{
"type": "shell",
"label": "GCC: My Compilation Task",
"command": "/usr/bin/g++",
"args": ["-g", "./main.cpp", "-o", "./build"],
"options": {
"cwd": "/usr/bin"
},
"problemMatcher": ["$gcc"],
"group": {
"kind": "build",
"isDefault": true
}
}
]
}
then you should be able to press F1 and type RUN TASK, when you see the option in the quick menu that says RUN TASK click it, and then select the tasks with the same name as the label key in your tasks.json file, which is "GCC: My Compilation Task"

Sublime Text 3 intel oneAPI Fortran build system

Has anyone figured out how to write the build system for the oneAPI Fortran compiler?
Previously, i was using Parallel Studio XE ifort, and i managed to get it working using the solution here:
{
"cmd": ["cmd", "/e:on", "/v:on", "/k", "ipsxe-comp-vars intel64 vs2013 && ifort ${file}"],
"file_regex": "^.*\\\\([0-9A-Za-z_]+\\.[A-Za-z0-9]+)\\(([0-9]+)\\):[ ]+error[ ]+#([0-9]+):[ ]+(.*)$",
"working_dir":"${file_path}",
"selector":"source.f ,source.for ,source.ftn ,source.f90 ,source.fpp ,source.i ,source.i90",
"encoding":"cp936",
"path":"C:\\Program Files (x86)\\IntelSWTools\\compilers_and_libraries_2017.4.210\\windows\\bin;${path}",
"variants":
[
{
"name": "Run",
"cmd": ["cmd", "/e:on", "/v:on", "/c", "ipsxe-comp-vars intel64 vs2013 && ifort ${file} && ${file_base_name}"]
}
]
}
I tried changing the paths to the new ones but it doesn't work. I get the following error:
"ipsxe-comp-vars" is not recognized as an internal or external command,
program o executable.
I found the answer. Explanation below. Posting the working build system here for visibility.
This should be the build system:
{
"cmd": ["cmd", "/e:on", "/v:on", "/S", "/k", "C:\\\"Program Files (x86)\"\\Intel\\oneAPI\\setvars.bat intel64 vs2022 && ifort ${file}"],
"file_regex": "^.*\\\\([0-9A-Za-z_]+\\.[A-Za-z0-9]+)\\(([0-9]+)\\):[ ]+error[ ]+#([0-9]+):[ ]+(.*)$",
"working_dir":"${file_path}",
"selector":"source.f ,source.for ,source.ftn ,source.f90 ,source.fpp ,source.i ,source.i90",
"encoding":"cp936",
"path":"C:\\Program Files (x86)\\Intel\\oneAPI\\compiler\\latest\\windows\\bin\\intel64;${path}",
"variants":
[
{
"name": "Run",
"cmd": ["cmd", "/e:on", "/v:on", "/s", "/c", "C:\\\"Program Files (x86)\"\\Intel\\oneAPI\\setvars.bat intel64 vs2022 && ifort ${file} && ${file_base_name}"]
}
]
}
Why the problem happens
For starters, ipsxe-comp-vars is a batch file which when run, sets up environment variables required to execute the intel compilers. This file is specific to Intel Parallel Studio XE (IPSXE). Now, when installing IPSXE, it would add this batch file to your PATH, meaning you could simply call ipsxe-comp-vars from any directory to set up the required environment variables.
Intel oneAPI has a differently named file, that essentially does the same thing, called setvars.bat. This file is stored in:
C:\Program Files (x86)\Intel\oneAPI\setvars.bat
So, at first it seems that calling ipsxe-comp-vars fails because the file is named differently. However, unlike IPSXE did with ipsxe-comp-vars, oneAPI does not add setvars to PATH, so you cannot simply call setvars, you have to usethe full path.
How to solve it
With IPSXE, you could call ipsxe-comp-vars and it would run the batch file that sets up environment variables, but with oneAPI either you add the file to PATH (not reccomended because it has a generic name), or you use the full path when calling it (same as above):
C:\Program Files (x86)\Intel\oneAPI\setvars.bat
Now, because you have to plug this in into the build system config, you need to format it correctly. ST runs the commands in a cmd.exe, so you have to use the correct options and format the path in a way that cmd can understand it:
options (you can get a full list by opening a cmd prompt, typing cmd /? and hitting return):
- /e:on Enables command extensions
- /v:on Enables extension of environment variables
- /s Modifies how the string following a /c or /k is read
- /k Executes the string command and continues
The path to the setvars.bat file must be formatted as follows:
C:\\\"Program Files (x86)\"\\Intel\\oneAPI\\setvars.bat
Each \ separating dirs needs to be escaped (using \ as well)
needs to be enclosed in double quotes, since it contains a whitespace. Each double quote needs to escaped as well (once again with )
The following options are specific to the setvars.bat file:
- intel64 specifies 64-bit configuration
- vs2022 specifies Visual Studio 2022 as the developer cmd or
powershell version to use
Finally, ifort is called on the current file with ifort ${file}
Additionally, the build system is completed with a variant "Run". This variant runs the output file once it has been compiled(&& ${file_base_name}), and will show the output in the Sublime Text 3 console (does not accept inputs, if anyone knows how to setup up sublimeREPL for Fortran please tell me)

Run script to setup environment in VSCode after connecting to container or before compling/debugging

I am working on a docker containerized c++ project that has defined shell scripts to setup the environment (using "source") for compiling and debugging. They have a lot of environment variables and could change at anytime so it would be hard to move them all into the launch.json file (and tedious to keep up with) so I need to call them before compiling or debugging.
The scripts only need to run once so if there was a way to run them after connection to the container that would be the best solution, however I cannot find anything like that.
I have tried to use the "preLaunchTask" in the launcher to run a task before debugging but it seems that the task's shell is different from the debug shell.
Is there anyway to handle this?
For the moment I am using a task to generate a .env file
printenv > ${workspaceFolder}/.preenv && . ${workspaceFolder}/setupEnv &&
printenv > ${workspaceFolder}/.postenv && grep -vFf
${workspaceFolder}/.preenv ${workspaceFolder}/.postenv >
${workspaceFolder}/.env
I have VSCode mount a directory as the container's homedir, and then put a .bash_profile file containing the necessary setups (or other suitable shell startup file) in that directory.
My /path/to/.devcontainer/devcontainer.json includes:
"mounts": [
"source=${localWorkspaceFolder}/.devcontainer/home,target=/home/username,type=bind,consistency=delegated"
],
"remoteUser": "username",
"userEnvProbe": "loginShell", // Ensures .bash_profile fires
Then my /path/to/.devcontainer/home/.bash_profile contains the necessary invocations to set my environment.

How to debug binary module of nodejs?

I have a node.js module written in C++ that provides some bindings for a C++ library. The library crashes with SIGSEGV, so I need to debug it with GDB and find out what goes wrong.
I already have the source for the module in ./node_modules/somelib/ and if I go to that folder and type npm install the library is compiled and can be used through a require('somelib') from node.js. I can attach gdb to node and reproduce the error, but in the stacktrace I just see node_modules/somelib/Release/somelib.node.
I'm not sure if this is important but the library is compiled using node-gyp.
Question 1: How do I load the source code or point gdb to the source code?
Question 2: How do I configure node-gyp to produce debug symbols?
I just found the answer to this in the node-gyp documentation. The solution is to invoke the build process with the --debug flag. That means to invoke node-gyp configure --debug and/or node-gyp build --debug. Then instead of a Release folder a Debug folder will be created. gdb will then automatically load the source files.
Shamelessly copied from an archive of the (now broken) link provided by #Peter Cordes
First, compile your add-on using node-gyp with the --debug flag.
$ node-gyp --debug configure rebuild
Second, if you're still in "playground" mode like I am, you're probably loading your module with something like
var ObjModule = require('./ObjModule/build/Release/objModule');
However, when you rebuild using node-gyp in debug mode, node-gyp throws away the Release version and creates a Debug version instead. So update the module path:
var ObjModule = require('./ObjModule/build/Debug/objModule');
Alright, now we're ready to debug our C++ add-on. Run gdb against the node binary, which is a C++ application. Now, node itself doesn't know about your add-on, so when you try to set a breakpoint on your add-on function (in this case, StringReverse) it complains that the specific function is not defined. Fear not, your add-on is part of the "future shared library load" it refers to, and will be loaded once you require() your add-on in JavaScript.
$ gdb node
...
Reading symbols from node...done.
(gdb) break StringReverse
Function "StringReverse" not defined.
Make breakpoint pending on future shared library load? (y or [n]) y
OK, now we just have to run the application:
(gdb) run ../modTest.js
...
Breakpoint 1, StringReverse (args=...) at ../objModule.cpp:49
You can add the directory containing the source of the module to gdb's search path:
(gdb) directory /path/to/source
See: http://sourceware.org/gdb/onlinedocs/gdb/Source-Path.html
Also, to get node-gyp debug symbols, install node-gyp-dbg/dev or equivalent, or compile it with -g
If you are a VSCode user, you may find this helpful inorder to debug your module.
Basic steps are:
Install the vscode plugin https://github.com/vadimcn/vscode-lldb
Setup your launch.json to look like this :
{
"version": "0.2.0",
"configurations": [{
"type": "lldb",
"request": "launch",
"name": "Launch Program",
"program": "/absolute/path/to/node",
"args": [
"/absolute/path/to/your/index.js"
]
}]
}
Then setup breakpoints as you would in VS Code.
Happy debugging!
I have also published a detailed blog here if you want more detailed explanation.
https://medium.com/#atulanand94/debugging-nodejs-c-addons-using-vs-code-27e9940fc3ad

Sublime Build System for Gradle

I want to have a custom build system but am really not able to make one. I have Gradle 1.2 installed and even the GRADLE_HOME is set correctly now I have the following commend in the build system file
{
"cmd": ["gradle","build.gradle"],
"path": "$project"
}
And the error I get is as follows (when I try to build my project):
[Errno 2] No such file or directory
[cmd: [u'gradle', u'build.gradle']]
[dir: /home/roger/Project/Visage/HelloWorld/src/main/visage/visage/javafx]
[path: $project]
[Finished]
Actually my Project Base directory is HelloWorld and I have my build.gradle there itself. Please help me to write the correct build system or give the correct commands to avoid error and execute successfully. I am currently using UBUNTU 12.04
I think you have to use a shell for your build system. and instead of path I guess you mean "working_dir". can you try this:
{
"cmd": ["gradle"],
"shell": "true",
"working_dir": "${project_path}"
}
cheers,
René
Even shorter Gradle configuration in Sublime Text 3:
{
"shell_cmd": "gradle",
"working_dir": "${project_path}"
}
Go to menu 'Tools > Build System > New Build System...' and paste this text. Then save the configuration file as 'Gradle.sublime-build'.