Debugging in GDB from Visual Studio
Add a new project
After installing the extension. You can create a new project type. Use:
File -> New -> Project... -> Templates/Visual C++/Cross Platform -> Makefile Project (GDB)
Note: If your solution have other configurations than Debug and Release, you may want to create additional project configurations for this project. This was my case when using CMake’s RelWithDebInfo.
First of all, we have to have a remote Unix-based machine (or even a local MinGW distribution) with
gdb and other developer tools installed. To start rapidly, I recommend you using vagrant. In the following that our machine has SSH listening on port
2200, user name is
vagrant and it is on the localhost (
If you use vagrant, the private key is in the
.vagrant/machines/default/virtual_box/private_key file. Unfortunately, it’s not in a format needed by the VS GDB extension. No problem though, we can use Puttygen tool to import the private key (in OpenSSH format) and save it into a
In the project properties, you should have something like this (see the Visual C++ Team blog post for some details).
- Remote Host Name:
- Remote User Name:
- Private Key:
- Secure Shell Executable:
- Remote Working Directory:
- Remote Executable: as you wish
- Remote Executable Arguments: as you wish
- Remote Debugger Executable:
Note: If your SSH daemon on the Linux listens on a non-standard port, e.g. 2200, add
-P 2200 to the end of Private Key (sic!). This will spare you a few problems.
- Build Command Line:
$(SecureShellExecutable) $(RemoteUserName)@$(RemoteHostName) -i $(PrivateKey) "LowerCaseConfiguration="%24(tr '[:upper:]' '[:lower:]' ^<^<^< $(Configuration) )"; cd $(RemoteWorkingDirectory)/../../project/$LowerCaseConfiguration; ninja $(RemoteExecutable)"
- Rebuild All Command Line:
pscp.exe -r -i $(PrivateKey) "C:workspacemy_source*" $(RemoteUserName)@$(RemoteHostName):$(RemoteWorkingDirectory)/../../qdb
The rebuild command will just overwrite all the files.
-r option will copy directories recursively. As you remember, I told you to add the port argument
-P 2200 to the private key. It’s useful here, we (nor extensions’ debug command) do not escape private key here so the additional argument will be used as we expect it. If we had chosen to add the port to the remote host name, this command would fail, because
$(RemoteHostName) would be expanded to
127.0.0.1 -P 2200 and so
pscp wouldn’t work.
The build command will, through SSH, go to the project directory and invoke ninja there.
I use the
$(Configuration) macro to make my life easy.
I have lower-cased the configuration name (using
tr) to go to the correct directory on the remote host.
I had to escape some characters as well.
First, we cannot write a dollar symbol
$ followed by an open bracket
(, because VS treats this in a special manner. To remedy this problem, we can use hexadecimal ASCII codes preceded by a percent sign
%, so we write
%24( instead of
Next, we have to escape the windows command line special characters
<<. So we write
^< instead of
If you don’t need such dirty hacks, just write:
$(SecureShellExecutable) $(RemoteUserName)@$(RemoteHostName) -i $(PrivateKey); cd $(RemoteWorkingDirectory)/../../project/$(Configuration); ninja $(RemoteExecutable)"
or even simpler
$(SecureShellExecutable) $(RemoteUserName)@$(RemoteHostName) -i $(PrivateKey); cd $(RemoteWorkingDirectory)/<project directory>; ninja <target>"
ninja, you can write
cmake --build $(RemoteWorkingDirectory)/<project directory> --target <target> as well.
One could just use
pscp as proposed in the VS blog post, but it will copy all files, even if there weren’t modified since the last copy. Use WinSCP instead. Have a look at keepuptodate task and script option.
# invoke with: "C:Program Files (x86)WinSCPwinscp.com" /script=name-of-this-file
open [email protected]:2200 # connect
option batch continue # resume on error
# exclude some directories
keepuptodate -filemask="|*/.git/;*/bin/*;*/project/*;*/thirdparty/" c:workspacemy_source /home/vagrant/my_source
Note: WinSCP should accept masks like
*/bin* that will omit
bin directory as well as
Do not forget to open the connection with WinSCP before, validate and accept the server fingerprint to avoid ugly warnings. In the script above, the name
[email protected]:2200 is the name of a connection created in WinSCP/PuTTy.
Alternatives: Some people use the
rsync from Cygwin. Others prefer their favourite editor’s plugin, e.g. Sublime Text has RSync plugin.
Get to work!
- Add breakpoints in existing projects of your solution.
There are some enhancements that would be welcome in this extension. Hopefully, the folks behind this extension will hear it… The list is minimalist:
- Add SSH port configuration: this will avoid our ugly hacks with passing port
-Pparameter in the private key.
- Synchronize automatically the files in the solution: ideally, no thirdparty software would be needed to synchronized modified files.
- Allow running without debugging (CTRL-F5): maybe that’s a problem in my configuration, but that just doesn’t work and it would make the life a bit easier.
That’s all for today. Don’t hesitate to share your thoughts and comments!