Skip to content

Navigation Menu

Sign in
Sign up

.NET 8 bundled runtime packs (preview 6) #3535

tmds started this conversation in General
Jun 23, 2023 · 1 comments · 6 replies
Discussion options

@dotnet/distro-maintainers, in the upcoming preview 6 the vmr build output will include the .NET Core and ASP.NET Core runtime packs.

These are the source-build equivalents of what Microsoft publishes as https://www.nuget.org/packages/Microsoft.NETCore.App.Runtime.linux-x64 and https://www.nuget.org/packages/Microsoft.AspNetCore.App.Runtime.linux-x64.

They are used when a .NET application is published as self-contained.

By including these packs, it is possible to build a self-contained application that uses binaries you've built from source, rather than binaries that were obtained from nuget.org.

To use these packs, the self-contained application must be published against the non-portable rid, for example:

dotnet publish -r fedora.37-x64 --sc

For this to work, the distro packages for .NET should include the runtime packs which are found at packs/Microsoft.NETCore.App.Runtime.<rid> and packs/Microsoft.AspNetCore.App.Runtime.<rid> in the vmr output.

These files are duplicate files from what is in the shared framework. To avoid bloating the install, you can combine the files with the corresponding shared framework files in a package and use hard links. The vmr output will contain such hard links, but they are easily lost when copying files, so there may be some work in preserving/re-creating them when packaging and installing.

If the packs are not included in the distro .NET packages, the SDK assume they should exist somewhere, go look for them on nuget.org, and fail.

That is the behavior with the preview6 build.
If there is a desire to be able to built without the runtime packs, we can make the feature opt-in.

I've created this discussion to raise awareness the packs are included with preview 6, and for getting your feedback.

cc @ashnaga @MichaelSimons @premun @dsplaisted

You must be logged in to vote

Replies: 1 comment 6 replies

Comment options

The vmr output will contain such hard links, but they are easily lost when copying files, so there may be some work in preserving/re-creating them when packaging and installing

Some feedback after trying this out in CentOS Stream, and RHEL.

Both RHEL 8 and 9 have trouble dealing with hardlinked files. There's some tools that run post-RPM-package-build that apparently haven't been tested with hardlinks. And it turns out they break in a few random ways. It's a bug in RHEL, but there's no immediate fix incoming.

In addition, when hardlinks are packaged into an RPM, something essentially loses track that the files are hardlinked and not copies. When we install the just-built RPMs we get copies of files on disk anyway, losing the benefits disk-space-savings that we would have seen with hardlinks.

You must be logged in to vote
6 replies
Comment options

@omajid, Has anything changed on the RPM front on your side in regards to hardlinks? If .NET started producing the sdk tarball w/hardlinks in .NET 11.0 would that be an issue for you as a way to eliminate the cost of duplicate files within the SDK layout?

Comment options

omajid Jan 16, 2026
Collaborator

Has anything changed on the RPM front on your side in regards to hardlinks?

No, not that I am aware of. I can test it again. Is there a quick way to build the SDK with hardlinks to verify the behaviour?

Comment options

No, not that I am aware of. I can test it again. Is there a quick way to build the SDK with hardlinks to verify the behaviour?

You can take my PR and build it. Use this commit as it it configured to create hardlinks on linux. I am actively experimenting with the PR so be aware if you pull the latest. If it helps you can pull the SB tarball artifact from centosstream here.

Comment options

omajid Apr 29, 2026
Collaborator

I have some time now, so I am revisiting this. I am testing 11 Preview 3, packaged as RPMs.

  • Using symbolic links (default behaviour now) seems to work okay everywhere. This build is also available here: https://copr.fedorainfracloud.org/coprs/g/dotnet-sig/dotnet-preview/build/10393156/. I don't know yet if our official build servers we use do things differently.
    • Fedora 43
      $ find /usr/lib64/dotnet -type l | wc -l
      675
      $ find /usr/lib64/dotnet -type f -links +1 | wc -l
      0
      $ du -hs /usr/lib64/dotnet/
      563M	/usr/lib64/dotnet/
      
    • RHEL 8
      $ find /usr/lib64/dotnet -type f -links +1 | wc -l
      0
      $ find /usr/lib64/dotnet -type l | wc -l
      675
      $ du -hs /usr/lib64/dotnet
      543M	/usr/lib64/dotnet
      
  • I tried a local building using force-enabling hardlinks using sed -i -E 's|>false</_UseHardLinks>|>true</_UseHardLinks>|' src/sdk/src/Layout/redist/targets/GenerateInstallerLayout.targets:
    • ✔️ Fedora 43
      $ find /usr/lib64/dotnet -type l | wc -l
      331
      $ find /usr/lib64/dotnet -type f -links +1 | wc -l
      620
      $ du -hs /usr/lib64/dotnet
      561M	/usr/lib64/dotnet
      
    • ✔️ RHEL 10
      $ find /usr/lib64/dotnet -type f -links +1 | wc -l
      620
      
    • ✔️ RHEL 9
      $ find /usr/lib64/dotnet -type f -links +1 | wc -l
      620
      $ find /usr/lib64/dotnet -type l | wc -l
      331
      $ du -hs /usr/lib64/dotnet/
      542M	/usr/lib64/dotnet/
      
    • ✔️ RHEL 8
      $ find /usr/lib64/dotnet -type l | wc -l
      331
      $ find /usr/lib64/dotnet -type f -links +1 | wc -l
      620
      $ du -hs /usr/lib64/dotnet
      542M	/usr/lib64/dotnet
      

I am a bit confused about what's going on. It seems to work everywhere and hardlinks are present on disk, even after packaging as RPM and extracting it back on disk. This doesn't match with what I saw last year. I am going to test this some more.

Comment options

omajid May 5, 2026
Collaborator

I did test builds on our build server and still see working hardlinks with space savings:

# RHEL 8 using 11.0 test-packages build on RHEL build servers:
$ find /usr/lib64/dotnet -type l | wc -l
331
$ find /usr/lib64/dotnet -type f -links +1 | wc -l
620
$ du -hs /usr/lib64/dotnet
542M	/usr/lib64/dotnet 

vs

# RHEL 8 using .NET 10 packages:
$ find /usr/lib64/dotnet -type l | wc -l
318
$ find /usr/lib64/dotnet -type f -links +1 | wc -l
0
$ du -hs /usr/lib64/dotnet
614M	/usr/lib64/dotnet

I can't explain why this wasn't working before. But the good news is that it does seem to be working now, and the on-disk savings are visible.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet

AltStyle によって変換されたページ (->オリジナル) /