In Visual Studio 2019 you can target both Windows and Linux from the comfort of a single IDE. In Visual Studio 2019 version 16.1 Preview 3 we announced several new features specific to the Linux Workload: native support for the Windows Subsystem for Linux (WSL), AddressSanitizer integration, and the ability to separate build and debug targets. If you’re just getting started with cross-platform development, I recommend trying our native support for WSL.
Native support for the Windows Subsystem for Linux (WSL)
Visual Studio now provides native support for using C++ with 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. Check out our post on native support for WSL in Visual Studio to learn more and follow a step-by-step guide on getting started.

AddressSanitizer for the Linux Workload
In Visual Studio 2019 version 16.1 Preview 3 we have integrated AddressSanitizer (ASan) into Visual Studio for Linux projects. ASan is a runtime memory error detector for C/C++. You can enable ASan for MSBuild-based Linux projects and CMake projects that target a remote Linux machine or WSL. Check out our post on AddressSanitizer for the Linux Workload in Visual Studio for more information.

Separate build and debug targets for Linux projects
Update 1/27/2020: In Visual Studio 2019 version 16.5 and later you can leverage Visual Studio’s native support for WSL when separating your build system from your remote deploy system.
You can now separate your remote build machine from your remote debug machine for both MSBuild-based Linux projects and CMake projects that target a remote Linux machine. For example, you can now cross-compile on x64 and deploy to an ARM device when targeting IoT scenarios.
For a MSBuild-based Linux project, you can specify a new remote debug machine in the project’s Property Pages (Configuration Properties > Debugging > Remote Debug Machine). By default, this value is synchronized with your remote build machine (Configuration Properties > General > Remote Build Machine). 
The drop-down menu is populated with all established remote connections. To add a new remote connection, navigate to Tools > Options > Cross Platform > Connection Manager or search for “Connection Manager” in the search bar at the top of your screen. You can also specify a new remote deploy directory in the project’s Property Pages (Configuration Properties > General > Remote Deploy Directory).
By default, only the files necessary for the process to debug will be deployed to the remote debug machine. You can view/configure which source files will be deployed via the Solution Explorer. When you click on a source file, you will see a preview of its File Properties directly below the Solution Explorer. You can also right-click on a source file and select “Properties.”

The “Content” property specifies whether the file will be deployed to the remote debug machine. You can also disable deployment entirely by navigating to Property Pages > Configuration Manager and unchecking “Deploy” for the desired configuration.
If you want complete control over your project’s deployment (e.g. some files you want to deploy are outside of your solution or you want to customize your remote deploy directory per file/directory), then you can append the following code block(s) to your .vcxproj file:
<ItemGroup>
<RemoteDeploy Include="__example.cpp">
<!-- This is the source Linux machine, can be empty if DeploymentType is LocalRemote -->
<SourceMachine>$(RemoteTarget)</SourceMachine>
<TargetMachine>$(RemoteDebuggingTarget)</TargetMachine>
<SourcePath>~/example.cpp</SourcePath>
<TargetPath>~/example.cpp</TargetPath>
<!-- DeploymentType can be LocalRemote, in which case SourceMachine will be empty and SourcePath is a local file on Windows -->
<DeploymentType>RemoteRemote</DeploymentType>
<!-- Indicates whether the deployment contains executables -->
<Executable>true</Executable>
</RemoteDeploy>
</ItemGroup>
For CMake projects that target a remote Linux machine, you can specify a new remote debug machine via launch.vs.json. By default, the value of “remoteMachineName” will be synchronized with the “remoteMachineName” property in CMakeSettings.json, which corresponds to your remote build machine. These properties no longer need to match, and the value of “remoteMachineName” in launch.vs.json will dictate the remote machine used for deploy and debug.

IntelliSense will suggest all a list of all established remote connections, but you can add a new remote connection by navigating to Tools > Options > Cross Platform > Connection Manager or searching for “Connection Manager” in the search bar at the top of your screen.
If you want complete control over your deployment, you can append the following code block(s) to launch.vs.json:
"disableDeploy": false,
"deployDirectory": "~\foo",
"deploy" : [
{
"sourceMachine": "127.0.0.1 (username=example1, port=22, authentication=Password)",
"targetMachine": "192.0.0.1 (username=example2, port=22, authentication=Password)",
"sourcePath": "~/example.cpp",
"targetPath": "~/example.cpp",
"executable": "false"
}
]
Resolved issues
The best way to report a problem or suggest a feature to the C++ team is via Developer Community. The following feedback tickets related to C++ cross-platform development have been recently resolved in Visual Studio 2019 16.1 Preview 2 or Preview 3:
No configurations when using CppProperties.json
Unable to attach process of linux vm
cmake linux binary deployment fails with WSL
Infobar appears when open existing CMake cache fails
VS2017 crashes if SSH has connection error while building remote Linux CMake project
CTest timeout feature doesn’t work in test explorer
CMake: Any minor change to CMakeLists.txt triggers a full cache regeneration
CMake + Intellisense: Preprocessor definitions in CMakeLists do not work with quoted strings
Intellisense problem for Linux Makefile project
Talk to us!
Do you have feedback on our Linux tooling in Visual Studio? Pick a time to chat with the C++ cross-platform team and share your experiences – the good and the bad – to help us prioritize and build the right features for you! We can also be reached via the comments below, email (visualcpp@microsoft.com), and Twitter (@VisualC) and (@erikasweet_).
Regarding Separate build and debug targets for Linux projects I’m having some issues, I’m building my project using WSL and then I want to debug / deploy to a remote machine, the build works but I have one .json file in my project that I’ve set to be content when I deploy I see this:
>Connecting to remote systems.
>CacheCleanupConnections failed
>Resolving remote paths.
>Copying files.
>Deploy failed.
I can’t find the file on my remote machine, I have setup $(RemoteDeployDir) and $(RemoteProjectDir) , can anyone help me out please?
Thanks.
OK, I’ve fixed all of my issues apart from:
>CacheCleanupConnections failed
>Resolving remote paths.
…resolving remote path takes a couple of minutes, why is that?
The feature to debug the project on a different target than it was built on is great, but it needs to be better documented and polished, otherwise you end up needing the old project structure with the makefile to copy binaries. The first problem is in the ProjectProperties->Linker->General, there are two fields named Output File now. But with a lot of experimenting I could identify each properties: The first OutputField is the relative output Path (including name + extionsion) of the linked file. This path is also used for copying to the windows project folder. On the remote target this...
thank you for the detailed feedback, we will evaluate and get back to you
Is there a way to use mutiple core to parallel compile like we do on windows? Projects are quite big and it takes a long time.
Is this for a MSBuild based Linux project, or CMake? The answer is absolutely, I’ll assume MSBuild, in Property Pages, C/C++ – General – Max Parallel Compilation Jobs
Thanks for the article! Is it possible to build (cross-compile) a linux executable on Windows using Clang/LLVM and then copy the executable to a remote Linux machine for running and debugging?
I tried creating a few projects using VisualStudio2019 without success so far. When selecting a Linux target, it automatically tries to compile on the Linux target. When selecting a Windows target, it uses the Windows source headers (win32) even when I force it to use Clang/LLVM in a CMakeSettings.json. Perhaps there is a way to do this?
this is possible to do, and we plan on documenting this scenario in the near feature, right now it would be significant to explain for MSBuild based projects, you can do it today with no problem for CMake based projects, you can use a toolset file to define the compiler, you should create a project here that looks like a Windows project