.NET8/9 – Testing Different Build/Deployment Modes – Part 3

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.

  • .NET8/9 – Testing different Build/Deployment modes – Part1
  • .NET8/9 – Testing different Build/Deployment modes – Part2
  • .NET8/9 – Testing different Build/Deployment modes – Part3
  • .NET8/9 – Testing different Build/Deployment modes – Part4
  • .NET8/9 – Testing different Build/Deployment modes – Part5
  • .NET8/9 – Testing different Build/Deployment modes – Part6

2. Build Results

Here is a list of build results. Most of my builds succeeded.

NOTE: These project settings all worked well somewhere around .NET 8.0.0. Later, with the upgrade of .NET runtime to later versions of .NET 8.0 and .NET 9.0 and an upgrade to Visual Studio, some of those projects stopped working. It looks like they introduced breaking changes in the build tools. Logic is still sound and build types are the same, just the build tools started to behave a bit differently. A new build configuration and build scripts are needed. 

NOTE: All these build results are with .NET framework version around .NET 8.0.0. With the change in .NET version, file sizes changed (typically smaller). But build types are still the same. It looks like they improved/changed their build tools. 

=== Build 1 ===================================================
Location: 
c:\tmpNetBundle\BundleExample01\ConsoleApp1\bin\Release\net8.0-windows\win-x64\

Publish mode:
1) Release; 2) Framework-dependent; 3) Platform-specific-win-x64; 4) Un-bundled; 5) Untrimmed; 6) NotR2R; 7) PdbEmbedded; 8) BinariesNotInSingleFile; 9) AssembliesNotCompressed; 10) NotAot

Works! App started and it runs properly.

Content:
- 41 files
- 13.6MB

=== Build 2 ===================================================
Location: 
c:\tmpNetBundle\BundleExample01\ConsoleApp1\Framework_SingleFile_Win-X64\

Publish mode:
1) Release; 2) Framework-dependent; 3) Platform-specific-win-x64; 4) Single-file; 5) Untrimmed; 6) NotR2R; 7) PdbEmbedded; 8) BinariesNotInSingleFile; 9) AssembliesNotCompressed; 10) NotAot

Works! App started and it runs properly.

Content:
- 4 files
- 13.6MB

=== Build 3 - Build that I was not able to make ===================
Location: 
c:\tmpNetBundle\BundleExample01\ConsoleApp4\Framework_SingleFile_Win-X64_Trimmed\

Publish mode:
1) Release; 2) Framework-dependent; 3) Platform-specific-win-x64; 4) Single-file; 5) Trimmed; 6) Not-precompiled; 7) PdbEmbedded; 8) BinariesNotInSingleFile; 9) AssembliesNotCompressed

Error encountered:
NETSDK1102: Optimizing assemblies for size is not supported for the selected publish configuration. Please ensure that you are publishing a self-contained app.

=== Build 4 ===================================================
Location: 
c:\tmpNetBundle\BundleExample01\ConsoleApp2\bin\Release\net8.0-windows\win-x64\

Publish mode:
1) Release; 2) Self-contained; 3) Platform-specific-win-x64; 4) Un-bundled; 5) Untrimmed; 6) NotR2R; 7) PdbEmbedded; 8) BinariesNotInSingleFile; 9) AssembliesNotCompressed; 10) NotAot

Works! App started and it runs properly.

Content:
- 500 files
- 183MB

=== Build 5 ===================================================
Location: 
c:\tmpNetBundle\BundleExample01\ConsoleApp2\SelfContained_SingleFile_win-x64\

Publish mode:
1) Release; 2) Self-contained; 3) Platform-specific-win-x64; 4) Single-file; 5) Untrimmed; 6) NotR2R; 7) PdbEmbedded; 8) BinariesNotInSingleFile; 9) AssembliesNotCompressed; 10) NotAot

Works! App started and it runs properly.

Content:
- 9 files
- 167MB

=== Build 6 ===================================================
Location: 
c:\tmpNetBundle\BundleExample01\ConsoleApp2\SelfContained_SingleFile_win-x64_Trimmed\

Publish mode:
1) Release; 2) Self-contained; 3) Platform-specific-win-x64; 4) Single-file; 5) Trimmed; 6) NotR2R; 7) PdbEmbedded; 8) BinariesNotInSingleFile; 9) AssembliesNotCompressed; 10) NotAot

Works! App started and it runs properly.

Content:
- 9 files
- 38.4MB

=== Build 7 ===================================================
Location: 
c:\tmpNetBundle\BundleExample01\ConsoleApp3\bin\Release\net8.0-windows\win-x64\

Publish mode:
1) Release; 2) Self-contained; 3) Platform-specific-win-x64; 4) Un-bundled; 5) Untrimmed; 6) Not-precompiled; 7) PdbEmbedded; 8) BinariesNotInSingleFile; 9) AssembliesNotCompressed; 10) NotAot

Works! App started and it runs properly.

Content:
- 500 files
- 183MB

=== Build 8 ===================================================
Location: 
c:\tmpNetBundle\BundleExample01\ConsoleApp3\SelfContained_SingleFile_win-x64_ReadyToRun\

Publish mode:
1) Release; 2) Self-contained; 3) Platform-specific-win-x64; 4) Single-file; 5) Untrimmed; 6) ReadyToRun; 7) PdbEmbedded; 8) BinariesNotInSingleFile; 9) AssembliesNotCompressed; 10) NotAot

Works! App started and it runs properly.

