Dotnet Warp to further optimize .Net self-contained single executable file.
Tags: dotnet, singleexe, optimization, warp
Published: 2020-07-02 18:13:27

.NET core 3.0 and later versions enable us to deploy executables as self-contained. This means we can copy the publish folder to any machine and can run it even that machine doesn't have .NET core runtime installed. 

Please check [Microsoft article] (https://docs.microsoft.com/en-us/dotnet/core/deploying/#:~:text=Publishing%20your%20app%20as%20self,NET%20Core%20runtime%20installed.&text=runtime%2Ddependent%20executable%20for%20the%20current%20platform) for more details.

The self-contained deployment significantly increases the overall size of the publish folder because it carries the whole .NET core runtime along with it. Second thing you will notice with self-contained deployment is the sheer number of files you will have in your publish folder.

Fortunately, .NET tools team provides 2 File Publish Options that let you produce much trimmed and single file version of your application.

The options are  
- Produce single file
- Trim unused files

To keep this a article to the scope, I won't be delving much into .NET Core deployment models. You can check my blog, [Dotnet Core 3.0 deployment models] (https://blogs.dhrutara.com/blogs/dotnet-core-deployment-models/), if you want to learn more about .NET core deployment models.

[Warp](https://github.com/dgiagio/warp) lets you produce a trimmed version of your self-contained single executable file. Warp is written in Rust and is supported on Linux, Windows and macOS.

##Dotnet-warp

To make it further easier for .NET developers, Hubert Rybak created a wrapper around wrap called [dotnet-warp] (https://github.com/Hubert-Rybak/dotnet-warp/graphs/contributors).

I have tested **dotnet-warp** on few of my internal projects and it definitely produces trimmer executable than the built-in one.

In the below image you can see that the executable produced by dotnet-warp is 5MB lighter than built-in produced executable. 

> In this case it might not be much of a gain, but I have noticed that as the dependencies grow the difference tend to increase. 

![dotnet-warp vs .Net core built-in] (https://dev-to-uploads.s3.amazonaws.com/i/am190cj2mkk7qkwtl1ch.jpg)

dotnet-warp is a dotnet tool so, we can install and use dotnet-warp as any other dotnet tools.

####To install dotnet-warp run below command
```
dotnet tool install --global dotnet-warp --version 1.1.0
```
Above command installs the tool globally. Globally doesn’t mean at machine level instead it is at user level. Once installed globally the tool can be executed by that specific user without giving the whole exe path. 

> To install it locally remove the flag –global

####Lets a take a simple application to 

- Let’s call it Dhrutara.DotnetWarp.
- I am using Visual Studio 2019
- Runtime is dotnet core 3.1
- Added NewtonSoft.Json as dependency but I am not going to use it.

**Newtonsoft.Json will be removed by warp-it because it is not used. **

####Use dotnet-warp
The only required argument for dotnet-warp is the project file. This could be either relative or absolute. Other arguments are optional.

So, let's begin with the only required argument.

- Open either windows PowerShell or command prompt.
- Navigate to the project folder. 
- Run below command.

```
dotnet-warp ".\Dhrutara.DotnetWarp.csproj"
```

![Screen shot of the project folder. dotnet-warp with only the required argument and --output argument](https://dev-to-uploads.s3.amazonaws.com/i/7m1gf3p68xobdr2vvi0j.jpg)

In this case the executable is created in the same folder where the project file resides. That is because dotnet-warp creates the executable in the same location where the command is ran from.

If you want to deploy it to a different location, then you can pass the target folder using “--output” option.

```
dotnet-warp ".\Dhrutara.DotnetWarp.csproj" --output ".\publish\Dhrutara.DotnetWarp.exe"
```
![Screen shot of the project folder with dotnet-warp with required argument and --output argument](https://dev-to-uploads.s3.amazonaws.com/i/4q4ddz1hpbqphii5pixt.jpg)

> With --output option it is mandatory to mention the executable file full name, including extension. 

dotnet-warp internally uses the default dotnet core compiler and hence it also allows us to pass additional arguments to the compiler. The format to pass compiler options is

```
-p:<argument name>=<argument value>
```

By default, dotnet-warp compiles in release mode. let us assume we want to compile Dhrutara.DotnetWarp in debug mode and also want to mention the version of the executable as 1.2.1. Below command can be used to achieve this.

```
dotnet-warp ".\Dhrutara.DotnetWarp.csproj" --output ".\publish\Dhrutara.DotnetWarp.exe" -p:configuration="debug" -p:Version="1.2.1"
```

> Since dotnet-warp is a dotnet tool we can use it in our azure CI/CD pipelines. Please check my blog [warp-it](https://blogs.dhrutara.com/blogs/warp-it/, "") to know how I used it in my projects.

##Conclusion
At the time of writing this article dotnet-warp produces lighter version of .NET core 3.0+ single executable files. .NET core team is working hard, and I hope very soon the built-in tool can do better job than dotnet-warp.