Visual C++ for Linux Development with CMake

In Visual Studio 2017 15.4 you can now target Linux from your CMake projects. This enables you to work on your existing code base that uses CMake as your build solution without having to convert it to a VS project. If your code base is cross-platform you can target both Windows and Linux from within Visual Studio.

Update 10/24/2017: 15.4.1 is in the Release channel now and addresses the setup issue previously noted here. 15.5 is in the Preview channel and removes the limitation on CMake 3.9, there CMake >= 3.8 can be used.

Getting Started

To enable this capability, make sure that you choose the Linux C++ Workload in the Visual Studio installer. The CMake support for Linux is selected by default for this workload. The CMake support in Visual Studio requires the server mode support that was introduced in CMake 3.8. See these instructions for building CMake from source if your package manager provides an older version.

To get started, create a simple CMakeLists.txt file in the same folder as a cpp file as in the example below. (via File > Open > Folder… or devenv.exe <foldername>).

As soon as you open this folder, Visual Studio will parse the CMakeLists.txt. By default, a Windows target of x86-Debug will be used. To target Linux, change the project settings to Linux-Debug or Linux-Release. When you do this, your source will be copied to your Linux machine where CMake will be run to generate the CMake cache for your project.

By default, the first remote system in the list under Tools > Options > Cross Platform > Connection Manager will be used. If you have not created any remote connections, you will be prompted to create one the first time you select a Linux target in your project settings.

To debug your code on the remote system, set a breakpoint, select the CMake target as the startup item in the toolbar menu next to the project setting, and click run (or press F5).

Configuring CMake Settings for Linux

To change the defaults that are used use the menu CMake > Change CMake Settings > CMakeLists.txt, or use the context menu by right clicking CMakeSettings.txt and choosing Change CMake Settings. This will create a new file in your folder called CMakeSettings.json. Initially this will be populated with the default configurations that are listed in the project settings menu item. Here is an example configuration for Linux-Debug based on the example above.

The name on line 2 can be of your choosing to identify your custom configuration. If you have more than one remote system defined, you can enter it in place of the default on line 4. IntelliSense is enabled for this field from your system to help you select the right system. The field remoteCMakeListsRoot on line 6 is where your project sources will be copied to on the remote system, by default under /var/tmp. The field remoteBuildRoot on line 9 is where the build output will be generated on your remote system, that output is also copied locally in the location specified by buildRoot on line 8.

Building a supported CMake release from source

The minimum version of CMake required on your Linux machine is 3.8, and it must also support server mode. To verify this run

cmake --version

To verify that server mode is enabled run

cmake -E capabilities

In the output look for “serverMode”:true. Note that even if compiling from source as described below you should check the capabilities when done. Your Linux system may have limitations that prevent server mode from being enabled. As one example we have run into issues with enabling server mode on Ubuntu 14.04 because of library and compiler limitations.

To get started building from source in the shell for your Linux system make sure your package manager is up to date, you have git and cmake available, then clone the CMake sources.

Now, make sure you are on a supported release of CMake for Visual Studio. We are actively tracking CMake development, but we cannot guarantee we support the latest.

15.4.1 is in the Release channel and supports up to 3.9.0 which you can ensure you build by running.

git checkout tags/v3.9.0

15.5 is in the Preview channel and removes the limitation on CMake 3.9, there CMake >= 3.8 can be used. You should be able to use the current release there.

Now to build and install a supported version, run the following commands.

mkdir out
cd out
cmake ../
make
sudo make install

The above will build and install the current release of CMake to /usr/local/bin. Verify the version is >= 3.8 and that server mode is enabled.

/usr/local/bin/cmake –version
cmake -E capabilities

Current Limitations

These are some known limitations that we are actively working on.

The Linux console window that enables input and output with a remote Linux application is not enabled for CMake yet. This is a limitation that this window currently only works for gdbserver mode, but our CMake support for Linux only works with gdb mode. This will be addressed in a future release.

What’s next

Download the Visual Studio 2017 Preview, install the Linux C++ Workload, and try our CMake support for Linux with your code. Let us know how it is or isn’t working for you. Your feedback matters.

I am in Windows with VS2017.4 and just did “File > Open > Folder”, this is when the error occurs. So it seems it naturally tries to run CMake for the Windows target first? (for which my project needs a CMake nightly build). So is there a way to make File > Open > Folder work with a CMake nightly on Windows?

Just chiming in here: 3.9.x (nightlies) added *a lot* of fixes for VS 2017.3 particularly with respect to C++17 so it would be really important to have it! (or have at least 3.10.0 as soon as it comes out in Oct/Nov but it will be a long wait :( )

I don’t have any strong feelings towards 3.9.1, or at least I have not encountered any of the problems that .1 addresses. I simply went and obtained the best and latest.

I am having some troubles though, but first I’m trying to solve them on my own, and once I make sure mistakes aren’t on my end, or simply a few bolts and springs are missing to make the experience awesome, I’ll return.

One clarification – do we need to be able to run CMake on Windows in order to use this? Or can we use this to build our project on Linux and Visual Studio will pull over the folder / project structure from the remote box?

Similarly, are we still restricted in intellisense pulling from our local box? Or will intellisense read from the remote CMakelist ? Actually..looks like this is still a TODO (github issue: #43 )

>> do we need to be able to run CMake on Windows in order to use this?

Hey that’s a good point! The first thing it does for me is run CMake locally (which currently fails, see my post above).
But the question is, if it’s all about building on a remote Linux and it’s executing CMake there anyway, why does it also need to execute it locally in VS. I’m sure there’s probably a reason for it. (I don’t think #43 is related)

For CMake for Linux, we don’t use anything local. Everything happens remotely. CMake is invoked remotely to generate the cache, then parse it. Build is invoked remotely as well. So is debugging. Regarding IntelliSense, you are correct. We currently designing an experience to fix that problem.

The reason for that is because Windows is the default configuration. So that runs first. If you switch the configuration to Linux, it will target Linux. Do you know see two Linux configurations in the dropdown?

1 year ago

Pete

No, there are just the 4 windows targets (or 2, I don’t remember and can’t currently check, but definitely just Windows targets and I found no way of adding/switching to Linux targets).

This is great!
Finally a simple way to use the same physical project folder, source files and build specifications to develop cross platform applications for Windows and Linux.

I still hope for a direct integration of WSL, but this should also reduce the impact of the indirection through ssh, because the inner modify-compile-test cycle can largely run on Windows and then I only occasionally switch over to Linux to verify everything still works there.

How do I specify which source files/directories visual studio will copy on the remote linux machine. In my case the top level CMakeLists.txt file is in the project folder and all other CMakeLists.txt as well cpp/h files are in a sub-folder.

When doing this with an internal project, the parsing and such seem to work fine, although the “Startup” combobox never gets populated. What are the CMake conditions necessary in order to have targets (add_executable(target …)) to appear in the Startup combobox ?

I have created a samba share of my Linux project and opened the network share with the Visual Studio so that sources don’t have to be copied to remote Linux machine. So I have set “remoteCopySources”: false in CMakeSettings.json