C++ with Visual Studio 2019 and Windows Subsystem for Linux (WSL)

Erika Sweet

Erika

In Visual Studio 2019 version 16.1 Preview 3 we have added native support for using C++ with the Windows Subsystem for Linux (WSL). WSL lets you run a lightweight Linux environment directly on Windows, including most command-line tools, utilities, and applications. In Visual Studio you no longer need to add a remote connection or configure SSH in order to build and debug on your local WSL installation. This will save you time getting up and running in a Linux environment and eliminates the need to copy and maintain sources on a remote machine. In order to use our native support for WSL you will need to install the Linux Development with C++ workload in Visual Studio.

In this blog post, we’ll first look at how to set up WSL. We will then walk-through how to use it with a CMake project and MSBuild-based Linux project. If you are just getting started with our native support for CMake, be sure to check out our CMake Support in Visual Studio introductory page too.

Setting up WSL

You can find details on how to install WSL here, but the easiest way is to download your distro of choice (Ubuntu, Debian, etc.) from the Windows Store.

To configure your WSL installation to work with Visual Studio you need the following tools installed: gcc, gdb, make, rsync, and zip. You can install them on distros that use apt with this command:

sudo apt install g++ gdb make rsync zip

The inclusion of rsync and zip allows Visual Studio to extract header files from your WSL instance to the Windows filesystem to use for IntelliSense. Due to the lack of visibility into the root file system of WSL from Windows, a local rsync copy is done inside WSL to copy the headers to a Windows visible location. This is a one-time operation that Visual Studio performs to configure IntelliSense for Linux connections.

Visual Studio CMake projects and WSL

Let’s start by looking at a simple CMake project.

1. Start Visual Studio 2019 (version 16.1 or later) and create a new CMake project using the “CMake Project” template or open an existing one.

2. Navigate to the configuration drop-down menu and select “Manage Configurations…” This will open the CMake Settings Editor.

"Manage Configurations..."
3. Visual Studio creates an x64-Debug or x86-Debug configuration by default. You can add a new WSL configuration by clicking on the green plus sign above the configuration manager on the left-hand side of the editor.

Add a new connection
4. Select a WSL-Debug configuration.

Select a WSL-Debug configuration
5. By default, Visual Studio will pick up on your default WSL configuration. If you have side-by-side installations of WSL, then you can specify which WSL executable Visual Studio should use by setting the “Path to WSL executable” property under the “General” section of the CMake Settings editor.

6. Save the editor (Ctrl + S) and select your WSL-Debug configuration as your active configuration using the configuration drop-down menu at the top of the page. This will start the cache generation of your WSL configuration.

Select WSL configuration
7. If you don’t have CMake on your WSL installation, then you will be prompted to automatically deploy a recent version of CMake from Visual Studio. If you are missing any other dependencies (gcc, gdb, make, rsync, zip) then see above for Setting up WSL.

8. In the Solution Explorer expand the project subfolder and in the .cpp file set a breakpoint in main() .

9. In the launch bar change the launch target from “Current Document” to your project name.

10. Now click “Start” (Debug > Start) or press F5. Your project will build, the executable will launch, and you will hit your breakpoint. You can see the output of your program (in this case, “Hello CMake”) in the Linux Console Window.

Debug program to see "Hello CMake"

 

Visual Studio MSBuild-based projects and WSL

We also support using WSL from our MSBuild-based Linux projects in Visual Studio. Here are the steps for getting started.

1. Create a new Linux Console Application (you can filter platform by Linux and look for “Console App”) in Visual Studio 2019 version 16.1 or later or open an existing one.

2. Right-click on the project in the Solution Explorer and select “Properties” to open the Project Property Pages.

3. In the dialog that opens you will see the “General” property page. On this page, there is an option for “Platform Toolset.” Change this from “Remote_GCC_1_0” to “WSL_1_0.”

4. By default, Visual Studio will target the WSL installation that is set as the default through wslconfig. If you have side-by-side installations of WSL, then you can specify which WSL executable Visual Studio should use by setting the “WSL *.exe full path” option directly below “Platform Toolset.” Press OK.

5. Set a breakpoint in main.cpp and click “Start Debugging” (Debug > Start Debugging). If you are missing any dependencies on your WSL installation (gcc, gdb, make, rsync, zip) then see above for Setting up WSL. You can see the output of your program in the Linux Console Window.

Give us your feedback!

If you have feedback on WSL or anything regarding our Linux support in Visual Studio, we would love to hear from you. We can be reached via the comments below or via email (visualcpp@microsoft.com). If you encounter other problems with Visual Studio or MSVC or have a suggestion, you can use the Report a Problem tool in Visual Studio or head over to Visual Studio Developer Community. You can also find us on Twitter (@VisualC) and (@erikasweet_).


Coming soon…

More announcements about AddressSanitizer integration for Linux projects, Code Analysis quick fixes, and Quick Info improvements are coming to the C++ Team Blog later this week. Stay tuned!

