Writing and debugging Linux C++ applications from Visual Studio using the "Windows Subsystem for Linux"
I've blogged about the "Windows Subsystem for Linux" (also known as "Bash on Ubuntu on Windows") many times before. Response to this Windows feature has been a little funny because folks try to:
- Minimize it - "Oh, it's just Cygwin." (It's actually not, it's the actual Ubuntu elf binaries running on a layer that abstracts the Linux kernel.)
- Design it - "So it's a docker container? A VM?" (Again, it's a whole subsystem. It does WAY more than you'd think, and it's FASTer than a VM.)
Here's a simple explanation from Andrew Pardoe:
1. The developer/user uses a bash shell.
2. The bash shell runs on an install of Ubuntu
3. The Ubuntu install runs on a Windows subsystem. This subsystem is designed to support Linux.
It's pretty cool. WSL has, frankly, kept me running Windows because I can run cmd, powershell, OR bash (or zsh or Fish). You can run vim, emacs, tmux, and run Javascript/node.js, Ruby, Python, C/C++, C# & F#, Rust, Go, and more. You can also now run sshd, MySQL, Apache, lighttpd as long as you know that when you close your last console the background services will shut down. Bash on Windows is for developers, not background server apps. And of course, you apt-get your way to glory.
Bash on Windows runs Ubuntu user-mode binaries provided by Canonical. This means the command-line utilities are the same as those that run within a native Ubuntu environment.
I wanted to write a Linux Console app in C++ using Visual Studio in Windows. Why? Why not? I like VS.
Setting up Visual Studio 2017 to compile and debug C++ apps on Linux
- I've got Visual Studio Community, which is free for small groups and open source.
- I make sure my Windows 10 is up to date and has Bash on Ubuntu installed.
- The "Windows 10 Creators Edition" is out April 11th but if you're a Windows Insider or use the Update Assistant you can get it on April 5th. It includes a bunch of improvements to Bash on Windows (release notes)
Then, from the bash shell make sure you have build-essential, gdb's server, and openssh's server:
$ sudo apt update
$ sudo apt install -y build-essential
$ sudo apt install -y gdbserver
$ sudo apt install -y openssh-server
Then open up /etc/ssh/sshd_config with vi (or nano) like
sudo nano /etc/ssh/sshd_config
and for simplicity's sake, set PasswordAuthentication to yes. Remember that it's not as big a security issue as you'd think as the SSHD daemon closes when your last console does, and because WSL's subsystem has to play well with Windows, it's privy to the Windows Firewall and all its existing rules, plus we're talking localhost also.
Now generate SSH keys and manually start the service:
$ sudo ssh-keygen -A
$ sudo service ssh start
Create a Linux app in Visual Studio (or open a Makefile app):
Make sure you know your target (x64, x86, ARM):
In Visual Studio's Cross Platform Connection Manager you can control your SSH connections (and set up ones with private keys, if you like.)
Boom. I'm writing C++ for Linux in Visual Studio on Windows...running, compiling and debugging on the local Linux Subsystem
It would be good if in the future the cmake integration could automagically pull in the source and other dependencies for us. The we could just tell VS to open a cmake project, plug in our cmake build arguments and go.
Another thing is the build and debug. We currently cross compile to x86_64 and ARM then copy the application to a device to debug it. There's not really any way to do that from within VS at the moment. For now we're stuck with a VM and Eclipse :(
initctl: Unable to connect to Upstart: Failed to connect to socket /com/ubuntu/upstart: Connection refused
I'm getting the following error when running sudo apt-get update after doing the previous steps on dot.net:
W: Failed to fetch https://apt-mo.trafficmanager.net/repos/dotnet-release/dists/trusty/main/binary-amd64/Packages gnutls_handshake() failed: Handshake failed
Since we don't have that today I did provide some bash scripts that can generate our current makefile projects from your existing code bases. You can use this to invoke whatever build process you have on the Linux side. I normally git clone in bash on my windows box then run these scripts.
If you want to reach me or our dev team directly you can find us at vcpplinux-support microsoft.com
ap:~$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description: Ubuntu 14.04.4 LTS
Release: 14.04
Codename: trusty
I'm not seeing that in VS2015 though, I assume this is new to VS2017.
Comments are closed.
In my situation, I have a 500+ source project with 14 static/dynamic libs in a CMake build system. If I want the full debugging experience (breakpoints, stepping, variable inspection, etc) on Linux, I must import the source, project, etc into these Visual Studio Project templates (eg Makefile Project template). It would be a lot of work and maintenance just for debugging within VS. If there is automation of this, it was beyond anything obvious with some web searches.
The perfect OOB scenario, would be to have VS 2017's new CMake integration, support this debugger. One build system to maintain. One VS instance. One VS "solution" (File->Open Folder). Compile/debug "all" platforms I target.