C++ and Linux support in Visual Studio 2017

This will be a post about the support that Visual Studio 2017 introduces for C++ developers and really has nothing to do with my main act, Azure. You may have noticed that I have written numerous posts about the open source support the Azure platform has. Now it is time to highlight that new version of Visual Studio is moving in the same direction.

Visual Studio for Mac

The obvious thing to notice is that Visual Studio now exists in a Mac edition. It is not just Xamarin with lipstick on it. Visual Studio for Mac makes it possible to have developers in your team that do DotNet development on their Mac. It requires of course that you develop for DotNet Core, but if you do, your team will have one common tool across platforms.

Visual Studio Cross Platform

Console Application (Linux)

If you do New Project > Other Languages > C++ you will find a section named Cross Platform with a few project types to choose from. Console Application (Linux) creates a console project that is intended be compiled and debugged on a Linux machine, but where you write the code on your Windows machine using Visual Studio.

In order to set up which Linux machine you will be using, you need to add via Tools > Options and navigate to Connection Manager. In my case it is a Ubuntu 16 in Azure.

The source code will be copied at build time to the remote machine to the path you specify under Project Properties > General > Remote Build Root Directory. The default is set to ~/projects by VS, but I changed it to ~/src here. If you want to modify the g++ compiler directives you will find them under Project properties > C/C++.

Building your project makes it copy the sources to the remote machine and invoke the g++ compiler.

Hitting F10 to start debugging, you will get the same experience as if you were debugging locally even if Visual Studio is interacting with gdbserver on the Linux machine. In the Debug menu you have a new menu item called Linux Console which opens up a window to show you the programs output. This is pretty cool stuff!

Makefile projects

If your C++ project is built using an already existing makefile the above approach is not what you want. In this case you should select the project type to be Makefile project (Linux). To test this I cloned the following project from Git https://github.com/avih/miniweb since it is a fairly complex C/C++ project that builds with a makefile. The project also has a Visual Studio 2012 Solution file, showing that it has been compiled on Windows in the past. I create a new project of type Makefile project (Linux) and copy add all source files needed. The difference from the previous project is that the Configuration Type says Makefile and that the Remote Build settings are basic instructions to jump into the project folder and run make

 The compiler emits a few warnings about the mixed usage of datatypes int/size_t, but the build succeds I could start debugging the target. If your breakpoints doesn’t get hit in Visual Studio, it’s because the gdbserver hasn’t found all symbols it needs and you should consider doing a Rebuild All. In worst case, you need to delete everything on the Linux machine before rebuilding.

Non-Visual Studio C/C++ projects

The two approaches above are really great news and a step forward, but both approaches requires that you create Visual Studio specific files, like the .sln and the .vcxproj files. What if you just want to clone something from Git (or other) that have no such files and you really do not want to go through the process of creating them either? Well, that is possible too

For this demo, I’ll use FreeRCT available on github https://github.com/FreeRCT/FreeRCT . It is an open source roller coaster game. In the readme text you’ll see it says “Linux is officially supported, although Windows should work”. Challange accepted!

In the build instructions, it says that the projects builds with CMake. Luckily Visual Studio 2017 now supports CMake, so that’s no problem. Futhermore, it says that it depends on other open source projects, such as libpng, SDL2 and SDL2-ttf. This is where it used to be extra painful to be a C++ developer on Windows, because not only do we need how to figure out how to build FreeRCT, we now also need to figure out the other dependant projects. Who knows if this cascades further….

Say hello to vcpkg

Python has pip, Node has npm and DotNet has Nuget, and C/C++ for Visual Studio now has a tool called vcpkg that you can download and build from https://github.com/Microsoft/vcpkg. It is an ecosystem for using open source C/C++ packages. It means that if any developer in the community has already solved how to build libpng on Windows using Visual Studio, we can leverage that work.

So with the two simple commands below I can download and build the dependancies I need thanks to the community.

vcpkg install zlib libpng lzo freetype icu liblzma --triplet x64-windows
vcpkg integrate install

Visual Studio Open Folder

A new feature in Visual Studio 2017 is that you now can open a project simply by opening the folder that you like. This is exactly what we want to to with the FreeRCT project since we don’t want to bother with sln-files, etc. You do this by typing “devenv <path>” at the command rpompt or File > Open > Folder inside Visual Studio. VS scans through the folder and determinds what to make out of it. In the FreeRCT case it realizes that it is a CMake project though it finds the CMakeLists.txt file

We need to make one modification to be able to compile FreeRCT and that is to tell it where to find all componants that vcpkg built for us. We do this by creating a file called CMakeSettings.json. All the  variables I added, like ZLIB_INCLUDE_DIR etc, are named in the cmake files that exist in the project. A bit of detective work to find them all, but if you are lazy you can just build it and see what errors you get and fix it from there.

{
  "configurations": [
    {
      "name": "x86-Debug",
      "generator": "Visual Studio 15 2017",
      "buildRoot": "${env.LOCALAPPDATA}\\CMakeBuild\\${workspaceHash}\\build\\${name}",
      "configurationType": "Debug",
      "cmakeCommandArgs": "",
      "buildCommandArgs": "-m -v:minimal -p:PreferredToolArchitecture=x64",
      "variables": [
        {
          "name": "ZLIB_LIBRARY",
          "value": "${WorkspaceRoot}/../vcpkg/installed/x86-windows/debug/lib/zlibd.lib"
        },
        {
          "name": "ZLIB_INCLUDE_DIR",
          "value": "${WorkspaceRoot}/../vcpkg/installed/x86-windows/include"
        },
        {
          "name": "PNG_LIBRARY",
          "value": "${WorkspaceRoot}/../vcpkg/installed/x86-windows/debug/lib/libpng16d.lib"
        },
        {
          "name": "PNG_PNG_INCLUDE_DIR",
          "value": "${WorkspaceRoot}/../vcpkg/installed/x86-windows/include"
        },
        {
          "name": "SDL2_LIBRARY",
          "value": "${WorkspaceRoot}/../vcpkg/installed/x86-windows/debug/lib/sdl2.lib"
        },
        {
          "name": "SDL2_INCLUDE_DIR",
          "value": "${WorkspaceRoot}/../vcpkg/installed/x86-windows/include/SDL2"
        },
        {
          "name": "SDL2TTF_LIBRARY",
          "value": "${WorkspaceRoot}/../vcpkg/installed/x86-windows/debug/lib/sdl2_ttf.lib"
        },
        {
          "name": "SDL2TTF_INCLUDE_DIR",
          "value": "${WorkspaceRoot}/../vcpkg/installed/x86-windows/include/SDL2"
        }
      ]
    }
  ]
}

Building and running FreeRCT is just a matter of right clicking on the CMakeLists.txt file and select Build in the menu. You’ll notice in the output window that Visual Studio actually creates a temporary vcxproj file in the AppData\Local directory to drive the build. Debugging the project also requires that you select the CMakeLists.txt file in Solution Explorer.

Summary

Using the new C/C++ Cross Platform features in Visual Studio 2017 you can now do the following

  • Create a new Visual Studio project that you build and debug on a remote Linux machine
  • Use already existing projects that builds with it’s own makefile or CMake and build and debug on a remote Linux machine, thereby avoiding creating the Visual Studio specific .sln and .vcxproj-files
  • Use the vcpkg tool to leverage the developer ecosystem for open source tools
  • Use Visual Studio for Mac

If you’ve been using Visual Studio for a long time, maybe even since -97, you will notice that this is not your father’s Visual Studio. When doing cross platform C/C++ development in the past, I used to do the steps manually that Visual Studio now have built in support for. Now I don’t which is a huge step forward.