Erika Sweet
Erika Sweet

Follow Erika   

44 comments

    • Erika Sweet
      Erika Sweet

      Hi Histro, this would require the separation of build and debug targets, which was just announced today. Unfortunately this support does not apply to native WSL configurations yet, so you will need to connect to WSL via SSH and treat it as a remote connection or order to separate your build machine (WSL) from your deploy/debug machine (ARM device) 

  • Avatar
    David Hunter

    Hi, works great for the test program. Our software has already moved on from GCC 7 which is what you get by default on Ubuntu Bionic. I did try GCC 8 and Clang 8 and they seemed to work for the test. Should I expect them to work in general for large code bases?

  • Avatar
    Warren Buckley

    I’ve tried following this walkthrough but VS2019 does not see the WSL. None of the options you showed for selecting the WSL appears in either the CMakeConfig or the property pages of a Linux console project..
    Edit: Nevermind, didn’t see that I needed the preview version of VS in order to use this feature.

  • Avatar
    Ike Starnes

    WSL_1_0 is not an option in the “Platform Toolset” for a brand new VCXPROJ. I only see “Remote_GCC_1_0” in the drop down list.

    Edit: Also, for a CMake project, WSL options are NOT availble when trying to add a new configuration. Seems something is missing.

  • Avatar
    Patrik Huber

    I followed this tutorial exactly (with the CMake example project), changed the launch target to the executable, and when I hit F5 (Debug), I get an error dialog box “The given key was not present in the dictionary.”. The output window shows the following:

    cd /mnt/c/Users/Patrik/VSCMakeProjectWSLTest/VSCMakeProjectWSLTest/out/build/WSL-Debug;export CXXFLAGS=-fsanitize\=address;export CFLAGS=-fsanitize\=address;export LDFLAGS=-fsanitize\=address;$HOME/.vs/cmake/bin/cmake –build “/mnt/c/Users/Patrik/VSCMakeProjectWSLTest/VSCMakeProjectWSLTest/out/build/WSL-Debug” –target VSCMakeProjectWSLTest ;
    [100%] Built target VSCMakeProjectWSLTest

    Edit: Sorry for the bad formatting, not sure how to format code/output here, backticks and “>” didn’t work.

    • Avatar
      Kostrzewa, Kevin P. (TR Tech, Content & Ops)

      I received the same error dialog (The given key was not present in the dictionary) with VS2019 version 16.1.0 Preview 3.0
      The output window shows
      cd /mnt/c/Users/kevin/source/repos/crossPlatformWSLTest-pvw/out/build/WSL-Debug;$HOME/.vs/cmake/bin/cmake –build “/mnt/c/Users/kevin/source/repos/crossPlatformWSLTest-pvw/out/build/WSL-Debug” –target crossPlatformWSLTest-pvw ;
      [100%] Built target crossPlatformWSLTest-pvw

      • Johannes Otepka
        Johannes Otepka

        Exact same problem for me (although I get the error message in German “Der angegebene Schlüssel war nicht im Wörterbuch angegeben.”). Do you need further details on my system?
        Please fix this issue, since I’m really looking forward to use this feature…

  • Avatar
    屿 罗

    Hi Erika, good feature! I’m wondering how to deploy my project after development. Do I still need to open a remote connection?

    • Erika Sweet
      Erika Sweet

      Nope! You no longer need to open a remote connection when working with WSL. For MSBuild-based Linux projects you can deploy your solution by selecting “Deploy Soltution” (Build > Deploy Solution). The solution is also automatically deployed when you start a debugging session. You can see where the executable is located in the Debug pane of the output windows (e.g. /mnt/c/Users…).

  • Avatar
    游 虎

    Project build success. But got this error and all headers cannot be loaded and IntelliSense is totally broken:
    Unable to find a stored connection for machine ”. Please add a new connection using Tools > Options > Cross Platform > Connection Manager.

    Project: https://github.com/btccom/btcagent/tree/deveth
    Clone to G:\work\btcagent.vs2019 (mount to /mnt/g/btcagent.vs2019 and /g/btcagent.vs2019 in WSL).
    VS2019 version 16.1.0 Preview 3.0.

  • Avatar
    Кузнецов Евгений Олегович

    When using the WSL + MSBuild, I ran into the following problems:
    1) It seems to be missing the “Lib” target in Linux.WSL.targets, so its impossible to build a static library.
    2) Parallel compilation doesn’t work.
    3) MSBuild doesn’t check if the translation unit should be rebuilt, so it always rebuilds the whole project.
    MSBuild WSL support is the great functionality, and I hope it will be fixed in the new preview and it will be possible to use it.

    • Erika Sweet
      Erika Sweet

      Issues 1 and 3 will be resolved in future updates – I will post back here when they are available for download. Can you please open a feature suggestion on Developer Community for the second issue (parallel compilation?) This will allow you to engage with our team directly, track the suggestion’s status, and provide transparency to other user’s with the same issue. Thank you! 

  • Avatar
    Mark de Wit

    I’m loving this feature!  I’ll try out the WSL integration for sure.  Here is some early feedback:
    I have a version of cmake built from the kitware sources myself – this installed in /usr/local/bin/cmake, but it appears you only search for cmake in /usr/bin.  It would be great if you could either expand the locations you search, or use whatever cmake appears in the path?

    Update: I managed to build something (created a softlink to my cmake binary to proceed).  However, when trying to run the debugger I only get a dialog with the error message: The given key was not present in the dictionary”.   No further information as to which key, what dictionary.   Note – my WSL is Ubuntu 18.04, gcc 7.4.0

    • Erika Sweet
      Erika Sweet

      Hey Mark, glad to hear you’re enjoying the feature! For future reference, you can change the path to the CMake executable in the CMake Settings Editor > Advanced Settings (link at the bottom of the editor) > CMake executable. The “given key not present in the directory” error is a known issue and will be fixed in the next release of version 16.1. I’ll circle back here when it’s available. 

    • Avatar
      Elizabeth Morrow

      Hi Mark!
      Really happy to hear you’re using the new feature. In your cmakesettings.json file you can specify a path to your cmake installation without the soft link by clicking the “Show advanced settings” hyperlink in the cmake settings editor and modifying the contents of “CMake executable path”.
      The “given key was not present in the dictionary” bug has been fixed in Preview 4. 
      Thanks,
      Elizabeth

  • Avatar
    Andrew Luo

    “The inclusion of rsync and zip allows Visual Studio to extract header files from your WSL instance to the Windows filesystem to use for IntelliSense. Due to the lack of visibility into the root file system of WSL from Windows, a local rsync copy is done inside WSL to copy the headers to a Windows visible location. This is a one-time operation that Visual Studio performs to configure IntelliSense for Linux connections.”
    Isn’t it possible to perform read-only access to the WSL filesystem via AppData\Local\Packages\CanonicalGroupLimited.UbuntuonWindows_79rhkp1fndgsc\LocalState\rootfs for example?  In the official VS Code documentation (https://code.visualstudio.com/docs/cpp/config-wsl) this is how it’s done.  Also, in the latest version of Windows (1903), isn’t the WSL filesystem directly accessible via \\wsl$?  I’m just wondering if it’s necessary to make this copy given these improvements.

  • Lawrence Mukwaya
    Lawrence Mukwaya

    For all the very clear steps, Setup GDB debugger fails to initialize – GDB works fine on the linux side. My hope is, Preview 4 has addressed my concern. 

  • Avatar
    Иван Моденов

    Hi Erica, got problem trying to use clang on WSL-Linux.
    I use libc++, but Intellisense can’t understand that from my CMakeLists.txt, and suggests things using libstdc++ headers (in particular I’m trying to get Intellisense suggestions for stuff from <filesystem> header).
    Project compiles and debugging works just fine, only Intellisense don’t work properly.
    My CMake file:
    cmake_minimum_required(VERSION 3.10)project (brain)add_compile_options(-stdlib=libc++)add_compile_options(-std=c++17)
    add_executable(brain main.cpp)target_link_libraries(brain c++ c++fs)

  • Avatar
    James Hartley

    So I followed this setup guide and I’m getting an error after I add WSL-Debug in the configurations manager and try to build. Output: 1> CMake generation started for configuration: ‘WSL-Debug’.1> Found cmake executable at $HOME/.vs/cmake/bin/cmake.1> C:\Users\JDBHa\Documents\Visual Studio Projects\CMakeProject1/CMakeLists.txt does not exist

    EDIT: So I moved my project folder to the root of C drive instead of documents and it’s working now. although i’m not entirely sure why.

  • Avatar
    Kevin Irick

    I’m really enjoying this feature.  My current CMake project requires me to debug using elevated privileges on Linux.  Is there a way to specify running the debug session in WSL as sudo or root user?  I’ve used VisualGDB for the same capabilities and there is an option to run as sudo.

  • Daniel Howard
    Daniel Howard

    Erika this may be a tangential question but perhaps you can help me.  I built an computer intensive AI windows executable that runs on the customers PCs.  It can run standalone but I occasionally need for this code to talk to a remote server or to my company website hosted on the cloud.  So I want to do this programmatically invisibly to the user.  I need a socket or something with the password of the server and server IP address and so on.  It seems simple but it appears difficult from Visual Studio visual C++.  The server is running Linux and probably has SSH.

  • Kelly Choi
    Kelly Choi

    Hi Erika

    I’ve followed both of your tutorials above and they work great! Is there any way to add files/folders from the WSL file system though? Or do all of the source files reside on the windows file system?

    I’ve been able to open folder/files through VSCode connected remotely to WSL, just wondering if it is possible in VS2019?

Leave a comment