68 megabytes for Hello World (and how to reduce that a bit)

When I first started playing around with .NET Core, I was perplexed when the default output was a .dll that you needed to run with the dotnet command line too.

To cut a long story short you can make .NET Core build as an exe by creating a publish profile via the GUI or with the following contents.

I guess building as a .dll by default makes sense when your primary target is Azure.

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup>
    <PublishProtocol>FileSystem</PublishProtocol>
    <Configuration>Release</Configuration>
    <Platform>Any CPU</Platform>
    <TargetFramework>netcoreapp2.1</TargetFramework>
    <PublishDir>bin\</PublishDir>
    <RuntimeIdentifier>win-x64</RuntimeIdentifier>
    <SelfContained>true</SelfContained>
    <_IsPortable>false</_IsPortable>
  </PropertyGroup>
</Project>

It looks like truly self-contained apps will never happen: https://github.com/dotnet/corefx/issues/13329#issuecomment-322494078

Package trimming, or 21.65MB for Hello World

PM> install-package Microsoft.Packaging.Tools.Trimming
install-package : Unable to find package 'Microsoft.Packaging.Tools.Trimming'
At line:1 char:1
+ install-package Microsoft.Packaging.Tools.Trimming
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [Install-Package], Exception
    + FullyQualifiedErrorId : NuGetCmdletUnhandledException,NuGet.PackageManagement.PowerShellCmdlets.InstallPackageCommand
 
Time Elapsed: 00:00:01.6966641

 

but… but… that’s what the official documentation says to do!

Turns out Adam from the past also had this issue. Thanks, Adam from the past! No idea why this has been removed from the docs.

Time Elapsed: 00:00:01.6966641
PM> install-package -pre Microsoft.Packaging.Tools.Trimming
  CACHE https://api.nuget.org/v3/registration3-gz-semver2/microsoft.packaging.tools.trimming/index.json
Restoring packages for c:\git\HelloWorldSingleFile\HelloWorldSingleFile\HelloWorldSingleFile.csproj...
  GET https://api.nuget.org/v3-flatcontainer/microsoft.packaging.tools.trimming/index.json
  OK https://api.nuget.org/v3-flatcontainer/microsoft.packaging.tools.trimming/index.json 890ms
  GET https://api.nuget.org/v3-flatcontainer/microsoft.packaging.tools.trimming/1.1.0-preview1-26619-01/microsoft.packaging.tools.trimming.1.1.0-preview1-26619-01.nupkg
  OK https://api.nuget.org/v3-flatcontainer/microsoft.packaging.tools.trimming/1.1.0-preview1-26619-01/microsoft.packaging.tools.trimming.1.1.0-preview1-26619-01.nupkg 819ms
Installing Microsoft.Packaging.Tools.Trimming 1.1.0-preview1-26619-01.
Installing NuGet package Microsoft.Packaging.Tools.Trimming 1.1.0-preview1-26619-01.

Also change your project file

<PropertyGroup>
  <TrimUnusedDependencies>true</TrimUnusedDependencies>
</PropertyGroup>

The next time you publish, you’ll see the following output

2>Trimmed 197 out of 214 files for a saving of 44.64 MB
2>Final app size is 21.65 MB

I understand why System.Text.Encoding.Extensions is shipped, but I don’t understand why System.Threading and Tasks are needed for Hello World.

.NET Core AOT / CoreRT or: you didn’t really need Reflection, did you? (Hello World in under 8 megabytes)

All snark aside, CoreRT is really, really impressive. Have a read of https://github.com/dotnet/corert/blob/master/Documentation/intro-to-corert.md or for more detail, http://mattwarren.org/2018/06/07/CoreRT-.NET-Runtime-for-AOT/

You’ll need Visual Studio 2017 with MSVC enabled, plus CMake, it seems, then clone https://github.com/dotnet/corert and run build.cmd

Some time later, you’ll be able to follow the instructions at https://github.com/dotnet/corert/blob/master/Documentation/how-to-build-and-run-ilcompiler-in-console-shell-prompt.md

PS c:\git\HelloWorldSingleFile> $env:IlcPath="c:\git\corert\bin\Windows_NT.x64.Debug"
PS c:\git\HelloWorldSingleFile> dotnet publish -r win-x64
...
 Generating native code
 HelloWorldSingleFile -> c:\git\HelloWorldSingleFile\HelloWorldSingleFile\bin\Debug\netcoreapp2.1\win-x64\publish\

If you don’t see the “Generating native code” line, you may need to delete your bin\ and obj\ folders. No, dotnet clean didn’t help here.

If you’ve got this far, you should have a ~7.6 MB exe that is independent of the .NET framework. Success!

The code for this article is at https://github.com/voltagex/HelloWorldSingleFile

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s