Visual C++ for Linux Development

Post updated on 6/17/2016 to remove mention of a dependency no longer needed and pull contact info to top.
Post updated on 6/14/2016 to include content from the 1.0.3 Update.
Post updated on 9/13/2016 to include content from the 1.0.5 Update, added a TOC, and updated how to report issues.

The Visual C++ for Linux Development extension enables you to author C++ code for Linux servers, desktops and devices. You can manage your connections to these machines from within VS. VS will automatically copy and remote build your sources and can launch your application with the debugger. Our project system supports targeting specific architectures, including ARM. Read on for how to get started with our new Linux projects.

Today we only support building remotely on the Linux target machine. We are not limited by specific Linux distros but we do have dependencies on the presence of some tools. Specifically, we need openssh-server, g++, gdb and gdbserver. Use your favorite package manager to install them, e.g. on Debian based systems:

sudo apt-get install openssh-server g++ gdb gdbserver

We do watch for comments on our blog posts and the extension gallery page. That does become hard to track so you can also reach us directly via our GitHub hosted issue list, email at vcpplinux-support@microsoft.com or find me on Twitter @robotdad.

This post is updated with content from update posts on this extension when they occur. As it has become lengthy here are the sections within this post.

Installation

Download the Visual C++ for Linux Development extension or get it from the extension manager in Visual Studio.

To get started create a new project by going to Templates > Visual C++ > Cross Platform > Linux.

Projects

Today we have three templates available; Blink for IoT devices like the Raspberry Pi, Console Application as a bare application, and Empty for you to add sources and configure from a clean slate.

Your First VS Linux Project

Let’s get started by creating a Console app. After creating your project from that template set a break point on the printf statement then hit F5 or the Remote GDB Debugger button. By default, the Console Application is set to a debug/x64 configuration. If your remote target is x86 or ARM you’ll want to change those options first. In this example I’m using a x64 Ubuntu VM.

ArchOptions

Since this is our first time targeting a Linux machine you will be prompted for connection information.  This is triggered by building the project.

Connect to Linux - first connection

We support both password and certificate base authorization, including use of passphrases with certificates. Upon a successful connection we save your connection information for subsequent connections. You can manage your saved connections under Tools > Options > Cross Platform > Linux. Yes, passwords/passphrases are encrypted when stored. We plan to support connecting without saving the connection information in a future update.

Upon connecting, your sources will be copied to the remote Linux machine and we will invoke gcc to build the sources with the options from the project properties. After the build successfully completes, your code will be launched on the remote machine and you will hit the break point you set earlier.

printf break

Linux Project Properties

Let’s take a look at the project properties to understand where things got deployed on the remote Linux machine.

Remote settings no connections

Under remote settings, you will see the remote root is set to ~/projects/ by default and that we are setting the remote project directory to match our project name in that location. If we take a look on the Linux machine, we’ll find main.cpp as well as our build artifacts in ~/projects/ConsoleApplication1.

OutputTypes

Looking at the General settings for the project, you can see how our output and intermediate directories were configured. Additionally, you’ll see that this project was configured as an application – thus our executable is under bin/x64/Debug/ as ConsoleApplication1.out. Notice that for configuration types we also support static and dynamic libraries.

Console window

We have a console window for interacting with your remote executables. This window shows not just the output of your program but can also take input. To activate this window use the menu Debug, Linux Console. This is what it looks like in action.

Console Window

Here is a simple program you can try these features out with.

#include <cstdio>

void log(char filename[], char visitor[])
{
	FILE * pLog;
	pLog = fopen(filename, "a");
	if (pLog != NULL)
	{
		fputs(visitor, pLog);
		fputs("\n", pLog);
		fclose(pLog);
	}
}

int main(int argc, char* argv[])
{
	if (argc != 2) 
	{
		printf("Please pass filename as input parameter\n");
		return 1;
	}
	char input[20];
	printf("What IDE are you using?\n");
	scanf("%19[0-9a-zA-Z ]", input);
       printf("%s! You can use that with me?!\n", input);
	log(argv[1], input);
       return 0;
}

Specify a filename in the Command Arguments input on your project’s Debugging property page. You can set a working directory on that page as well, if it is not set your home directory will be the working directory.

Debug Property Page

Linux IoT Projects

Now let’s take a look at an IoT device, the Raspberry Pi. You can use any type of Pi running Raspbian. For our blink sample we use wiringPi – if you don’t have this setup you can either install it via apt or from source. To add a new connection, go to Tools > Options and search for Linux. Now click add to connect to your Raspberry Pi.

PiConnection

Go to project properties and take a look under Build Events at Remote Post-Build Events.

Remote post build event

You can use this to execute a command on the remote Linux target after build. This template comes preconfigured to export the GPIO pin for the LED so that we don’t have to run our executable as root.

Now connect an LED to pin 17 on your Raspberry Pi as shown here.

LEDWiring

Open main.cpp and set a breakpoint on the delay call after the first digitalWrite and hit F5. You should see your LED light up and execution will pause at your breakpoint. Step through your code over the next digitalWrite call and you will see your LED turn off.

