Making a tiny .NET Core 3.0 entirely self-contained single executable
I've always been fascinated by making apps as small as possible, especially in the .NET space. No need to ship any files - or methods - that you don't need, right? I've blogged about optimizations you can make in your Dockerfiles to make your .NET containerized apps small, as well as using the ILLInk.Tasks linker from Mono to "tree trim" your apps to be as small as they can be.
Work is on going, but with .NET Core 3.0 preview 6, ILLink.Tasks is no longer supported and instead the Tree Trimming feature is built into .NET Core directly.
Here is a .NET Core 3.0 Hello World app.
Now I'll open the csproj and add PublishTrimmed = true.
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.0</TargetFramework>
<PublishTrimmed>true</PublishTrimmed>
</PropertyGroup>
</Project>
And I will compile and publish it for Win-x64, my chosen target.
dotnet publish -r win-x64 -c release
Now it's just 64 files and 28 megs!
If your app uses reflection you can let the Tree Trimmer know by telling the project system about your Assembly, or even specific Types or Methods you don't want trimmed away.
<ItemGroup>
<TrimmerRootAssembly Include="System.IO.FileSystem" />
</ItemGroup>
The intent in the future is to have .NET be able to create a single small executable that includes everything you need. In my case I'd get "supersmallapp.exe" with no dependencies. That's done using PublishSingleFile along with the RuntimeIdentifier in the csproj like this:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.0</TargetFramework>
<PublishTrimmed>true</PublishTrimmed>
<PublishReadyToRun>true</PublishReadyToRun>
<PublishSingleFile>true</PublishSingleFile>
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
</PropertyGroup>
</Project>
At this point you've got everything expressed in the project file and a simple "dotnet publish -c Release" makes you a single exe!
There's also a cool global utility called Warp that makes things even smaller. This utility, combined with the .NET Core 3.0 SDK's now-built-in Tree Trimmer creates a 13 meg single executable that includes everything it needs to run.
C:\Users\scott\Desktop\SuperSmallApp>dotnet warp
Running Publish...
Running Pack...
Saved binary to "SuperSmallApp.exe"
And the result is just a 13 meg single EXE ready to go on Windows.
If you want, you can combine this "PublishedTrimmed" object with "PublishReadyToRun" as well and get a small AND fast app.
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.0</TargetFramework>
<PublishTrimmed>true</PublishTrimmed>
<PublishReadyToRun>true</PublishReadyToRun>
</PropertyGroup>
</Project>
These are not just IL (Intermediate Language) assemblies that are JITted (Just in time compiled) on the target machine. These are more "pre-chewed" AOT (Ahead of Time) compiled assemblies with as much native code as possible to speed up your app's startup time. From the blog post:
In terms of compatibility, ReadyToRun images are similar to IL assemblies, with some key differences.
- IL assemblies contain just IL code. They can run on any runtime that supports the given target framework for that assembly. For example a
netstandard2.0
assembly can run on .NET Framework 4.6+ and .NET Core 2.0+, on any supported operating system (Windows, macOS, Linux) and architecture (Intel, ARM, 32-bit, 64-bit). - R2R assemblies contain IL and native code. They are compiled for a specific minimum .NET Core runtime version and runtime environment (RID). For example, a
netstandard2.0
assembly might be R2R compiled for .NET Core 3.0 and Linux x64. It will only be usable in that or a compatible configuration (like .NET Core 3.1 or .NET Core 5.0, on Linux x64), because it contains native code that is only usable in that runtime environment.
I'll keep exploring .NET Core 3.0, and you can install the SDK here in minutes. It won't mess up any of your existing stuff.
Sponsor: Suffering from a lack of clarity around software bugs? Give your customers the experience they deserve and expect with error monitoring from Raygun.com. Installs in minutes, try it today!
About Scott
Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.
About Newsletter
I don't think there is any mention of a parameter called --self-contained in the this post; or in the comment section, for that matter.
However :) The term self-contained is used to express what the goal is.
I remember when Netscape Navigator hit 6MB on my dial up 14.4k modem and though it was the most evil thing would leave on overnight to download.
Nice blog post :-)
Is there a way(or will there be in the future) to create a "self-contained single executable" for a asp.net core or Blazor (ASP.NET Core hosted) app ?
Still no answers about the HUGE security problems you have when distribute .net core apps.
PublishReadyToRun>true</PublishReadyToRun>
and published with
dotnet publish -r win-x64 -c release
but the size is pretty 100% identical. Moreover, there is no performance improvements at all. In your example it shows
<OutputType>Exe</OutputType>
but shouldn't it be
<OutputType>WinExe</OutputType>
as it is for WPF? What kind of application did you use? Winforms? WPF? Console only? I also couldn't find any documentation about this, whether it supports WPF or just winforms or just console only or whether it has been tested with WPF at all, seems like not.
Using .NET Core 3 Preview 7.
Edward, can you elaborate on the security problems you're referring to?
Currently, the ASP.NET Core Hosting Module is only offered via the hosting bundle that includes both x32 and x64 versions of the respective run time, which from a software distribution standpoint kills the benefit of the self-contained and/or trimmed builds.
Don't get me wrong, this is all well and good for command line/desktop applications but still leaves the ASP.NET Core side of the fence out to dry because of how MS offers .NET Core downloads.
Comments are closed.