Re: Discussion about why GNU/Linux system upgrades cause old programs to break
Jeremy Bryant <[email protected]> Tue, 11 Aug 2026 23:48:05 +0100
| Newsgroups | gmane.emacs.devel |
|---|---|
| Message-ID | <[email protected]> |
Thanks Arsen for explaining lots of detailed technical points, it is interesting reading. I have a few questions interspersed below. Arsen Arsenović <[email protected]> writes: > Eli Zaretskii <[email protected]> writes: > >>> > What happened was a system upgrade. I don't expect a system upgrade >>> > to remove capabilities. Am I alone in this expectation? I agree this is a reasonable expectation. >> My point is that at least in some cases we decide "not to solve" this >> too soon. We could do better. Having a program break 25 years after >> it was built is much better than if it stops working after 5, I hope >> you agree. > > Absolutely, some such cases happened; I listed one such case above. There is more agreement that a program should continue to work for a longer period of time than sometimes it currently does. > >> You are talking about programs that are part of the OS. By contrast, >> I'm talking about programs that were built by the user -- those are >> not upgraded when the system is, and one of the worst effects of a >> system upgrade is to see programs which worked for you for years >> suddenly stop working. > > No, I'm not. > > My paragraph was worded a bit poorly, let me restate what I stated > above, and expand on it: > >>> The system vendor (be it Apple or Microsoft or Google or whoever) >>> simply ships you, the developer, a set of dependencies dated to, say, >>> some year, so you end up seeing breakages when you change which date >>> the system-vendor-provided dependencies attach themselves to, because >>> you, the developer, are the one acting as an integrator for the vast >>> majority of the dependencies, and your own code, with the >>> vendor-provided code. >>> >>> The users end up not seeing this at all because each program gets >>> distributed with nearly all dependencies, with the ones distributed >>> as part of the OS being installed multiple times. > > These system-vendor-provided dependencies are equivalent to the "core" > GNU system: GCC runtime libraries, glibc, coreutils, GTK2/3/4 (at some > point at least), etc. These are in that year-versioned bundle that I > was referring to, that gets installed a few times on each users' system. > > The dependencies outside of these, however (say, libjpeg or > tree-sitter), are integrated by the developer, and get shipped with the > program. > > So, when any of these dependencies - whichever category they belong to - > change, builds break *for the developer*. The user doesn't notice, > because it was made the developers' problem. The user just gets a ton > of binaries, with all the parts epoxied together. > > But the user in our case is given source-code, and the freedom and > compulsion to vary dependencies. Exactly as the developer was in these > alternative models. The user becomes the integrator. > > It is not possible to avoid breakages as a result. > > Great effort is already taken to avoid them, yet they still happen. > >>> (those who have used MS-w are aware of "VC++ Redistributable XYZW" - or >>> whatever the name was - which they have to install on occasion for >>> various XYZW). >> >> That's just a packaging issue: those redistributables should have been >> bundled with the program that needs them, but could not be due to >> copyright issues and such. The important part is that, once you do >> have the redistributable installed, no system upgrade will remove it. > > I'm not sure whether a MS-w upgrade by a major version would remove > them. > > But, even if not, they're the exception to the rule on that OS; most > dependencies are shipped with most programs, thus they're mostly > isolated from each-other. > > Which is its own mess, of course (tried using TeXLive and Inkscape > together through svg.sty? what a mess..). > > The issue we're discussing is also a packaging issue, though; programs > in the Linux and BSD and ... ecosystems generally don't get distributed > in binary form with all of their dependencies built in, they get > distributed in source form, without dependencies. > > Whereas programs in the ecosystems I refer to above are all distributed > in binary form with nearly all of their dependencies bundled. > > The former means that the same sources are expected to work with a > myriad of combinations of various dependency versions. > > Obviously, the developer testing them all is unfeasible. Especially as > many of those combinations do not yet exist at time of writing. > > Thus, problems arise sometimes quite late. > > This is where compiler laxness comes into play. I'll return to this > below. > >>> This is also why many cling to static linking. >> >> Static linking is a two-edged sword: it could be more robust in the >> long run, but in the shorter run you lose the ability to easily update >> a dependency library if and when its developers fix some grave bug in >> it, without the need to rebuild your application. >> >> Most programs nowadays use dynamic linking, IME. > > There's other problems with static linking also, but, yes, most programs > are dynamic linked nowadays. > > What I was saying is that there's a contingent of developers who cling > to static linking as a solution for the problems you lie out in this > thread. > > Which are real problems. But they aren't problems solvable at the > source level, or even at the binary level. We still try to, though. > > The solutions in the ecosystems I referred to above are far closer to > static linking (because you can't really independently update components > as the user) than what we usually do in the Linux and BSD and > ... ecosystems. > > You can't have your cake and eat it, too. You either allow varying > dependencies and thus have breakages, or you don't, and everything works > (you even get gratis bugs because you can't independently fix them). > > I think we've largely made the right choice. The free software world > permits anyone to fix problems that arise as a result of Hyrum's Law, > and we're able to integrate masses of code written by many thousands of > people and work on them collaboratively. > > But, this does mean that the constraint of "unmodified program works > indefinitely" is impossible to satisfy. Arsen, do you have a suggestion for improving the longevity of Emacs source? Are you suggesting it amounts to forms of more 'static linking'? Should it be something to recommend to distros (Gentoo, Debian/Trisquel, ...) ? Would there be a subset of dependencies such that there is greater longevity anticipated for, by way of illustration, Emacs compiled without GTK. Namely, a subset of e.g. terminal-based Emacs? >>> > One example of this is compiling a program that used K&R syntax. >>> > E.g., Emacs switched to C90-style function definitions only in version >>> > 24.1, which was released in 2012. All the older versions used K&R >>> > syntax; they are now "broken" by your definitions, and cannot be >>> > easily compiled. >>> >>> Well, yes, if Emacs versions up to 2012 were telling the compiler that >>> they were C99 programs, but were not valid C99, they were certainly >>> broken, and only worked due to a defect in GCC. >> >> See above: that's not what happens. In reality, the build invokes the >> compiler without specifying the dialect, so whatever is the default C >> dialect is being used. So when the default changes to be >> backward-incompatible, it's bound to break old programs. > > Indeed, the default dialect can change. This is why I find the > autotools choice to only provide -std=... conditionally dubious. Do you have a suggestion to improve this? >>> I've argued before, and stand by it now, that source-level backwards >>> compatibility should not be the default for compiled languages. When a >>> compiler is present, it should only be backwards-compatible if told to >>> be explicitly. >> >> This makes recompiling old sources harder, so I think it's a mistake, >> unless we don't care about these case. > > I'm sure many more hours have been spent tracking down stuff that > could've been prevented by stronger diagnostics than have been spent > trying to compile old code. > > I do not mean to imply that backwards compatibility is a "sin". But, > backwards compatibility in this instance means relaxing compiler > diagnostics, thus making the compiler less strict. This is universally > a disservice to users. I've went over why earlier, but I can restate it > in brief again: anything that can be caught early but isn't harms > everyone, including program authors and users. > > There are two different classes of users of compilers: program > authors and program users building the source form. > > The former is harmed, substantially, by such default laxness, because > they're enabled to write programs that are slightly wrong. The latter > receives some slight relief from default backwards compatibility. > > But, this is a Pyrrhic victory for the latter: as a result of default > backwards compatibility, rather than fixing defects in an early versions > of programs, those defects go unnoticed are kept around long enough to > break in more insidious ways later, blowing up in the users' face. > > Indeed, the case I showed in my last email with 'reallocarray' was > exactly such a case: the user of flex "benefited" from default backwards > compatibility, only to get a program that was slightly broken under > specific conditions. > > Luckily, in that case, the breakage manifested as an easy-to-find crash. > In many cases, it will manifest as a rare and difficult to diagnose > runtime bug. > > Meanwhile the developer of flex was left unaware of this breakage for a > longer time. > > It was a disservice to both classes of users to postpone or entirely > omit diagnostics on code that GCC knew was very likely to be wrong. > > The driver behind the GCC 14 change was not that anyone else decided to > do it (though arguably Clang doing it acted as a trigger), it was that > we've been fixing related bugs for many years in many programs, and that > we've been teaching students that "this code is not correct but the > compiler ignored it because old code exists, but you shouldn't ignore > it" (to very little effect). Arsen, do you have more ideas on how to make recompiling old Emacs sources specifically have greater longevity than at present?