question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

.NET 8: [breaking] dotnet build/publish produces RID-specific apps by default

See original GitHub issue

[breaking] dotnet build/publish produces RID-specific apps by default

Proposal: dotnet build (and friends) produce RID-specific apps by default. This change results in apps that are smaller, simpler, faster to startup, and more reliable.

Proposal: any is the new RID for portable apps, since they will no longer be the default.

Example:

PS C:\Users\rich\app3> dotnet add package SkiaSharp
PS C:\Users\rich\app3> dotnet build
PS C:\Users\rich\app3> Get-ChildItem .\bin\Debug\ -Recurse | Measure-Object -Sum Length | Select-Object Sum

     Sum
     ---
31754654

PS C:\Users\rich\app3> Get-ChildItem .\bin\Debug\*Skia* -Recurse | Select-Object Name, Length, Directory

Name                Length Directory
----                ------ ---------
libSkiaSharp.dylib 8495552 C:\Users\rich\app3\bin\Debug\net6.0\runtimes\osx\native
libSkiaSharp.dll   7177104 C:\Users\rich\app3\bin\Debug\net6.0\runtimes\win-arm64\native
libSkiaSharp.dll   8413072 C:\Users\rich\app3\bin\Debug\net6.0\runtimes\win-x64\native
libSkiaSharp.dll   7081872 C:\Users\rich\app3\bin\Debug\net6.0\runtimes\win-x86\native
SkiaSharp.dll       414096 C:\Users\rich\app3\bin\Debug\net6.0

PS C:\Users\rich\app3> Remove-Item -Recurse bin
PS C:\Users\rich\app3> dotnet build -a x64
PS C:\Users\rich\app3> Get-ChildItem .\bin\Debug\ -Recurse | Measure-Object -Sum Length | Select-Object Sum

    Sum
    ---
8998050

PS C:\Users\rich\app3> Get-ChildItem .\bin\Debug\*Skia* -Recurse | Select-Object Name, Length, Directory

Name              Length Directory
----              ------ ---------
libSkiaSharp.dll 8413072 C:\Users\rich\app3\bin\Debug\net6.0\win-x64
SkiaSharp.dll     414096 C:\Users\rich\app3\bin\Debug\net6.0\win-x64

This app, with a SkiaSharp dependency, is 31MB by default (with the existing behavior) and ~9MB with the proposed behavior. That’s a significant benefit. If you have multiple RID-specific dependencies, then the benefit could be higher.

Related: https://github.com/dotnet/sdk/issues/23539

Context

.NET Core 1.0 started with the concept of both portable and RID-specific apps. We thought of portable apps as being matched with framework-dependent deployment and RID-specific apps being matched with self-contained deployment. That made good sense at the time. The idea is that portable apps could run on any runtime you paired the app with, and self-contained apps could only run in the specific environment that they were published for. Also, self-contained apps were the only apps with executables. Framework dependent. It wasn’t until .NET Core 3.0 that framework dependent apps got native executables by default. We now have a platform that has a diverse set of application offerings, which bias to portable or RID-specific apps being preferred. It’s worth re-considering which of the two models should be the default.

Portable apps only make sense if the following characteristics are all true:

  • App is deployed as framework-dependent.
  • App doesn’t require a native executable for the desired UX, and can be launched with the dotnet MyApp.dll pattern.
  • Size isn’t a primary performance metric.

Client apps don’t satisfy those characteristics:

  • Desktop client apps require an executable.
  • Mobile apps are self-contained.
  • Wasm apps are self-contained.

Server apps are mixed:

  • For container apps, RID-specific is best since size is a primary performance metric, and because the app will only ever be launched one way. The flexibility offered by portable apps doesn’t apply.
  • Apps that are developed and built on one environment (like Windows x64) and uploaded as binaries to a cloud service and then run in another environment (like Linux Arm64) are the poster-child for portable apps.

There is also the scenario where a dependency may have a security issue (CVE) on one platform and not another. It would be nice if you didn’t have to service a Linux binary on Windows (or vice versa) just to satisfy compliance rules.

In looking at the landscape, it becomes obvious that most scenarios benefit significantly from RID-specific deployment (either framework-dependent or self-contained) and that only niche scenarios benefit from portable apps. As a result, we should switch to RID-specific builds as the new SDK default.

Note: It turns out we already did this in very early .NET 7, but it wasn’t quite complete:

Issue Analytics

  • State:closed
  • Created 2 years ago
  • Reactions:5
  • Comments:7 (4 by maintainers)

github_iconTop GitHub Comments

1reaction
symphonic-navigatorcommented, Nov 22, 2022

I’m against it.

In a microservice environment with IoT (ARM64 in addition to AMD64) and multiple types of developer hardware (Windows PC, Linux PC, MacOS) it’s important to be able to build portable apps so build step can be done once in CI/CD only, not redundant per target platform.

In my opinion platform independent should be default, the argument “size” doesn’t really count when it comes to containers.

It would be more interesting to be able to have dotnet publish being able to publish “external dependencies only” and .NET applications able to use dependencies from a different directory (so we could build images with the dependencies pre-installed).

Things like that.

0reactions
nagilsoncommented, Jan 20, 2023

We won’t be doing this. New proposal for something related, though not the breaking change: https://github.com/dotnet/sdk/issues/29950

Read more comments on GitHub >

github_iconTop Results From Across the Web

Runtime-specific apps no longer self-contained - .NET
Learn about a breaking change in the .NET 8 SDK where apps that specify a runtime identifier are no longer self-contained by default....
Read more >
Breaking changes in .NET 8
If you're migrating an app to .NET 8, the breaking changes listed here might affect you. Changes are grouped by technology area, ...
Read more >
NET application publishing overview
.NET can publish platform-specific or cross-platform apps. ... Both publishing modes produce a platform-specific executable by default.
Read more >
Announcing .NET 8 Preview 5
The Linux distribution-built (source-build) SDK can now build self-contained applications that utilizes source-build runtime packages.
Read more >
`RuntimeIdentifier` warning if self-contained is unspecified ...
NET SDK defaults the build, publish, and run outputs to be self-contained applications. The default without specifying a RuntimeIdentifier is to ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found