This post was co-authored by David Carmona, a Principal Program Manager Lead in .NET Team and Joe Morris, a Senior Program Manager in .NET Team.
Couple of weeks back, we dedicated a blog post introducing .NET Standard 2.0, which will significantly extend your ability to share code by unifying .NET APIs across all application types and platforms.
Today, we are going to focus on how we are unifying the project system and the build infrastructure with MSBuild. These changes were announced back in May and will be available aligned with the next version of Visual Studio (Visual Studio “15”). These tools will provide you with a development experience in Visual Studio, Visual Studio Code and the command line.
For the impatient: TL;DR
We released .NET Core 1.0 back in June. This included the RTM runtime and a preview of tools components. The final release of .NET Core tools will provide a build and project system that are unified with the rest of .NET project types, moving away from the project.json infrastructure that was specific to .NET Core. While this means we need to move away from the straightforward JSON format for project files and embrace the XML format used in MSBuild, this change will bring significant benefits in the overall experience. We are not claiming that XML is better than JSON but we think the compatibility of all .NET projects is better.
.NET Core application and .NET Standard library projects will just be another kind of .NET project you can use in conjunction with other project types, such as Xamarin, WPF, Unity or UWP.
At the same time, we’ve also preserved key project.json characteristics that many of you have told us you value and we will bring more over time, further simplifying the project representation in MSBuild. We are also planning to bring those benefits to all the .csproj projects in the future, not only .NET Core or .NET Standard. And because we will support full migration of existing project.json files, you can continue to work with them safely.
Here are the key improved experiences you will see in this unified Build system:
- Project references work: You can reference .NET Core and .NET Standard library projects from existing .NET projects (WPF, ASP.NET, Xamarin, Unity etc.) and the opposite direction also, as explained in the .NET Standard post.
- Package references are integrated: NuGet package references are now part of the csproj format, not a special file using its own format.
- Cross-targeting support: You can cross-target multiple target frameworks in one project.
- Simplified csproj format: The csproj format has been made as minimal as possible to make it easier to edit by hand. Hand-editing is optional, common gestures in Visual Studio will take care of updating the file and we will also provide command line options in the CLI for the most common actions.
- Support for file wildcards: No requirement to list individual files in the project file. This enables folder-based projects that don’t require every file to be added manually and dramatically improve team collaboration, as the project file doesn’t need to be modified every time a new file is added.
- Migration of project.json/xproj to csproj : You can seamlessly migrate your existing .NET Core projects from project.json to csproj without any loss at any time, in Visual Studio or at the command line.
Why do we need a standard Build System?
We’ve been talking recently about .NET Standard 2.0. It will give you access to many more APIs and can be used to share code across all the apps you are working on. That sounds great! It turns out that a key enabler of this outcome is a standard build system. In absence of that, the .NET Standard 2.0 vision is not fully realized. .NET Standard requires a standard API and standard project types to act as currencies within a standard build system. With those in place, you can flow code to all the places you want, enabling all the potential combination of project to project and NuGet references.
.NET Core is the only one that isn’t using MSBuild today, so it’s the only one that has to change. This includes .NET Standard Library projects. With all project types using the same build system and project formats, it’s easy and intuitive to re-use libraries across different project types.
The New Tools Experience at the Command line
The updated tools experience will have similar ease-of-use as the existing project.json system, with a better experience if you want to switch back and forth with Visual Studio. The following walkthrough is intended to demonstrate that. Today’s post focusses on the command line experience. We will publish another post at a later date that walks through the same experiences in Visual Studio “15”.
Note: We will show today manual editing of csproj files. We also plan to add
dotnet commands that will update csproj and sln files for common tasks, such as adding a NuGet package when working outside of Visual Studio.
dotnet new is the command to use to create new templates with the .NET Core command line tools. It will generate a csproj project and
Program.cs files. The csproj file will be given the same name as the directory by default. You can see the new experience in the image below.
The csproj file format has been significantly simplified to make it more friendly for the command line experience. If you are familiar with project.json, you can see that it contains very similar information. It also supports a wildcard syntax, to avoid the need of listing individual source files.
This is the default csproj that
dotnet new creates. It provides you with access to all of the assemblies that are part of the .NET Core runtime install, such as System.Collections. It also provides access to all of the tools and targets that comes with the .NET Core SDK.
As you can see, the resulting project file definition is in fact quite simple, avoiding the use of complex values such as GUIDs. A detailed mapping of project.json to .csproj elements is listed here.
Because the improved .csproj file supports wildcards, you don’t require the full listing of code files in the project file. This enables a great tooling experience: Files added to the folder will automatically show up in the Solution Explorer. Changes made in files will automatically modify the project file if needed.
NuGet Package references
You can add NuGet package references within the csproj format, instead of needing to specify them in a separate file with a special format. NuGet package references take the following form:
<PackageReference Include="[Package-Name]" Version="[Package-Version]" />.
For example, if you want to add a reference in the project above to WindowsAzure.Storage you just need to add the following line to the other two package references:
In most cases, you will target a single .NET Core, .NET Framework or .NET Standard target with your library. Sometimes you need more flexibility and have to produce multiple assets. MSBuild now supports cross-targeting as a key scenario. You can see the syntax below to specify the set of targets that you want to build for, as a semicolon-separated list.
This will also automatically set the right #defines that you can use in your code to enable or disable specific blocks of code depending on the target frameworks.
You will be able to migrate existing project.json projects to csproj very easily using the new command
dotnet migrate. The following project.json generates the exact same csproj file showed before after applying
.NET CLI commands
There are a set of useful commands exposed by the .NET CLI tools.
dotnet publish and
dotnet pack are good examples. These commands will continue to be included with the .NET CLI and do largely the same thing as before, with the exception that they will be implemented on top of MSBuild, as appropriate.
The only difference is that the .NET CLI will provide a much thinner layer, as it will rely on MSBuild for most of the work. The primary role for the .NET CLI is to provide a user-friendly experience for executing MSBuild commands and also as a single tool host for commands that do not use MSBuild, such as
We are in the process of building the new tools and related experiences that you’ve seen in this post. We’re excited to ship a preview update to you later this year and the final version aligned with Visual Studio “15”.
In the meanwhile you can safely continue to use the existing project.json format which will carry forward as shown before.
We’d love to hear your feedback on this work. We think this is a big step forward for a unified .NET platform that will make your life easier by bringing your new and existing code to any application type and platform.
And because we develop in the open, you are welcome to join the GitHub repos where this work is taking place:
- https://github.com/dotnet/cli – CLI changes to support csproj/MSBuild.
- https://github.com/dotnet/roslyn-project-system – Visual Studio IDE changes to support new project system for .NET Core.
- https://github.com/dotnet/sdk – Core functionality needed to create .NET Core projects that is shared between Visual Studio and CLI.