Relationship between the dotnet cli and the new vs2017 msbuild

kimsagro picture kimsagro · Apr 15, 2017 · Viewed 15.3k times · Source

With the move from project.json to the new csproj format introduced with VS2017, I'm struggling to understand the difference between the dotnet cli and the new msbuild and when to use one over the other.

1) To build a new csproj netstandard library from the command line, should I be calling the dotnet cli (for example dotnet restore dotnet build) or use msbuild (for example msbuild ExampleNetstandard.sln).

2) Also, my understanding is that there are two versions of msbuild, one built on the full framework and another targeting dotnet core. Is this correct? Should I always use the dotnet version

3) Is dotnet cli standalone or does it require msbuild to be installed?. For instance when you install the dotnet SDK does this install msbuild as well? If so is this different to the version that is installed with vs2017?

Answer

Julian picture Julian · Apr 17, 2017

Questions

1) To build a new csproj netstandard library from the command line, should I be calling the dotnet cli (for example dotnet restore dotnet build) or use msbuild (for example msbuild ExampleNetstandard.sln).

Both do fine as currently dotnet is built on top of msbuild. So it's a matter of taste. You could also call msbuild tasks by using the dotnet CLI. (dotnet msbuild <msbuild_arguments>)

In the beginning, all the .NET core stuff was only in dotnet and not in msbuild. This was cumbersome as a lot of stuff that was already built on msbuild wasn't working well with dotnet out of the box (e.g. Xamarin). So they moved the stuff to msbuild and build dotnet on top of msbuild.

dotnet has some features that aren't in msbuild, like dotnet new. In my opinion, dotnet is easier to use than msbuild, so I prefer dotnet.

To make it more clear, I have added a comparison between msbuild and dotnet at the end of my post.

2) Also, my understanding is that there are two versions of msbuild, one built on the full framework and another targeting dotnet core. Is this correct? Should I always use the dotnet version

There is only one msbuild. dotnet CLI is using msbuild:

Since CLI uses MSBuild as its build engine, we recommend that these parts of the tool be written as custom MSBuild targets and tasks, since they can then take part in the overall build process

https://docs.microsoft.com/en-us/dotnet/articles/core/tools/extensibility

The older version of msbuild was lacking the .NET Core support. Maybe that's the other version ;)

I agree it's confusing, as it was very different a few months ago.

3) Is dotnet cli standalone or does it require msbuild to be installed?. For instance when you install the dotnet SDK does this install msbuild as well? If so is this different to the version that is installed with vs2017?

I wasn't sure about this, but it was easy to test. I have removed all msbuild.exe and it still worked. Found out it's using the msbuild.dll in the SDK folder. e.g. "C:\Program Files\dotnet\sdk\1.0.3\MSBuild.dll"

If you remove that one, there is a proof:

When msbuild.dll removed

msbuild.dll is actually msbuild.exe, as you can see in the properties:

msbuild.dll properties of SDK 1.0.3

Some code

If you look into the code of the dotnet CLI, you can see it's generating msbuild commands.

For example dotnet restore, is created by the RestoreCommand class inside dotnet CLI.

A stripped version:

public class RestoreCommand : MSBuildForwardingApp
{
    ...
    public static RestoreCommand FromArgs(string[] args, string msbuildPath = null)
    {
        var result = parser.ParseFrom("dotnet restore", args);
        ...
        var msbuildArgs = new List<string>
        {
            "/NoLogo",
            "/t:Restore",
            "/ConsoleLoggerParameters:Verbosity=Minimal"
        };
        ...
        return new RestoreCommand(msbuildArgs, msbuildPath);
    }

    public static int Run(string[] args)
    {
        RestoreCommand cmd;
        try
        {
            cmd = FromArgs(args);
        }
        catch (CommandCreationException e)
        {
            return e.ExitCode;
        }

        return cmd.Execute();
    }
    ...
}

You can see dotnet restore is just calling msbuild /NoLogo /t:Restore /ConsoleLoggerParameters:Verbosity=Minimal


If you check RestoreCommand in the time of dotnet v1.0.0 RC2, it wasn't using msbuild but was calling nuget directly.

return NuGet3.Restore(args, quiet);

Mapping between dotnet and msbuild

I made a mapping between dotnet and msbuild. It's not complete, but the important commands are there.

Dotnet                 | Msbuild                                    | Remarks                         
-----------------------|--------------------------------------------|---------------------------------
Add                    |                                            |         
-----------------------|--------------------------------------------|---------------------------------                        
Build                  | /t:Build                                   |  
-----------------------|--------------------------------------------|---------------------------------                                
Build --no-incremental | /t:Rebuild                                 |    
-----------------------|--------------------------------------------|---------------------------------                              
Clean                  | /t:clean                                   |                                 
-----------------------|--------------------------------------------|--------------------------------- 
Complete               |                                            |                                 
-----------------------|--------------------------------------------|--------------------------------- 
Help                   |                                            | Help!                           
-----------------------|--------------------------------------------|--------------------------------- 
List                   |                                            |                                 
-----------------------|--------------------------------------------|--------------------------------- 
Migrate                | -                                          |                                 
-----------------------|--------------------------------------------|--------------------------------- 
Msbuild                |                                            | Forwarding all                  
-----------------------|--------------------------------------------|--------------------------------- 
New                    |                                            |                                 
-----------------------|--------------------------------------------|--------------------------------- 
Nuget                  |                                            |  *
-----------------------|--------------------------------------------|--------------------------------- 
Pack                   | /t:pack                                    |                                 
-----------------------|--------------------------------------------|--------------------------------- 
Publish                | /t:publish                                 |                                 
-----------------------|--------------------------------------------|--------------------------------- 
Remove                 |                                            |                                 
-----------------------|--------------------------------------------|--------------------------------- 
Restore                | /NoLogo /t:Restore                         |
                         /ConsoleLoggerParameters:Verbosity=Minimal |
-----------------------|--------------------------------------------|--------------------------------- 
Run                    | /nologo /verbosity:quiet                   |
                         /p:Configuration=   /p:TargetFramework     |                                 
-----------------------|--------------------------------------------|--------------------------------- 
Sln                    |                                            | Not in msbuild                  
-----------------------|--------------------------------------------|--------------------------------- 
Store                  | /t:ComposeStore                            |                                 
-----------------------|--------------------------------------------|--------------------------------- 
Test                   | /t:VSTest /v:quiet /nologo                 |                                 
-----------------------|--------------------------------------------|--------------------------------- 
Vstest                 |                                            | Forwarding to vstest.console.dll

* dotnet nuget: Adding/removing packages to csproj, also limited set of nuget.exe, see comparison

PS no markdown tables in SO :(