-
Notifications
You must be signed in to change notification settings - Fork 4.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Microsoft.NETCore.App 1.0.1 app does not run on .NET Core 1.1.0 #2542
Comments
@tmds In general, our policy is to keep patch version updates rolling forward as they maintain strict compatibility requirement of being functional equivalent with their predecessors. When incrementing minor version, we may not be bug-to-bug compatible while still being functionally compatbility. Hence, rolling forward is not necessarily going to work and thus, you see the behaviour above. To target new minor (or major) versions, one will need to consume it using the required tools. @leecow can share more details on this policy and also point to the tools that help buiding apps for 1.1.0. |
Can you clarify what you mean by bug-to-bug compatible? And how this is different between patch and minor increments? |
@tmds @gkhanna79 The only time updated tooling would be needed to target an particular shared framework is if specific functionality were added to the tooling. An example might be additional Linux distro support that did not previously exist. @tmds Our LTS releases are meant to satisfy exactly your long-running scenario. Careful attention is paid to patch compatibility so there can be confidence that your application will continue to work as expected across the entire range of A.B.x updates. Since Minor version updates (what we are calling 'Current') don't have such a strict compatibility requirement, it was decided to not automatically update across this boundary. I believe what Gaurav is referring to with bug-to-bug compatibility is that when an issue is fixed which will target a patch version (eg 1.0.3), the functionality being fixed is also needed in the next 'Current' branch. In some cases, the safest fix to maintain compatibility for a patch version may not be the 'best' fix from a long term engineering perspective. In these cases the fixed functionality may be arrived at in different ways which can lead to behavioral changes. These changes may be acceptable across minor version boundaries but violate the compatibility contract for a path release. |
The LTS releases satisfy the long-running scenario but not the ability to widely deploy. New versions of a distro supported by a new current release won't run your app since new the support is not back-ported to the LTS release. E.g. if your app targets 1.0, it doesn't run on fedora 24 which is now supported by 1.1. So if you want to support these new versions, you need to re-target your app on each current release. Similar when the new distro version drops support for a current release, you have to make sure your app targets one that is still supported. With the current scheme I find it hard to determine what versions a developer should target and what versions a distro should maintain. |
\cc @DamianEdwards |
Picking this up after a week. This issue is about this 1 line in core/support that says:
Because .NET Core versioning uses SemVer, a change of minor guarantees the API to be backwards compatible. I understand that changing a minor may have differences in behavior (e.g. a bugfix on 1.2 which is not in 1.1). And an application may have relied on this behavior causing it to break. So I think the preferable thing to do is to use a minor which matches that of the application. By not automatically picking up higher minor when the matching is not available, both developers and distro maintainers get stuck in a "Write once, Build everywhere". Before netstandard, library developers had to target multiple platforms. Now they get a common API, which may have it's quirks on the different implementations. Similar, it should be possible to target the .NET Core API and accept the quirks that may arise from one minor change to the next. Considering the current approach, what would be your advice to Alice and Bob in a year or so, assuming there are 4 versions of .NET Core: 1.0, 1.1, 1.2 and 2.0.
|
That is already a question i'm about to ask in our next meeting... |
That sounds great in principle, but it doesn't work so well in practice. The .NET Framework has exactly the characteristic you describe and as a result, the degrees of freedom we have with adding new features to it are severely limited. Keep in mind that compatibility isn't a black & white thing: even changes most devs would describe as compatible have resulted in applications not being able to run on the later version of a framework. Let me quote from my blog post:
That's why for .NET Core we want to roll patch changes forward (third digit) while feature additions (major or minor) aren't. |
@terrajobst Totally agree. It's preferable to use the exact minor to avoid these issues. What's your advice for Alice and Bob? |
My advice for Bob is simple: create a self-contained console app. We're also planning in investing more into linker tools so that the app can be tree shaken. In other words, Bob wouldn't run on a shared framework. This allows Bob to use whatever he wants with no external dependencies (besides the OS, of course). For Alice, that's a bit more nuanced. Generally speaking, I'd expect the distros to select the .NET Core versions based on support policies (LTS vs. fast track). |
As far as I understand, this involves Bob to publish against each RID. Which means as distros create new releases, Bob will have to target those as well otherwise his app won't run there. He will also need to package his app for each RID. Since the RIDs he targets have a .NET runtime, he's better off depending on the shared framework and providing a single download.
If you look at Windows of RHEL, it's feasible to build each .NET Core version because your target runtime is not changing often. When support for a certain version has stopped, apps will still run there. If your distro is moving fast, like Fedora or Ubuntu: not building a version of .NET Core (e.g. because no longer supported), means apps no longer run there (because apps don't automatically use the new minor). @terrajobst Let me know if I've missed something. I will close the issue afterwards. |
@terrajobst Is there still something you want to add? Should I close the issue? |
That' correct.
The packaging for self-contained apps is either XCOPY or OS-specific installer/package manager. Sharing vs. non sharing doesn't change that. What does change is the number of outputs for your app.
Whether Bob is better off depends on the goals Bob has: does he care about control of his dependencies? Does he care about being able to use the latest bits? Would Bob prefer an AOT tool chain? Sharing isn't net wise better; it comes with a separate set of trade-offs.
That's fair, but I'm not sure automatically rolling forward is making Alice's life easier or harder. If the distro you're targeting moves fast, then maybe Alice would be better of building the app specifically for that distro, i.e. going down a self-contained path. The assumption you're making is that rolling Alice forward will result in her app to continue to run on the higher version of the shared framework. In my experience, while that's often true, isn't a guarantee. That being said, I don't think there is anything fundamentally wrong with giving the app-author the option to mark their app as "roll forward to the smallest shared framework that my app is targeting". Personally, I'd even be in favor of making this the default with the understanding that this cannot, in principle, be guaranteed to work. The app might depend on bugs in the framework that fixed in the higher version. |
If by this you mean "use a higher minor if the exact is not available": 👍 👍 👍 By doing this, Alice can adopt the strategy of supporting LTS releases and the latest minor release (for each LTS). If Bob wants to minimize the chance of breaking due to automatic minor upgrades, he'll target an LTS release. |
@terrajobst the tools are not following the rules... netcoreapp1.0 tools run on 1.1. |
Looks like this is being worked on in the coreclr/corefx repos. 👍 |
Is there anything outstanding on this issue? |
With recent changes and linux-x64 rid, Bob will sure be happy. Not that much for Alice, however, this will in a way solve her problem as well - because Bob will be able to simply target linux-x64 and publish with all the things included, if they can't keep up with dotnet minor versions. They won't really need any kind of framework installed on the target machine, therefor Alice is not fully responsible for providing it to Bob and can simply go with LTS and latest. |
As a developer, I want to build my app once and have it working on as many distributions possible for as long as possible without having to do anything myself :)
Currently an app for A.B.C will run on A.B.D (D>=C). It would be nicer if it were also running on A.E.F (E>B) if no A.B.D was found.
This will be very annoying when you upgrade your distro and all your compiled apps no longer run because the new version of the distro includes a new "current release" of .NET.
The text was updated successfully, but these errors were encountered: