dotnet / sdk

Core functionality needed to create .NET Core projects, that is shared between Visual Studio and CLI
https://dot.net/core
MIT License
2.68k stars 1.06k forks source link

PublishTrimmed should imply self-contained #30104

Closed eerhardt closed 9 months ago

eerhardt commented 1 year ago

Doing the following steps:

Results in the following error:

C:\Users\eerhardt\.nuget\packages\microsoft.net.illink.tasks\8.0.100-1.22619.1\build\Microsoft.NET.ILLink.targets(196,5): error NETSDK1102: Optimizing assemblies for size is not supported for
the selected publish configuration. Please ensure that you are publishing a self-contained app. [C:\DotNetTest\Net8Console\Net8Console.csproj]

However, doing

Just works without more command line args.

We should make PublishTrimmed=true imply SelfContained=true, just like PublishAot=true and PublishSingleFile=true does. That way users don't need to pass extra args on the command line, just to make this work.

If in the future we want to support a mode where PublishTrimmed=true, but SelfContained=false, those customers can explicitly --self-contained false. This is consistent with the current PublishSingleFile=true behavior. By default it is self-contained. And you can opt into Framework Dependent Deployment with dotnet publish -p:PublishSingleFile=true --self-contained false.

cc @vitek-karas @sbomer @agocke

ghost commented 1 year ago

@dotnet/linker-contrib a new issue has been filed in the ILLink area, please triage

agocke commented 1 year ago

Surprised that dotnet publish -p:PublishSingleFile=true is self-contained by default. But I don't dislike the behavior. And agree with the proposal about PublishTrimmed.

The only thing I don't like is that these properties affect dotnet build as well. In fact, I don't like self-contained dotnet build at all. I think that should be a publish-only gesture.

sbomer commented 1 year ago

I think this is happening because of the default RID selection. PublishReadyToRun/PublishSingleFile/PublishAot use the current RID, and having a RID currently implies self-contained. https://github.com/dotnet/sdk/blob/201d7199a60503fa627fd3c06cab03a53066ac92/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.RuntimeIdentifierInference.targets#L79-L92 But @nagilson is working on a breaking change where RID no longer implies self-contained: https://github.com/dotnet/sdk/pull/30038.

I expect that after this change, PublishAot will have an error similar to the current one for PublishTrimmed, and the PublishSingleFile default will become framework-dependent. The latter might violate user expectations, but at least will be consistent with the new defaults.

sbomer commented 1 year ago

@marcpopMSFT IIRC you set up the auto-tagging of @dotnet/linker-contrib based on the area labels. The team name changed to @dotnet/illink-contrib. Would you be able to update the bot config?

marcpopMSFT commented 1 year ago

@sbomer see https://github.com/dotnet/sdk/pull/30152. Feel free to update this in the future if there are changes needed.

richlander commented 1 year ago

Good topic! We're trying to provide coherent behaviors for some things that are similar and others less so. It's sometimes easier when we group the options such that the answer pops out. Let's see if that happens here.

I'm going to use MSBuild syntax, where all properties are intended as true or otherwise have coherent value.

Always framework-dependent:

Supports both:

Could support both, but only supports self-contained:

Always self-contained:

There are two ways we could go with this:

There are four groups. The pragmatic choice is make the first two groups fx-dependent by default and the second two are self-contained.

Another observation is that PublishTrimmed is likely not used that often on its own. Instead, we could do the following:

That approach would have multiple benefits:

This approach seems to balance CLI consistency with convenience while also most often providing users with a set of artifacts that we would say are "good".

sbomer commented 1 year ago

Default PublishSelfContained to infer PublishTrimmed and require users to disable trimming if they don't want it. We could also infer PublishReadyToRun in the same way.

It's worth noting that PublishTrimmed and PublishReadyToRun can be somewhat at odds, depending on the goals - trimming will remove R2R info and produce the smallest output, while R2R adds back some size in exchange for startup perf.

Single file would remain a separate concern. The thinking to date is that the various forms of single file should be opt-in since there are more compat considerations with single file variants than with self-contained.

It seems like the same reasoning would apply to PublishTrimmed as well - there are compat concerns if we implicitly set PublishTrimmed for PublishSelfContained.