How to use the VC++ for Linux with the Intel Edison board

Using the VC++ for Linux extension with the Intel Edison board is largely like any other Linux system. First you’ll want to make sure you’ve setup your device following Intel’s instructions. You should be able to connect to your Edison via our connection manager once you have connected it to your Wi-Fi network. If you need a direct connection to your Edison use these instructions for using Ethernet over USB with your Edison which will also work with our connection manager.

The Edison makes it easy to start building an IoT application with sensor data. Accessories like the Arduino shield open make it easy to connect add-ons like the Grove shield from Seeed Studios. That shield lets you use any of the many available Grove sensors without having to worry about wiring a circuit on a breadboard, you can just get straight to your code. Intel has made this even easier to use with their UPM sensor library that covers a broad range of sensor including the Grove ones.

Shown here is an Edison compute module on an Arduino expansion board with a Grove shield attached and a temperature sensor plugged in.Edison module

In Visual Studio, create a new project, and under VC++, Cross Platform, Linux select Empty Project. Make sure that you set your solution platform to x86 when targeting the Edison. Add a C++ file to the project and use the code from this Grove Temperature Sample from Intel. The UPM libraries are part of the default Yocto Linux image used on the Edison so no additional setup is needed to acquire them. You should change the include statement in the sample to properly reference their location as follows:

#include <upm/grove.h>

With that change, you are ready to build and run your code. Here you can see the output of this sample in Visual Studio’s debug mode. If you are wonder about that first output line the first read from this type of sensor is often a bit off.

Edison Debugging in VS

To enable IntelliSense follow the instructions below for copying your include files locally from your Edison. At this time, we do have an IntelliSense bug that impacts this sample that will be fixed in a future update.

In a future post we’ll cover taking this sample further by connecting it to Azure IoT Hub.

Visit our IoT Development page to stay current on all of our offerings in this space.

Desktop Applications

We’ve covered headless and device Linux applications, what about desktop? Well, we have something special here: we’re going to launch an OpenGL app on a Linux desktop. First make sure your Linux desktop has been configured for OpenGL development. Here are the apt packages we used: libgles1-mesa, libgles1-mesa-dev, freeglut3, freeglut3-dev.

Now create an empty Linux project and go grab the source for Spinning Cube from Julien Guertault’s OpenGL tutorial. Extract it and add main.c to your project. To enable Intellisense you will need to add the OpenGL headers to the VC++ Directories, you can get them from the OpenGL Registry.  Now go to your project properties and add export DISPLAY=:0.0 to the Pre-Launch command.

Linker input

Now, under Linker Input add the library dependencies: m;GL;GLU;glut.

Also, make sure your remote settings are for the right machine.

ChangeRemote

Now hit F5.

UbuntuSpinningCube

A couple of interesting places to put breakpoints are around line 80 where the cube rotation is set (try changing the alpha value) or in KeyboardFunc where you can inspect the values of the pressed key.

Makefile Project Template

The Makefile project template supports using external build systems on your remote machine (make, gmake, CMake, bash script etc.). This works as you would expect under the C++ project property pages you can set your local Intellisense paths, then on the remote build property page you add the commands, semicolon separated, to trigger your build on the remote machine. In the example here I’m switching to my remote directory with my build script and then executing it.

I’ve thrown together some bash scripts that can generate our makefile project with your sources based on the directory structure. These scripts do assume that the source code on the Linux machine is in a directory that has been mapped to Windows. They do set the new flag in the project properties to not copy files remotely. These are unlikely to meet all needs but should give you a good starting point if you have a large project.

Makefile project proeprties

Usage tips

In this section we’re going to provide tips on using the extension to make you more productive.

Verbose build output

We’ve gotten a lot of questions about what exactly are the arguments being passed to GCC. Our build output doesn’t make this obvious, but you can enable it. There are two ways to get to the same place to change this setting. In the quick input window search for “verbosity”, or under Tools, Options go to Projects and Solutions, Build and Run. Now for the option of MSBuild Project output verbosity change it to diagnostic to see everything in your output window when you build. This can really help you find what exactly was passed to GCC to build your program if you are having issues.

Getting your include files

Everyone loves IntelliSense, but we’re not yet synchronizing the include files from your Linux system. Everyone has their own ways to either share or copy these files which is great. I wanted to share a really simple way to accomplish this I used in prepping the next section on the Intel Edison. I simply grab the whole folder locally onto my Windows box using PSCP.

pscp -r root@192.168.2.15:/usr/include .

Now on your project properties go to the VC++ Directories page and add your local path.

Remote file copy management

It is possible to specify at the file and project level whether or not a file should be remotely copied. This means you can use your existing build mechanisms just by mapping your existing sources locally and adding them to your project for editing and debugging.

Copy Sources project properties

Overridable C/C++ Compiler Path

You can override the compiler commands used on the remote machine in the Property Pages. That will enable you to point to specific versions of GCC if needed or even point to an alternate compiler like clang. You can use either full paths or a command available on your path.

Compiler project properties

Build Events

Under Build Events node of the project properties there are also new pre-build and pre-link remote build events as well as options for arbitrary file copy in all build events to provide greater flexibility.

Build events project properties

Debugging Options

In addition to supporting gdbserver we have a gdb mode to improve compatibility where we may not have the correct client gdb bits on Windows for the remote target.

Debugger mode project property

You can also override the debugger command itself, this is useful for debugging external programs compiled outside of VS.

Debug program project propery

The Debugging Property Page has support for additional gdb commands to be passed to the debugger to run when starting debugging. One example of where this can come in handy is Azure IoT projects. If you’ve used the Azure IoT C SDK on the Raspberry Pi you may have run into seeing an illegal exception being thrown when you start debugging. This is caused by some interactions between libcrypto and gdb. You can find some discussion of this issue here. While debugging can continue you can avoid this error by passing an instruction to the debugger before it starts, in this case “handle SIGILL nostop noprint”.

Debug commands project property

Reporting issues

In addition to our support email alias, vcpplinux-support, VC++ for Linux has a public issue list on GitHub. This is a great option for having public discussion or reporting bugs. We have added our backlog for the extension here as well. You can see what we are targeting for a release by looking at the milestone tagged to an issue.

So please do follow our GitHub issue list and use it by either submitting feedback or +1 existing feedback there. We love hearing about how and where our extension is being used. Feel free to use our support email alias if you want to share that with us even if you don’t have any issues. You can also find me on Twitter @robotdad.

Again, thank you for your feedback and keep it coming.

Go Write Some Native Linux Code

We hope you are as excited by the possibilities this opens up as we are.

Install the Visual C++ for Linux Development extension, try it out and let us know what works for you, what doesn’t or if you encounter any issues. If your focus is IoT remember to check out our IoT Development page to stay current on happenings there. You can reach us here through the blog, on the extension page on the gallery, via the VS Feedback channel, or find our team @visualc or me, @robotdad, on Twitter.

– Marc Goodner

Changes

We always post our change logs on the Visual Studio Gallery page for the Linux extension, but here is the complete tally since our original release.

8/19/2016 v1.0.5

  • Major performance improvements with incremental copy and build, and considerably reducing the number of connections
  • Makefile project support for external build system support (make, CMake etc)
  • Over ridable C/C++ compiler path in Property Pages
  • Remote source copy management per file/project: no copy, and/or override destination path
  • Debug command override, useful for debugging external programs
  • Pre-build and pre-link remote build events
  • Arbitrary file copy as part of the build events
  • Over ridable timeouts through project for command execution, compile, link and archiver.
    • Add elements to project file under <PropertyGroup Label=Globals> to override default value of 30 minutes. Values are:
    • RemoteExecuteTimeout, RemoteCompileCommandTimeout, RemoteLdCommmandTimeout, or RemoteArCommmandTimeout
  • Debugging Property Page support for additional gdb commands for the debugger to run before starting debugging (debugger bootstrap commands)
  • Linux console hang during infinite loops bug fix
  • Default to IPv4 when using hostnames
  • Custom local/remote ports ignored bug fix
  • Linker error parsing updates
  • Fixed ““” escaping issue
  • Connection manager uname -m, machine arch parsing bug fix
  • Remote project directory is set to a system directory bug fix
  • MIEngine bits moved up to Update 3

7/8/2016 v1.0.4

  • Bug fix for new source files in empty projects
  • Added clean support
  • Fixes bugs in remote target changes not triggering new build required
  • Use first successful connection, instead of last successful, as the default connection
  • General performance improvements
  • Major IntelliSense fixes
  • New experimenal debugging mode, gdb over the shell, which offers greater compatibility

6/6/2016 1.0.3

  • Added a console I/O Tool Window for interacting with remote process launched from VS
  • Added support for working directory and command line arguments for the debugged process
  • Added ability to use files outside the project directory
  • UI for system information (OS/architecture) in the Tools – Options
  • C++14 support IntelliSense bug fix
  • Connect to Linux dialog UI bug fixes
  • Linux Connections UI remove connection after add bug fix
  • Fixes an access denied bug when uploading read only files
  • Fixes -x c, -x c++ bug and compiling as C
  • FreeBSD, OSX partial support, including connections, compile and link. Debugging is not supported yet.
  • Performance improvements

4/14/2016 v1.0.2

  • Removed the dependency on Android NDK and Android MDD bits
  • Intel Edison support and bug fixes
  • Fix for login as root
  • Fixes the occasional “4444 port in use”
  • Fixes the “no such file” bug
  • Local and remote ports in the Property Pages are not dependent on each other and each can be supplied individually
  • Fixes a bug with removing entries from Linux Connection Manager
  • Resource management (leaked sshd processes) fixes
  • General robustness fixes in the Connect dialog
  • Gdbserver cleanup at the end of debugging
  • Improved build diagnostics and linker errors parsing from build
  • Fix for empty output file name extension, now the output can have no file extension

4/4/2016 v1.0.1

  • Fixed crash during login