dotnet build vs publish on Azure DevOps

user687554 picture user687554 · Sep 14, 2018 · Viewed 15.2k times · Source

I have a .NET Core 2.0 console app. I can successfully build or publish this app and run it locally. I can also successfully build and publish this app in Azure DevOps. However, if I build the app in Azure DevOps, I cannot run the result.

In Azure DevOps, I tried building using:

dotnet build -c Release -r win-x64 -o app

This generates a small number of files with just the project related files. It does not include all of the System.*.dll files, etc that seem excessive for most of my cases. This command works fine when I run it on my local machine and I can successfully click the MyApp.exe file and run my console app. However, if I run the same command on Azure DevOps, the MyApp.exe file that gets generated does not run as expected. Instead, it starts then immediately quits. Nothing is printed in the console app. I see no errors. The app is very basic, includes a "try-catch" around everything and has a Console.ReadLine at the end. So, I thought it would stay open.

When I run:

dotnet publish -c Release -r win-x64 -o app

I get the same files, but with all of the System.*.dll files, etc. included. This time, I've noticed that I can successfully run MyApp.exe and it behaves as expected.

Why does dotnet build ... work locally, but I don't seem to get the same behavior when I run dotnet build ... in Azure DevOps. It seems I'm forced to use dotnet publish. My issue is, the resulting .zip file goes from ~500kb to 30MB. This is big difference.

Answer

Shayan C picture Shayan C · May 2, 2019

An answer from the horse's mouth:

The dotnet build command builds the project and its dependencies into a set of binaries. The binaries include the project's code in Intermediate Language (IL) files with a .dll extension and symbol files used for debugging with a .pdb extension. A dependencies JSON file (*.deps.json) is produced that lists the dependencies of the application. A *.runtimeconfig.json file is produced, which specifies the shared runtime and its version for the application.

If the project has third-party dependencies, such as libraries from NuGet, they're resolved from the NuGet cache and aren't available with the project's built output. With that in mind, the product of dotnet build isn't ready to be transferred to another machine to run.

dotnet build - Builds a project and all of its dependencies.

dotnet publish - Packs the application and its dependencies into a folder for deployment to a hosting system. (PS - this also builds the application before packing)

The description is actually very good considering it's coming directly from Microsoft so I will not duplicate the words here.

As an exercise create a solution with multiple projects. For one of the projects add a reference to another project. Add some static files which your code references and a few NuGet packages. And run these commands at the solution root level and at the project level and observe the output in the bin folder.

Commands to run: dotnet build dotnet publish

dotnet clean to clean the bin folder

Also, run this at the root level and observe the output with the self-contained flag enabled:

dotnet publish -o ./output --runtime win10-x64 --self-contained

More info on self-contained builds