Type: Debugger
I need to setup environment variables from a setup.bash file for a ROS project.
The default ROS development cycle is:
source /opt/ros/melodic/setup.bash
source ./devel/setup.bash
catkin_make
Since the cpp debugger happily ignores sources environment variables in the preLaunchTask and also likes to ignore forced ~/.profile initialization in a VSCode Devcontainer context with Docker,
i thought I could easily bypass this problem, by running a preLaunchTask that writes the full environment to a file an then I load it again with envFile.
Unfortunately this last workaround also does not work. :disappointed:
Describe the bug
To Reproduce
envFilepreLaunchTask, that writes to the `envFilelaunch.json
{
// See https://go.microsoft.com/fwlink/?LinkId=733558
// for the documentation about the tasks.json format
"version": "2.0.0",
"configurations": [
{
"name": "(gdb) Launch",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/devel/myapp/lib/myapp",
"args": [],
"stopAtEntry": false,
"cwd": "${workspaceFolder}",
"environment": [],
"MIMode": "gdb",
"setupCommands": [
{
"description": "Enable pretty-printing for gdb",
"text": "-enable-pretty-printing",
"ignoreFailures": true
}
],
"preLaunchTask": "prerun-launch",
"envFile": "${workspaceFolder}/devel/temp_launch.env",
"externalConsole": false,
}
]
}
task.json
{
// See https://go.microsoft.com/fwlink/?LinkId=733558
// for the documentation about the tasks.json format
"version": "2.0.0",
"tasks": [
{
"label": "prerun-launch",
"type": "shell",
"command": "source /opt/ros/melodic/setup.bash && source /catkin_ws/devel/setup.bash && env | head -n -1 > ${workspaceFolder}/devel/temp_launch.env",
"presentation": {
"reveal": "never",
"panel": "shared"
}
}
]
}
Additional context
envFile is evaluated before preLaunchTask.
If I run the task first, and then run the debugger it works fine.
Failed to use envFile. Reason: ENOENT: no such file or directory, open '/catkin_ws/devel/temp_launch.env'
This would be due to how VS Code handles launching the debugger.
It goes from resolveDebugConfiguration -> resolveTasks -> createDebugAdapterDescriptor.
We read and setup the envFile in resolveDebugConfigurations since that is the only time we can handle the debug configuration before it is sent off to the debug adapter.
You will need to reach out VS Code to enable a way for you to run tasks before running resolveDebugConfiguration.
A possible workaround for now is to use miDebuggerPath which will execute within the debug adapter (after preLaunchTasks). You can point miDebuggerPath to your environment setup script and have it execute gdb.exe at the end.
Make sure to pass any arguments given to the script to gdb at the end.
Having a similar issue here, with what I suspect is the same root cause. It's very counter-intuitive that when you specify an envFile, you cannot reference values in that file in other parts of the launch configuration, such as "miDebuggerServerAddress": "${env:REMOTE_HOST_SOCKET}" to allow the user to attach to an arbitrary gdbserver socket. The motivation to do this is to not require input, since there are multiple tasks defined to set up the remote host in different ways, and the user already filled out inputs there to complete the task. If they just initialized host 192.168.1.155 they should not have to input the same data again when connecting.
launch.json specifies these values:
{
// ...
"envFile": "${workspaceFolder}/.vscode/remote_debug.env",
// ...
"miDebuggerServerAddress": "${env:REMOTE_HOST_SOCKET}",
// ...
}
When I try, and add verbose logging, here is my output鈥攑lease note the first line resolves MIDebuggerServerAddress to an empty string, and the last lines later resolve the environment.
1: (183) LaunchOptions WaitDynamicLibLoad='true'
--> E (output): {"type":"event","event":"output","body":{"category":"console","output":"1: (183) LaunchOptions MIDebuggerServerAddress=''\r\n"},"seq":20}
1: (183) LaunchOptions MIDebuggerServerAddress=''
--> E (output): {"type":"event","event":"output","body":{"category":"console","output":"1: (183) LaunchOptions ExternalConsole='true'\r\n"},"seq":22}
1: (183) LaunchOptions ExternalConsole='true'
--> E (output): {"type":"event","event":"output","body":{"category":"console","output":"1: (183) LaunchOptions>\r\n"},"seq":24}
1: (183) LaunchOptions>
--> E (output): {"type":"event","event":"output","body":{"category":"console","output":"1: (184) LaunchOptions <SetupCommands>\r\n"},"seq":26}
1: (184) LaunchOptions <SetupCommands>
--> E (output): {"type":"event","event":"output","body":{"category":"console","output":"1: (184) LaunchOptions <Command IgnoreFailures='true' Description='Enable pretty-printing for gdb'>-enable-pretty-printing</Command>\r\n"},"seq":28}
1: (184) LaunchOptions <Command IgnoreFailures='true' Description='Enable pretty-printing for gdb'>-enable-pretty-printing</Command>
--> E (output): {"type":"event","event":"output","body":{"category":"console","output":"1: (184) LaunchOptions </SetupCommands>\r\n"},"seq":30}
1: (184) LaunchOptions </SetupCommands>
--> E (output): {"type":"event","event":"output","body":{"category":"console","output":"1: (184) LaunchOptions <Environment>\r\n"},"seq":32}
1: (184) LaunchOptions <Environment>
--> E (output): {"type":"event","event":"output","body":{"category":"console","output":"1: (184) LaunchOptions <EnvironmentEntry Name='REMOTE_HOST_SOCKET' Value='192.168.1.155:1234' />\r\n"},"seq":34}
1: (184) LaunchOptions <EnvironmentEntry Name='REMOTE_HOST_SOCKET' Value='192.168.1.155:1234' />
--> E (output): {"type":"event","event":"output","body":{"category":"console","output":"1: (184) LaunchOptions </Environment>\r\n"},"seq":36}
1: (184) LaunchOptions </Environment>
In my experience envFile declared variables don't get passed to the debugee.
I am having the same issue - I am using my build prelaunchTask to create my environment file, I would like that to complete before getting to the launch config which loads the envFile.
This issue has been closed automatically because it's labeled as 'external'.
@WardenGnaw The concept and the semantics of "environment variables in an envFile" is not part of VS Code. It is purely an implementation detail of a specific debug extension. So the cpptools debug extension is in full and only control.
Please note that the "resolveDebugConfiguration" hook is called before the "preLaunchTasks" and the "resolveDebugConfigurationWithSubstitutedVariables" is called after. The reason for this order is that the "prelaunchtask" property can use variables like ${defaultBuildTask} which must be resolved before the task becomes known.
So if the "preLaunchTask" modifies an envFile, these changes will only be seen if the envFile is read in the "resolveDebugConfigurationWithSubstitutedVariables" (or even later in the debug adapter itself).
The debugger already reads envFile in the resolveDebugConfigurationWithSubstitutedVariables method.
That means cpptools will correctly pick up an envFile that was updated by a "preLaunchTask".
This change was made in https://github.com/microsoft/vscode-cpptools/commit/dcc1f93f1c4f658f51a5043d0a091eea4406bf91 on Oct 26, 2020 and has been in since release 1.1.0
Most helpful comment
This change was made in https://github.com/microsoft/vscode-cpptools/commit/dcc1f93f1c4f658f51a5043d0a091eea4406bf91 on Oct 26, 2020 and has been in since release 1.1.0