Abstract: We practically show examples of 15 different .NET8/9 build modes, including Framework-Dependent and Framework-Independent, how to bundle an app into a single-file, how to trim app bundles from unused libraries, and how to build an Ahead-of-time (AOT) precompiled app.

1. .NET8/9 toolset supports different build/publish/deployment modes

I was experimenting with different project properties/flags, and I developed several proof-of-concept build projects showcasing different build/publish/deployment modes available in .NET8/9, using Microsoft tools.

1.2. Articles in this series

For technical reasons, I will organize this text into several articles.

2. Analyzing Build Results

I will use dotPeek by JetBrains ([5]), a powerful Decompiler, to have a look into some of the more interesting build types. That product is free. I do not know how they make money from it, but it is free.

3. Build 2- Framework-dependent, Single File

  1. NOTE: All these build results are with the .NET framework version around .NET 8.0.0. With the change in the .NET version, file sizes changed (typically smaller). But build types are still the same. It looks like they improved/changed their build tools.
  2. Location: c:\tmpNetBundle\BundleExample01\ConsoleApp1\Framework_SingleFile_Win-X64\
  3. Publish mode: 1)Release; 2)framework-dependent; 3)Platform-specific-win-x64; 4)Single-file; 5)Untrimmed; 6)NotR2R; 7)PdbEmbeded; 8)binariesNotInSingleFile; 9)assembliesNotCompressed; 10)NotAot
  4. Build result Content: -4 files, -13.6MB
    Content

Here are some screenshots from the detPeek decompiler and from the file system.

detpeek

.NET

Microsoft

Comments

4. Build 13- Framework-independent (Self-Contained), Single File, Untrimmed

  1. NOTE: All these build results are with the .NET framework version around .NET 8.0.0. With the change in the .NET version, file sizes changed (typically smaller). But build types are still the same. It looks like they improved/changed their build tools.
  2. Location: c:\tmpNetBundle\BundleExample01\ConsoleApp2C\SelfContained_SingleFile_win-x64\
  3. Publish mode: 1)Release; 2)self-contained; 3)Platform-specific-win-x64; 4)Single-file; 5)Untrimmed; 6)NotR2R; 7)PdbEmbeded; 8)binariesInSingleFile; 9)assembliesCompressed; 10)NotAot
  4. Build result Content: -1 file; -76 MB.
    Bulid result

Here are some screenshots from the detPeek decompiler. It seems that the decompiler automatically decompresses files. I assume that the assembliesCompressed flag worked.

ConsoleApp

Assembly

EF files

Comments

5. Build 14- Framework-independent (Self-Contained), Single File, Trimmed

  1. NOTE: All these build results are with the .NET framework version around .NET 8.0.0. With the change in the .NET version, file sizes changed (typically smaller). But build types are still the same. It looks like they improved/changed their build tools.
  2. Location: c:\tmpNetBundle\BundleExample01\ConsoleApp2C\SelfContained_SingleFile_win-x64_Trimmed\
  3. Publish mode: 1)Release; 2)self-contained; 3)Platform-specific-win-x64; 4)Single-file; 5)Trimmed; 6)NotR2R; 7)PdbEmbeded; 8)binariesInSingleFile; 9)assembliesCompressed ; 10)NotAot
  4. Build result Content: -1 file; -20.4MB.
    NetBundle

Here are some screenshots from the detPeek decompiler. It seems that the decompiler automatically decompresses files.

Embedded files

.Net Assembly

Metadata

Comments

6. Build 17- Framework-independent (Self-Contained), Single File, Trimmed, ReadyToRun

  1. Note. All these build results are with the .NET framework version around .NET 8.0.0. With the change in the .NET version, file sizes changed (typically smaller). But build types are still the same. It looks like they improved/changed their build tools.
  2. Location: c:\tmpNetBundle\BundleExample01\ConsoleApp3C\SelfContained_SingleFile_win-x64_Trimmed_ReadyToRun\
  3. Publish mode: 1)Release; 2)self-contained; 3)Platform-specific-win-x64; 4)Single-file; 5)Trimmed; 6)ReadyToRun; 7)PdbEmbeded; 8)binariesInSingleFile; 9)assembliesCompressed ; 10)NotAot
  4. Build result Content: -1 file; -22MB.
    .Net

Here are some screenshots from the detPeek decompiler. It seems that the decompiler automatically decompresses files.

Modules

DOS Header

Properties

Comments

7. Build 19- Native Ahead-Of-Time Compilation

  1. NOTE: All these build results are with the .NET framework version around .NET 8.0.0. With the change in the .NET version, file sizes changed (typically smaller). But build types are still the same. It looks like they improved/changed their build tools.
  2. Location: c:\tmpNetBundle\BundleExample01\ConsoleApp5\win-x64_Trimmed_AOT\
  3. Publish mode: 1)Release; 2)self-contained; 3)Platform-specific-win-x64; 4)Un-bundled; 5)Trimmed; 6)NotR2R; 7)PdbEmbeded; 8)binariesNotInSingleFile; 9)assembliesNotCompressed; 10)PublishAot
  4. Build result Content: -10 file; -19.5MB.
    Trimmed

Here are some screenshots from the detPeek decompiler and from the file system.

File system

Comments

8. Milestone – That was the .NET 8.0.0 framework so far

In this series of articles so far, we showed 15 different ways to build a .NET8 application, depending on the options wanted. There are probably more options or combinations of build properties/flags, but we can call this proof-of-concept testing successful and broad enough. According to the documentation, most of the build/publish options are working properly.

I was in this article aiming for some “intermediate level of practical skills” that a modern C#/.NET developer should have. Of course, this is a very interesting topic for every software engineer to get familiar with.

One very interesting technology offered as a part of .NET8 environment it ReadyToRun build option, which is a form of ahead-of-time (AOT) compilation. More details can be found at [7]. Looks to me like a serious topic, but I do not see the point of really studying it in detail unless you work in Microsoft in their .NET runtime/core department. An average C#/.NET engineer just needs to know how to activate properly the build options and benefits of it.

We also showed how to do a native Ahead-Of-Time compilation deployment model. That can be attractive in some cases, too.

9. To be continued

This will be continued in the next article of the series.

10. References

[1] .NET application publishing overview

https://learn.microsoft.com/en-us/dotnet/core/deploying/

[2] Self-contained deployment runtime roll forward

https://learn.microsoft.com/en-us/dotnet/core/deploying/runtime-patch-selection

[3] https://www.red-gate.com/products/smartassembly/

[4] https://learn.microsoft.com/en-us/dotnet/core/deploying/single-file/overview?tabs=cli#api-incompatibility

[5] https://www.jetbrains.com/decompiler/

[7] https://devblogs.microsoft.com/dotnet/conversation-about-ready-to-run/