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