Content:
- 9 files
- 204MB

=== Build 9 ===================================================
Location: 
c:\tmpNetBundle\BundleExample01\ConsoleApp3\SelfContained_SingleFile_win-x64_Trimmed_ReadyToRun\

Publish mode:
1) Release; 2) Self-contained; 3) Platform-specific-win-x64; 4) Single-file; 5) Trimmed; 6) ReadyToRun; 7) PdbEmbedded; 8) BinariesNotInSingleFile; 9) AssembliesNotCompressed; 10) NotAot

Works! App started and it runs properly.

Content:
- 9 files
- 41.7MB

=== Build 10 ===================================================
Location: 
c:\tmpNetBundle\BundleExample01\ConsoleApp1C\bin\Release\net8.0-windows\win-x64\

Publish mode:
1) Release; 2) Framework-dependent; 3) Platform-specific-win-x64; 4) Un-bundled; 5) Untrimmed; 6) NotR2R; 7) PdbEmbedded; 8) BinariesNotInSingleFile; 9) AssembliesNotCompressed; 10) NotAot

Works! App started and it runs properly.

Content:
- 41 files
- 13.6MB

=== Build 11 ===================================================
Location: 
c:\tmpNetBundle\BundleExample01\ConsoleApp1C\Framework_SingleFile_Win-X64\

Publish mode:
1) Release; 2) Framework-dependent; 3) Platform-specific-win-x64; 4) Single-file; 5) Untrimmed; 6) NotR2R; 7) PdbEmbedded; 8) BinariesInSingleFile; 9) AssembliesNotCompressed; 10) NotAot

Works! App started and it runs properly.

Content:
- 1 file
- 13.6MB

=== Build 12 ===================================================
Location: 
c:\tmpNetBundle\BundleExample01\ConsoleApp2C\bin\Release\net8.0-windows\win-x64\

Publish mode:
1) Release; 2) Self-contained; 3) Platform-specific-win-x64; 4) Un-bundled; 5) Untrimmed; 6) NotR2R; 7) PdbEmbedded; 8) BinariesInSingleFile; 9) AssembliesCompressed; 10) NotAot

Works! App started and it runs properly.

Content:
- 500 files
- 183MB

=== Build 13 ===================================================
Location: 
c:\tmpNetBundle\BundleExample01\ConsoleApp2C\SelfContained_SingleFile_win-x64\

Publish mode:
1) Release; 2) Self-contained; 3) Platform-specific-win-x64; 4) Single-file; 5) Untrimmed; 6) NotR2R; 7) PdbEmbedded; 8) BinariesInSingleFile; 9) AssembliesCompressed; 10) NotAot

Works! App started and it runs properly.

Content:
- 1 file
- 73.2MB

=== Build 14 ===================================================
Location: 
c:\tmpNetBundle\BundleExample01\ConsoleApp2C\SelfContained_SingleFile_win-x64_Trimmed\

Publish mode:
1) Release; 2) Self-contained; 3) Platform-specific-win-x64; 4) Single-file; 5) Trimmed; 6) NotR2R; 7) PdbEmbedded; 8) BinariesInSingleFile; 9) AssembliesCompressed; 10) NotAot

Works! App started and it runs properly.

Content:
- 1 file
- 20.4MB

=== Build 15 ===================================================
Location: 
c:\tmpNetBundle\BundleExample01\ConsoleApp3C\bin\Release\net8.0-windows\win-x64\

Publish mode:
1) Release; 2) Self-contained; 3) Platform-specific-win-x64; 4) Un-bundled; 5) Untrimmed; 6) NotR2R; 7) PdbEmbedded; 8) BinariesNotInSingleFile; 9) AssembliesNotCompressed; 10) NotAot

Works! App started and it runs properly.

Content:
- 500 files
- 183MB

=== Build 16 ===================================================
Location: 
c:\tmpNetBundle\BundleExample01\ConsoleApp3C\SelfContained_SingleFile_win-x64_ReadyToRun\

Publish mode:
1) Release; 2) Self-contained; 3) Platform-specific-win-x64; 4) Single-file; 5) Untrimmed; 6) ReadyToRun; 7) PdbEmbedded; 8) BinariesInSingleFile; 9) AssembliesCompressed; 10) NotAot

Works! App started and

3. Analyzing Build Results

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

4. Build 1 – Framework-dependent, normal build

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.

  1. Location: c:\tmpNetBundle\BundleExample01\ConsoleApp1\bin\Release\net8.0-windows\win-x64\
  2. Publish mode: 1)Release; 2)framework-dependent; 3)Platform-specific-win-x64; 4)Un-bundled; 5)Untrimmed; 6)NotR2R; 7)PdbEmbeded; 8)binariesNotInSingleFile; 9)assembliesNotCompressed; 10)NotAot.
  3. Build result Content: -41 files, -13.6MB.
    Result Content

Here are some screenshots from the detPeek decompiler.

DetPeek decompiler

ConsoleApp

Comments

  • This is a classical build of .NET8 console application
  • You get 2 files, ConsoleApp1.exe and ConsoleApp1.dll, and supporting libraries
  • ConsoleApp1.exe is not an assembly. It is just a loader with an embedded file name of the assembly that is supposed to load
  • ConsoleApp1.dll is the real .NET assembly that contains app code

5. To be continued

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

6. References

[1] .NET application publishing overview.

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

[2] Self-contained deployment runtime rolls 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/


Similar Articles