On Jun 5, 2012, at 6:35 PM, Josh Triplett <j...@joshtriplett.org> wrote:
> [Side note: your mails show up with ridiculously long uwrapped lines, > which makes them harder to reply to.] Interesting, the one in my sent folder is quoted-printable with proper-length lines. The mail that I see from the list server is 7bit instead of quoted-printable, and it has incorrectly long lines that violate RFC2821. I don't know what might be causing that, but I'll do some experiments, thanks. I'm sorry this line will likely appear as "long", but I want to test this message. I'll manually break lines below. >> Take libXi for example, since it's probably fresh in most of our minds. >> With Xi2, libXi added a ton of new functionality and remained backwards >> compatible. Thus, the minor version of the library was bumped >> (http://cgit.freedesktop.org/xorg/lib/libXi/commit/?id=0d19a3ec942aedf5432a9bda1e80f29f7186ce5b) >> from 6.0 to 6.1. >> >> As far as I can tell, though, symbols are not annotated with "available in >> 6.1 and later" so the only difference is the minor version bump, and as you >> said, Linux/ELF essentially ignores this ... so in this case, there is no >> *practical* difference between going forward with an added symbol and going >> backwards with a removed symbol. To make this a bit more clear (words fail >> me, sorry), consider: >> >> case 1: >> libABC.0.0 contains symbols a, b, c >> libABC.1.0 contains symbols a, b >> libABC.1.1 contains symbols a, b, c (c was added back in but not annotated >> as new in 1.1) >> >> case 2: >> libABC.0.0 contains symbols a, b, c >> libABC.0.1 contains symbols a, b >> >> In case 1, libABC.1.1 and libABC.0.0 are identical. Since Linux/ELF >> ignores minor version, there is no effective difference between >> linking against libABC.1.1 and running with libABC.1.0 in case 1 >> compared to linking against libABC.0.0 and running with libABC.0.1 in >> case 2. > > I agree with your statement that from a functional standpoint this holds > true: the linker doesn't seem to enforce the minor version rule, so you > can build against a newer library and run with an older one, or vice > versa, as long as the major version matches. The linker will complain > if you use a symbol that it can't resolve, though. As it should (well unless the symbol is weak and can be checked for at runtime). > Linux distributions primarily want to avoid the scenario in which the > dynamic linker considers a library version acceptable but the program > requiring that library crashes or otherwise breaks at runtime. I think that's a fairly universal concern beyond just Linux distros. > That > doesn't happen with the addition or removal of symbols, because the > dynamic linker will attempt to resolve those symbols and complain if it > can't; in that scenario, the rule of bumping the major version when > removing functions represents a "don't do that" convention to avoid > having users surprised by programs that suddenly refuse to run with a > library that claims compatibility; upgrading to a newer version of a > library with the same major number should never cause existing programs > to stop working. Yes, I thoroughly agree with that, but I also believe that applications built against a newer version of a library should be *capable* of running on older versions of that library (with the same major version) and that API should *almost never* be removed (deprecated yes, removed no) to allow the best portability possible. > In particular, the minor version serves as a hint to the programmer that > if they link against libABC.so.1.1, they might or might not successfully > run against libABC.so.1.0, depending on what symbols they used. IMO, that should be annotated in header files in a way that allows those symbols to be weak linked and checked for at runtime (and thus go down an alternative codepath if unavailable). > On the > other hand, a programmer expects that a program linked against > libABC.so.1.0 should *always* work with libABC.so.1.1, but won't > necessarily work with libABC.so.2.0. Well, it won't *EVER* work with libABC.so.2.0 because the dynamic linker sees it as a completely different library. > Removing or changing symbols > breaks that assumption; adding symbols doesn't. > > Libraries typically introduce symbol versioning to handle more complex > cases that the linker can't catch on its own, namely a *change* to an > existing symbol, such as by adding a new parameter to a function, or > more subtly by changing the layout of a data structure used by a > function. In that scenario, the linker will see no problem, but the > program will break at runtime, precisely as if you cast a function > pointer to a different type with different parameters and tried to call > it (because, effectively, you did). Symbol versioning lets you maintain > ABI (though often not API) compatibility in this case, by having old > programs use a compatibility symbol that knows how to handle the old > calling signature. Yeah, we essentially have that same mechanism in place, usually for cancelable/non-cancelable variants, legacy vs UNIX-conforming variants, changes to 'struct stat', ... > However, the details of how much the dynamic linker enforces and how > much just occurs by convention don't change the general rules for how to > set library major and minor versions: always bump the major version if > you remove symbols or change the meaning of existing symbols. > Exceptions to that rule lead to unexpected breakage, even when > attempting to claim that a symbol doesn't represent public API, and such > exceptions should only occur with careful consideration of the breakage > they'll introduce. I just disagree with this point. If a symbol exists just for internal consumption but is exported (yes, the developer should've used visibility), then I don't believe removing it warrants a major version bump. _______________________________________________ xorg@lists.x.org: X.Org support Archives: http://lists.freedesktop.org/archives/xorg Info: http://lists.x.org/mailman/listinfo/xorg Your subscription address: arch...@mail-archive.com