I've been using ILMerge and various hacks to merge/squish executables together for well over 12 years. The .NET community has long toyed with the idea of a single self-contained EXE that would "just work." No need to copy a folder, no need to install anything. Just a single EXE.

While work and thought continues on a CoreCLR Single File EXE solution, there's a nice Rust tool called Warp that creates self-contained single executables. Warp is cross-platform, works on any tech, and is very clever

The Warp Packer app has a slightly complex command line, like this:

.\warp-packer --arch windows-x64 --input_dir bin/Release/netcoreapp2.1/win10-x64/publish --exec myapp.exe --output myapp.exe

Fortunately Hubert Rybak has created a very nice "dotnet-warp" global tool that wraps this all up into a single command, dotnet-warp.

All you have to do is this:

C:\supertestweb> dotnet tool install -g dotnet-warp

C:\supertestweb> dotnet-warp

O Running Publish...

O Running Pack...

In this example, I just took a Razor web app with "dotnet new razor" and then packed it up with this tool using Warp packer. Now I've got a 40 meg self-contained app. I don't need to install anything, it just works.

C:\supertestweb> dir

Directory: C:\supertestweb



Mode LastWriteTime Length Name

---- ------------- ------ ----

d----- 2/6/2019 9:14 AM bin

d----- 2/6/2019 9:14 AM obj

d----- 2/6/2019 9:13 AM Pages

d----- 2/6/2019 9:13 AM Properties

d----- 2/6/2019 9:13 AM wwwroot

-a---- 2/6/2019 9:13 AM 146 appsettings.Development.json

-a---- 2/6/2019 9:13 AM 157 appsettings.json

-a---- 2/6/2019 9:13 AM 767 Program.cs

-a---- 2/6/2019 9:13 AM 2115 Startup.cs

-a---- 2/6/2019 9:13 AM 294 supertestweb.csproj

-a---- 2/6/2019 9:15 AM 40982879 supertestweb.exe

Now here's what it gets interesting. Let's say I have a console app. Hello World, packed with Warp, ends up being about 35 megs. But if I use the "dotnet-warp -l aggressive" the tool will add the Mono ILLinker (tree shaker/trimmer) and shake off all the methods that aren't needed. The resulting single executable? Just 9 megs compressed (20 uncompressed).

C:\squishedapp> dotnet-warp -l aggressive

O Running AddLinkerPackage...

O Running Publish...

O Running Pack...

O Running RemoveLinkerPackage...

C:\squishedapp> dir

Mode LastWriteTime Length Name

---- ------------- ------ ----

d----- 2/6/2019 9:32 AM bin

d----- 2/6/2019 9:32 AM obj

-a---- 2/6/2019 9:31 AM 47 global.json

-a---- 2/6/2019 9:31 AM 193 Program.cs

-a---- 2/6/2019 9:32 AM 178 squishedapp.csproj

-a---- 2/6/2019 9:32 AM 9116643 squishedapp.exe

Here is where you come in!

NOTE: The .NET team has planned to have a "single EXE" supported packing solution built into .NET 3.0. There's a lot of ways to do this. Do you zip it all up with a header/unzipper? Well, that would hit the disk a lot and be messy. Do you "unzip" into memory? Do you merge into a single assembly? Or do you try to AoT (Ahead of Time) compile and do as much work as possible before you merge things? Is a small size more important than speed?

What do you think? How should a built-in feature like this work and what would YOU focus on?

Sponsor: Check out Seq 5 for real-time diagnostics from ASP.NET Core and Serilog, now with faster queries, support for Docker on Linux, and beautiful new dark and light themes.