agocke commented 1 year ago

@richlander Based on my comment above, I want to retire SelfContained as it is today. Specifically, I think if you want a self-contained output you should have to use dotnet publish.

agocke commented 1 year ago

A couple more things, actually.

Default PublishSelfContained to infer PublishTrimmed and require users to disable trimming if they don't want it. We could also infer PublishReadyToRun in the same way.

I'm not sure I understand what you're suggesting here. You mean that if PublishSelfContained is true, the default for PublishTrimmed is also true? Or the other way around?

Single file would remain a separate concern. The thinking to date is that the various forms of single file should be opt-in since there are more compat considerations with single file variants than with self-contained.

The compat between self-contained single file and plain self-contained is getting pretty good at this point. It's pretty much just Assembly.Location now.

richlander commented 1 year ago

That's a good point @sbomer. Let's go with that.

I'm thinking about this more. I was trying to get at something with that categorization in my previous post, but I didn't quite know what. I do now.

Let's try again.

App characteristics (don't auto-switch from FDD -> SCD):

App kind (these auto switch to SCD):

This feels like a more useful categorization, but I still don't find it particularly satisfying. For example, PublishSingleFile feels like it should be an app kind and PublishTrimmed only supports self-contained apps currently.

In the ideal case, users set the minimum values in their project file, like setting PublishSelfContained=true. If they want to try out trimming or single file from the CLI, they will always get the desired result.

I think this conversation comes down to specializing a default project file (like what templates produce) via the CLI. I think a solution like this would help: https://github.com/dotnet/sdk/issues/26249#issuecomment-1406940259. It's basically the same thing as specifying the same values in a project file.

@agocke -- SelfContained ... I'm a little torn on that one. We need to decide once and for all that we're going to stay with publish forever. If we agree to that, then I'm happy to go along with your suggestion. Related: https://github.com/dotnet/sdk/issues/26247.

@agocke -- I meant that PublishSelfContained could infer PublishTrimmed. I had proposed single file as a default in the past. @jkotas considered that too much of a compatibility risk for opt-out.

Upon further thinking, I think we should go with the categorization I have above and then rely on good project file and CLI gestures to make it easy to adopt the configuration you want. We just added PublishSelfContained and the bad PM for that feature hasn't published a blog post on that yet. I think we don't have enough customer feedback to suggest we need something more dramatic. I'd rather see us make the CLI easier to use to specify defaults for an environment.

richlander commented 1 year ago

@baronfel @dsplaisted

nagilson commented 1 year ago

Thanks everyone for engaging here + internally 😄

@richlander Should we still take this change: https://github.com/dotnet/sdk/pull/30038 if it does not have PublishAot giving SelfContained by default? Today is the last day for it to get merged (technically Monday at 3 PM...). It sounds like we are OK with this change breaking PublishTrimmed, PublishSingleFile, and PublishReadyToRun such that old usages of these will now have to add SelfContained.

If we have a finalized decision on this, we should close/edit this issue since we've seem to have decided against it, and make one specifically for having PublishAot -> SelfContained, as well as one for PublishSelfContained.

richlander commented 1 year ago

Right. I'm suggesting that PublishAot and PublishSelfContained should infer SelfContained.

I think all the other cases should not infer a SelfContained value. That breaks our model, IMO, and is impossible to explain w/o giving folks a decoder ring. Sometimes what feels like a productivity killer (like our PublishTrimmed example) is overshadowed by an inconsistent model.

richlander commented 1 year ago

Up-leveling a bit. We should be dissatisfied with experiences that are inconvenient. However, addressing those at the lowest levels (like with these properties) is just one option. We should ensure we have all the options on the table for how to address UX. I'm proposing we handle this UX concerns (like PublishTrimmed being annoying) at a higher level. It's really only annoying for the CLI scenario.

sbomer commented 1 year ago

If we intend to handle UX concerns at a higher level (which as I understand means through project templates, or some other way to "bake in" the chosen options), would it make sense to treat PublishAot the same as PublishTrimmed? That way it becomes very clear whether the output is SCD or FDD, based on the presence/absence of PublishSelfContained, and PublishAot is no longer the odd one out.

From the internal discussion it also sounds like a FDD PublishAot deployment is possible in theory, even if it's unlikely we would add this option.

Then we can explain everything by saying that SCD is orthogonal to the other publish options. To use your terminology, SCD is an "app kind" and everything else is an "app characteristic" - where not all combinations are supported, but nothing is implicitly set (so no decoder ring is required).

richlander commented 1 year ago

I don't think PublishAot and PublishTrimmed are very similar. We could enable PublishTrimmed for FDD if we wanted to. We just haven't. It also means we're one motivating customer request from doing so.

Another middling option is to expose another set of CLI flags, like --trim-scd or similar.

jkotas commented 1 year ago

We could enable PublishTrimmed for FDD if we wanted to. We just haven't.

The same can be said about PublishAot. (FDD was the default deployment option for .NET Native for UWP.)

richlander commented 1 year ago

You are right! I forgot about that. However (and correct me if I'm wrong), it seems more likely that we'll enable trimming for FDD than Native Aot for FDD. Or, do we just need to wait on a similar "one motiving scenario"?

jkotas commented 1 year ago

I agree.

richlander commented 1 year ago

That's a bit ambiguous. There were two things you could agree with. I assume you were agreeing that trimming for FDD was more likely.

jkotas commented 1 year ago

I assume you were agreeing that trimming for FDD was more likely.

Yep.

richlander commented 1 year ago

Here's a concrete proposal, since we still have time on our side.

I make no secret that I think this approach would be a good solution for this specific topic area and also have broader utility for even more common scenarios.

vitek-karas commented 1 year ago

As stated above there's a conflict between consistency and "ease of use". The above discussion makes it clear that we're proposing sacrifying "easy of use on CLI" and want consistent CLI options. (Personally I'm split on this, but if most people think that's the right approach, let's do it). This means that for example adding trimming in CLI will be somewhat cumbersome (need to also specify SCD).

With that, I don't see why we would special case PublishNativeAOT as the only which implies SCD. On the scale of "basic" to "advanced" uses, AOT is probably the most advanced right now, so we could argue that making it easy to use from CLI is low priority.

Another way to look at it - if we think we can solve the UX for trimming outside of CLI, I don't see why we could not solve it the same way for AOT as well. And then keep the CLI 100% consistent.

As already mentioned, we could introduce CLI-only aliases which solve the UX: We're already introducing dotnet new api -aot and thus it would make sense to have dotnet publish -aot which will "do the right thing" (and that could mean different things for different TFMs if we really needed to). Basically, decouple the MSBuild properties (very explicit and orthogonal/independent) from use-of-use CLI options (targeted at the most frequent scenarios).

eerhardt commented 1 year ago

I don't think making a breaking change for PublishSingleFile to default to framework-dependent is correct. Logically, I want my app in a single file. To me, making the default behavior being "the whole app in a single file" is the expected behavior.

For PublishTrimmed, even if/when we support FDD with PublishTrimmed, the fact that we've only had self-contained for 4, going on 5, versions now should tell us what the logical default is. If the scenario isn't important enough to implement, it isn't important enough to be considered the "default".

sbomer commented 1 year ago

I don't think making a breaking change for PublishSingleFile to default to framework-dependent is correct

I agree that this is one of the biggest downsides to the breaking change (RID no longer implying self-contained). Same applies to vanilla "dotnet publish -r \<RID>".

However, I would find it really unexpected if "dotnet publish" produced one kind (SCD/FDD) of deployment, but "dotnet publish -p:PublishSingleFile=true" produced a different kind. So I'll throw another idea into the mix: what if we made PublishSelfContained true by default? It would keep the command-line options independent, and shifts where the breaking change is.

Pros:

Cons:

I'm not sure how significant the "dotnet publish" break is. Personally I only ever do a RID-specific publish anyway (and almost always want it to be self-contained), but maybe my usage is not representative.

nagilson commented 1 year ago

PublishSelfContained by default is an interesting idea. Another idea per @marcpopMSFT is that we could infer SelfContained by default when using these properties, BUT have a warning like the old SelfContained warning,

WARNING: NETSDK11??: One of '--self-contained' or '--no-self-contained' options are recommended when `Publish*` is used.

Thoughts @richlander ? I think this is a good compromise with UX but also on the orthogonal properties perspective.

eerhardt commented 1 year ago

I don't think making a breaking change for PublishSingleFile to default to framework-dependent is correct

I agree that this is one of the biggest downsides to the breaking change (RID no longer implying self-contained). Same applies to vanilla "dotnet publish -r ".

IMO - This isn't part of the RID breaking change. I didn't specify a RID at all: dotnet publish -p:PublishSingleFile=true. I don't get a warning on .NET 7, like I do for -r <RID>.

richlander commented 1 year ago

Here's the product behavior to date. It's useful to record that so that we're all on the same page.

.NET 6:

root@d2e8b3f38232:/app# dotnet --version
6.0.405
root@d2e8b3f38232:/app# dotnet new console -o app
root@d2e8b3f38232:/app# dotnet publish
root@d2e8b3f38232:/app# find . | grep coreclr
root@d2e8b3f38232:/app# dotnet publish -p:SelfContained=true
MSBuild version 17.3.2+561848881 for .NET
  Determining projects to restore...
  All projects are up-to-date for restore.
/usr/share/dotnet/sdk/6.0.405/Sdks/Microsoft.NET.Sdk/targets/Microsoft.NET.RuntimeIdentifierInference.targets(154,5): error NETSDK1031: It is not supported to build or publish a self-contained application without specifying a RuntimeIdentifier. You must either specify a RuntimeIdentifier or set SelfContained to false. [/app/app.csproj]
root@d2e8b3f38232:/app# dotnet publish -p:PublishReadyToRun=true
MSBuild version 17.3.2+561848881 for .NET
  Determining projects to restore...
  Restored /app/app.csproj (in 5.18 sec).
  app -> /app/bin/Debug/net6.0/app.dll
/usr/share/dotnet/sdk/6.0.405/Sdks/Microsoft.NET.Sdk/targets/Microsoft.NET.Publish.targets(293,5): error NETSDK1094: Unable to optimize assemblies for performance: a valid runtime package was not found. Either set the PublishReadyToRun property to false, or use a supported runtime identifier when publishing. [/app/app.csproj]

.NET 7:

root@d94e82f2a8a2:/app# dotnet --version
7.0.102
root@d94e82f2a8a2:/app# dotnet new console
root@d94e82f2a8a2:/app# dotnet publish
root@d94e82f2a8a2:/app# find . | grep coreclr
root@d94e82f2a8a2:/app# dotnet publish -p:SelfContained=true
MSBuild version 17.4.1+9a89d02ff for .NET
  Determining projects to restore...
  Restored /app/app.csproj (in 4.97 sec).
  app -> /app/bin/Debug/net7.0/linux-x64/app.dll
  app -> /app/bin/Debug/net7.0/linux-x64/publish/
root@d94e82f2a8a2:/app# find . | grep coreclr
./bin/Debug/net7.0/linux-x64/libcoreclr.so
root@d94e82f2a8a2:/app# dotnet publish -p:PublishReadyToRun=true
MSBuild version 17.4.1+9a89d02ff for .NET
  Determining projects to restore...
  All projects are up-to-date for restore.
  app -> /app/bin/Debug/net7.0/linux-x64/app.dll
  app -> /app/bin/Debug/net7.0/linux-x64/publish/
root@d94e82f2a8a2:/app# find . | grep coreclr
./bin/Debug/net7.0/linux-x64/libcoreclr.so
./bin/Debug/net7.0/linux-x64/publish/libcoreclr.so
root@d94e82f2a8a2:/app# dotnet publish -p:PublishTrimmed=true
MSBuild version 17.4.1+9a89d02ff for .NET
  Determining projects to restore...
  Restored /app/app.csproj (in 64 ms).
  app -> /app/bin/Debug/net7.0/app.dll
/usr/share/dotnet/sdk/7.0.102/Sdks/Microsoft.NET.ILLink.Tasks/build/Microsoft.NET.ILLink.targets(196,5): error NETSDK1102: Optimizing assemblies for size is not supported for the selected publish configuration. Please ensure that you are publishing a self-contained app. [/app/app.csproj]
root@d94e82f2a8a2:/app# dotnet publish -p:PublishSingleFile=true
MSBuild version 17.4.1+9a89d02ff for .NET
  Determining projects to restore...
  Restored /app/app.csproj (in 104 ms).
  app -> /app/bin/Debug/net7.0/linux-x64/app.dll
  app -> /app/bin/Debug/net7.0/linux-x64/publish/
root@d94e82f2a8a2:/app# dotnet publish -p:PublishNativeAot=true
MSBuild version 17.4.1+9a89d02ff for .NET
  Determining projects to restore...
  Restored /app/app.csproj (in 81 ms).
  app -> /app/bin/Debug/net7.0/app.dll
  app -> /app/bin/Debug/net7.0/publish/

I actually thought we implemented PublishSelfContained last version, but I guess not. As I recall, this isn't the first time I've been confused by that.

The quick summary is this, all new in .NET 7:

richlander commented 1 year ago

However, I would find it really unexpected if "dotnet publish" produced one kind (SCD/FDD) of deployment, but "dotnet publish -p:PublishSingleFile=true" produced a different kind.

It is even more true for dotnet build to dotnet publish, in general. We cannot change dotnet publish to be SCD. That's a very large breaking change and would fundamentally change the product. For example, there are tons of people that use our container images. They need to produce FDD apps for that to make sense.

I guess after all of this conversation, I conclude that we should leave the behavior as-is in .NET 7. I think we all agree that there is an affinity to SCD with Single File and AOT. That's why they have the current behavior. I'm no longer proposing we change that.

I'm still not convinced on PublishTrimmed. We are going through a painful multi-release effort of changing what dotnet publish -r some-rid means, making it FDD by default. I don't want to regret this moment when we later decide to support FDD trimming. I suspect it will happen at some point.

Let's assume that we were enabling FDD trimming this release. What would we do?

I think we'd enable it for both FDD and SCD PublishTrimmed, and (like now) it wouldn't imply either.

We'd then need to decide if we wanted a simpler way to enable PublishTrimmed + SCD in one gesture. I'd be happy with PublishTrimmedScd. Is that good enough to satisfy the usability concerns?

Tell me if I'm wrong, but I don't think we need to over-prioritize the loose-files scenario. I'm guessing that most folks prefer one of our single file scenarios. Also, has there been many requests to improve this? If not, then that suggests to me that people are using the single file options.

richlander commented 1 year ago

I just did some more research. I forgot about PublishReadyToRun. It implies a RID and SCD. I updated the comment above to include that.

I'm not sure I agree with my previous thinking (in .NET 7) that led to this point, but I'm now coming to a different conclusion given the experiences all pushing one way and a desire for consistent behaviors and not breaking compat.

Back to what we'd do if we were enabling PublishTrimmed now. I'd suggest then that we consider adding a PublishTrimmedFdd variant and same to the other Publish* properties that currently imply SCD but also can support FDD.

Outside of that idea, people could update their project files like this and that would work.

<PropertyGroup>
  <PublishTrimmed>true</PublishTrimmed>
  <PublishSelfContained>false</PublishSelfContained>
</PropertyGroup>

That leads me to the conclusion that all the Publish* properties should imply SCD and a RID. That's not too crazy. The Publish* properties were created for the non-default case. Most people that want the non-default case are opting for some form of SCD.

sbomer commented 1 year ago

I agree that this is one of the biggest downsides to the breaking change (RID no longer implying self-contained). Same applies to vanilla "dotnet publish -r ".

IMO - This isn't part of the RID breaking change. I didn't specify a RID at all: dotnet publish -p:PublishSingleFile=true. I don't get a warning on .NET 7, like I do for -r .

@nagilson please correct me if I'm wrong, but I believe that the behavior is the consequence of "use current rid for single-file" combined with "rid implies self-contained" - so I think https://github.com/dotnet/sdk/pull/30038 will result in single-file being FDD by default.

richlander commented 1 year ago

Unless we change it. We need to decide on the intended behavior and then we have deliver it. I have made a proposal on that.

sbomer commented 1 year ago

Let's assume that we were enabling FDD trimming this release. What would we do?

I think we'd enable it for both FDD and SCD PublishTrimmed, and (like now) it wouldn't imply either.

all the Publish* properties should imply SCD and a RID.

I preferred the first conclusion. :) I would keep trimming orthogonal to FDD/SCD - it feels wrong to have one deployment mode for "dotnet publish", and the opposite for "dotnet publish -p:PublishTrimmed=true", especially if we support both.

It seems worth revisiting our reasoning for removing the "RID -> self-contained" behavior. My understanding is that since RID-specific works with both FDD and SCD, we wanted to keep the options orthogonal to each other. It was confusing that no-RID meant FDD, and RID meant SCD.

How are the publish options different? (Why should no-R2R be FDD, but R2R be SCD by default?)

agocke commented 1 year ago

Seems like there are three reasons why we might set defaults to particular values:

  1. Consistency
  2. Belief that one use case is more common
  3. Only one use case is supported

(3) is a bit tricky because the support might be temporary, but I don't necessarily think that's a bad reason to set a default if we think that even if that changes (2) still holds.

So it appears that we have three options:

  1. Have everything set to FDD by default, as that is the default for regular build and this would be the most consistent choice.
  2. Go option by option and try to predict which use will be most common
  3. Set the option that works, if only one works, assuming that we've also done (2) and think that if another option works in the future, that will still hold.
DamianEdwards commented 1 year ago

Random thought, might be nice to enable something like this (it would just set the specific properties during the relevant target, with values for the specific properties winning if also specified):

<PropertyGroup>
  <PublishKind>Trimmed;SelfContained;SingleFile;Release</PublishKind>
</PropertyGroup>

The valid values are any of the '*' values from the 'Publish*' properties. If an invalid combination is specified it would error.

agocke commented 1 year ago

@DamianEdwards Meh. Sorry, seems like clutter to me, and now I have to remember two ways of configuring the flags. 😄

DamianEdwards commented 1 year ago

@agocke well that's just, like, your opinion man 😉

But seriously, eye of the beholder and all that. But looking at this sea of publish properties made me desire something more concise, especially when we start talking about combination properties like PublishTimmedScd ewww

agocke commented 1 year ago

combination properties like PublishTimmedScd ewww

Yeah, I'm not convinced we should do those either. At the end of the day I think the verbosity of setting each individual flag isn't such a big deal, and much of the verbosity actually comes from XML. I'd rather not create complex parsing just to work around XML verbosity. Whether or not we like it, it's the language we've chosen.

DamianEdwards commented 1 year ago

I'd rather not create complex parsing just to work around XML verbosity.

I understood this was an established pattern in our build system already (semi-colon separated values) so I didn't consider it as introducing anything new or complex.

agocke commented 1 year ago

Items are generally preferred, because then you don't have the (ridiculously common, always infuriating) problem of <NoWarn>CA12356</NoWarn> accidentally overriding all the previous <NoWarn> clauses.

But the difficulty mostly comes from your suggestion of parsing the separated values and then using them to set the PublishX property. Not easy to implement in MSBuild target language and not possible in a build task.

richlander commented 1 year ago

it would just set the specific properties during the relevant target

Interesting idea, but I don't think that's the key aspect we're struggling with. In fact, that feels a bit like an anti-pattern since we're trying to make the product provide best practice behavior by default. It just turns out that's hard in some cases..

especially when we start talking about combination properties like PublishTimmedScd ewww

Agree.

How are the publish options different? (Why should no-R2R be FDD, but R2R be SCD by default?)

You are right. The current system doesn't make much sense. When I was writing last night, I was getting "compat afraid". So, let's play the "compat be damned" game.

I'd switch all of these to FDD by default, give the teams the opportunity to provide a valuable FDD behavior, and then add a --scd flag to the CLI. Obviously PublishSelfContained would remain SCD.

Actually, I'd also leave PublishNativeAot as-is, implying SCD. I don't think we're ever going to provide an FDD behavior for it. As Jan raised, we've done that in the past, but I am extremely doubtful that we'll ever repeat that.

This release is definitely our last opportunity to make these changes. What do folks think of this proposal? Certainly, it would be the most coherent to the product overall.

DamianEdwards commented 1 year ago

and then add a --scd flag to the CLI

We already have --self-contained though right? Or am I misunderstanding?

richlander commented 1 year ago

Yes. It's a pain to type. What I'm hearing from this conversation is that people on the team (who I totally recognize are not our customers) find the following to be arduous:

root@d94e82f2a8a2:/app# dotnet publish -p:PublishTrimmed=true
MSBuild version 17.4.1+9a89d02ff for .NET
  Determining projects to restore...
  Restored /app/app.csproj (in 64 ms).
  app -> /app/bin/Debug/net7.0/app.dll
/usr/share/dotnet/sdk/7.0.102/Sdks/Microsoft.NET.ILLink.Tasks/build/Microsoft.NET.ILLink.targets(196,5): error NETSDK1102: Optimizing assemblies for size is not supported for the selected publish configuration. Please ensure that you are publishing a self-contained app. [/app/app.csproj]
root@d94e82f2a8a2:/app# dotnet publish -p:PublishTrimmed=true --self-contained

The UX ask was to make -p:PublishTrimmed=true to be SCD. While also recognize my flip-flop-ness on the topic, I've been pushing back on that. I'm trying to make the product consistent and easier to use at the same time. Adding --scd was intended to help with that and be a middle ground answer. I do want to reiterate that I think this whole converation is a function of the CLI experience. I hold that we have a good model for project files since they are typically "get it right once and forget it".

Also, lots of CLIs offer short forms like that so it doesn't seem strange.

For example:

$ wget --help | grep verbose
  -v,  --verbose                   be verbose (this is the default)
  -nv, --no-verbose                turn off verboseness, without being quiet
agocke commented 1 year ago

Actually, I'd also leave PublishNativeAot as-is, implying SCD

This feels like my argument about commonality-over-consistency. Even if we build PublishAot FDD, it will be much less common than scd. I think at can make the same argument for Publish Trimmed or single file

richlander commented 1 year ago

NativeAot is most that way and we get farther from that level of certainty as we go. They don't sit at the same spot on the spectrum. That's why I don't find this argument convincing.

Also, we're never going to build Native AOT FDD. It's a waste of time since no one wants that modality.

agocke commented 1 year ago

Also, we're never going to build Native AOT FDD

The more I look at it, the more I think the same think about PublishTrimmed.

vitek-karas commented 1 year ago

The more I look at it, the more I think the same think about PublishTrimmed.

I've seen several asks for FDD Trimming over time (TerraFx - if I remember correctly is one example, WinUI is another).

FDD Single-File is also pretty useful and I've seen it used. Definitely not as common as SCD though.

I personally don't buy any argument toward making R2R default to SCD - those two are completely orthogonal even functionally.

So the only two which I think we might consider are:

sbomer commented 1 year ago

I'd switch all of these to FDD by default, give the teams the opportunity to provide a valuable FDD behavior, and then add a --scd flag to the CLI. Obviously PublishSelfContained would remain SCD.

This is my favorite proposal so far - and I like the less verbose --scd flag as a UX improvement.

Regarding AOT and trimming:

There's also the argument about one-way doors. If we make either scenario SCD by default, it is harder to go back. If we make them "fail by default" (with an obvious and easily fixed error) we still leave open the option of making them SCD by default in the future.

This suggests to me that we could take the breaking change as-is, and look for feedback in .NET 8 previews to see how painful it is for customers. We still have plenty of time to add SCD-by-default for trimming/aot if we need to.

agocke commented 1 year ago

less verbose --scd flag as a UX improvement

We already have --sc.

nagilson commented 1 year ago

@sbomer Thanks for bringing me in here.

Please correct me if I'm wrong, but I believe that the behavior is the consequence of "use current rid for single-file" combined with "rid implies self-contained"

This is correct.

Net 6: (No Implicit RID): dotnet publish -p:PublishSingleFile=true --> SelfContained=false, except it will fail. Once you add the rid to make it pass, then it is the same as:

Net 7: (Implicit RID): dotnet publish -p:PublishSingleFile=true --> RuntimeIdentifier --> SelfContained=true

For PublishSingleFile the default FDD behavior is OK, it won't fail. And that was the default behavior in NET 6. (Well, you can do it with --no-selfcontained: but you need to provide a RID. Sorry for my sloppy language, thanks.)