I may regret throwing my hat in to this ring in the future, but with respect to the example about user downloading $APP and having it not work because it uses $FOO ( linked to libCstd ) and $BAR ( linked to stdcxx ), that would mean that the developer of $APP explicitly linked to both, which is just silly, that $FOO or $BAR changed under it's feet, which would be a different ARC case altogether, or that $FOO/ $BAR had the STL ripped out from under /it's/ feet, and removal of old libraries would be yet another ARC case altogether.
Take care -John On 5-Sep-08, at 4:46 PM, Garrett D'Amore wrote: > Thank you for your instructional description of the C++ language with > respect to templates. > > There are a few significant points, that I think you keep missing, or > are glossing over: > > When I said C++ doesn't separate *binary* interface from > implementation, > I was *not* talking about the nice separation done for the benefit of > the programmer. I was talking about separation done across the > boundary > created by the linker ... AFAIK, C++ does not recognize that there is > such an interface boundary. > > In C++, if an inline function is expanded by the compiler, but makes > use > of *private* members of the class, then the *binary implementation* of > the resulting code is *tied* to the implementation, and if the > implementation changes (e.g. by changing the dynamically linked > library) > then there can be unfortunate consequences. > > I'm not a template expert, so I'll demonstrate with a simple inline > function using C++ circa 1990. > > class box { > int width; > int height; > /* put more private details here... */ > > public: > void draw(); // private implementation elsewhere > > public inline int getwidth() { return width; } > }; > > If this is in header, then the implementation parts (the width, the > height and their offsets within the class) wind up getting encoded > into > the binary that includes this header. If the width or the height ever > move (e..g by moving another member in front of them in the class), > then > the binary is busted. Likewise, if the private members change type > (e.g. from a uint16_t to a uint32_t), breakage ensues. > > It is possible to have implementations that don't suffer from this > problem, but it requires that the implementation refrain from inline > functions, and take care that the headers *only* expose portions of > the > classes that will never ever change (or change in a way that breaks > the > binary implementation of the class.) I won't endeavor to describe how > this problem may or may not affect templates, as such is out of my > area > of expertise. > > I've not kept up with the C++ standards admittedly, but I believe that > this aspect of binary compatibility is not one that has been addressed > in the standards, and likely not in the specification of the > libraries. > It is possible that the Apache product has taken great care to avoid > this kind of potential breakage, but my first reaction is doubt. > > Now, that's only *one* aspect of the "compatibility problem." > > There is a grave and other serious problem, which relates to the fact > that this proposal effectively creates a new baseline (i.e. a new ABI) > for C++ programs, where programs linked (directly or indirectly) > against > this library are incompatible with our one and only bless (at this > time) > ABI, based on the libC that ships with Solaris today. > > And, the project recognizes that future breakage is not just possible, > but *likely*, when either the compiler team ships another project, or > when the library needs an update due to changes in the standard. > > Imagine the plight of the poor user who downloads a program > (WhizzyDownloadTracker) which uses two different class libraries. On > the one hand, it uses the NiftyNetworking library for networking > functionality, and it uses the KDE libraries for user interface work. > Well, good thing, the IPS repo contains both NiftyNetworking and KDE. > Download both, install, and then download, compile (via ./configure) > and > install the WhizzyDownloadTracker. All's good, right? > > Well, a few hours later, when the compile for WhizzyDownloadTracker > finally completes, we find out life isn't so good. > > Because you see, the NiftyNetworking set was not built with the Apache > libstdc++, but instead with the "default" libraries that we have been > recommending people use for years. The user tries to run the program, > and if he's lucky, gets a meaningful link error message. In reality, > the error message, if any, that results is probably completely cryptic > to the end user, who was just trying to install software. In a worse > scenario, the program just dumps core mysteriously. > > The worst part of the above scenario, apart from the confusion that > the > poor non-C++-developing victim gets to experience, is that he's > downloaded the foundation libraries from a single source (Sun's IPS > repo), so they *should* work together, shouldn't they?!? > > Too bad. > > So now the user complains to the FOSS authors for > WhizzyDownloadTracker, > who are unfamiliar with Solaris (they did their development on Linux, > see?), and don't know that Solaris has multiple incompatible C++ ABIs, > nor how to tell which components were built against which ABI. > > So, the FOSS author probably gives up, and tells the poor user that he > needs to recompile the base libraries (either KDE or NiftyNetworking), > so that they are built with compatible libraries. > > At this point, the FOSS author is laughing at Sun and Solaris, and > probably also cheerfully writes a blog somewhere admonishing folks > against running Solaris. > > And, the original user? He's probably given up. Most likely he > either > he chooses not to use WhizzyDownloadTracker, or winds up giving up on > Solaris and switches back to Linux or Windows. Either way he's > probably > pretty ticked that "Sun" is delivering crapware that just doesn't work > together. > > I don't know if the above illustration clearly enough paints the > picture > of my features, but I think it certainly demonstrates that we cannot > just blithely ignore the issue and pretend it won't affect anyone. > > -- Garrett > > Stefan Teleman wrote: >> >> >> Garrett D'Amore wrote: >>> John Plocher wrote: >>>> Garrett D'Amore wrote: >>>>> One of the implications of such a binding (Volatile), is that >>>>> projects which build other C++ shared libraries upon this one >>>>> cannot have a commitment level higher than Volatile either. >>>> >>>> Braap. Bad Architecture Alert. The whole reason we provide >>>> abstractions >>>> like consolidations and components is precisely so that we can >>>> provide >>>> "higher than Volatile" expectations for things that theselves may >>>> exhibit >>>> "less than Volatile" stability. >>>> >>>> There is no reason this couldn't be made a part of the KDE >>>> consolidation, >>>> and maintained by them as Committed interfaces for use by any KDE >>>> consumers >>>> who need it. Volatile means "can change", not "will change", and >>>> both the >>>> Apache C++ Lib and the KDE projects certainly seem to meet the >>>> basic >>>> ARC >>>> expectations of managing the compatible evolution of their >>>> component. >>>> >>>> If the C++ basis that KDE builds upon were to change >>>> incompatibly, I'd >>>> expect KDE to react by producing a major release - again, just >>>> like the >>>> ARC would expect. >>>> >>>> Nothing here requires KDE to be Volatile. >>> >>> We're not talking about something that is delivered with >>> Consolidation Private binding... we're talking about (assuming >>> Volatile binding) something that could change underneath KDE. >>> Such a >>> change would be devastating to binary compatibility for applications >>> linking against KDE C++ libraries. >>> >>> If KDE has a way to shield applications underneath from such a >>> binary >>> breakage, then its a different story altogether. However, my >>> understanding is that in this case (unlike more simple cases >>> involving only C), there isn't a way for KDE to do that. >> >> This ARC Case is not about KDE, but about the Standard C++ Library. >> What KDE may or may not expose in its header files, and how it >> handles >> implementation delegation design patterns is for a different ARC >> Case. >> >>> I.e. with C++ code, if application #include's a KDE header, which >>> itself #include's a libstdc++ header, the binary bits of the >>> application *very* likely contain details of the underlying libstdc >>> ++ >>> implementation encoded in them. >> >> It is the responsibility of the implementation to shield any private >> and potentially incompatible implementation details from the publicly >> exported interfaces. For the purposes of this statement, "interfaces" >> refers to both source and binary. >> >> The principle of separating interface from implementation is one of >> the Design Principles of the C++ Programming Language, and has been a >> C++ software design principle ever since the creation of the >> Language. >> It has been widely discussed and documented in relevant literature, >> and it has also been put in practice by many C++ software systems, >> including, but not limited to, the Apache Standard C++ Library, and/ >> or >> the existing libCstd.so.1. >> >>> C++ is reasonably good at providing good programmatic boundaries >>> between interface and implementation at the *source* code level. >>> However, it falls down completely at the *binary* level. (Which >>> isn't to say that libraries simply *can't* prevent this sort of >>> problem -- merely that the expectation should *not* be that they do, >>> because it will probably require some rather grotesque contortions >>> on >>> the part of the library to do so.) >> >> The private implementation details of any particular C++ software >> system are just that: private. The blanket statement that C++ falls >> down completely at the binary compatibility level is false, and it is >> invalidated by existing software practice. It is indeed possible to >> maintain binary compatibility for a C++ software system, and no >> grotesque contortions are required to achieve this goal. >> >>> Now, if the library (KDE) never #include's "standard" C++ headers >>> (provided by this library) in its own headers (that it exports to >>> applications), but only uses them in .cxx (or .cpp or .C or >>> whatever) >>> implementation files, then I agree that there is no problem. >>> (Although the consuming application may itself still wind up needing >>> to have its own dependency upon the libstdc++, but that issue is >>> largely orthogonal as far as something like KDE is concerned.) >> >> The dependency constraint has already been clearly stated in the ARC >> Case. >> >> Although it is generally considered a poor software implementation >> choice to #include Standard C++ Library header files in application >> header files exporting public interfaces, the implementation of the >> Apache Standard C++ Library allows for this inclusion, without >> breaking ABI [ pursuant to the compatibility constraints described in >> the ARC Case Materials ]. However, the Language allows for the >> implicit inclusion of interfaces from the Standard C++ Library [ or >> for that matter, any other library ], in header files, without the >> need for explicit #include directives. >> >> The Library incompatibility constraint is still in effect: the Apache >> Standard C++ Library is not compatible with: >> >> - any implementation of the Apache Standard C++ Library, which is not >> at Major Release 4 level >> - any _other_ implementation of the Standard C++ Library, including, >> but not limited to: libCstd.so, the GNU Standard C++ Library, >> STLport, >> etc. >> >>> To put this in comparison, imagine if almost all of the standard C >>> functions were simply *macros* rather than functions, and the macros >>> made references to volatile innards of the C library. While the >>> *API* might be "clean" and safe, the *ABI* would most certainly not >>> be. This is the situation that we're in with C++, I think. >> >> Intentionally, and by Language Design, C++ inline functions, or >> templates (which is what you are referring to) are *NOT* C macros. C >> ++ >> inline functions are functions. C++ templates are templates. Their >> symbols are mangled, they obey all the language overloading rules, >> they are assigned the implicit "this" pointer by the compiler (if >> they >> are class members), and they behave exactly in the same way as any >> other C++ function. They [ classes ] also implement a distinct type. >> >> The complexity of the implementation of C++ functions increases in >> the >> case where the class, or function in question, is a template (which >> is >> the case with the majority of the classes in the Standard C++ >> Library). If the class is a template, the compiler instantiates a >> distinct type, based on the type defined by the class template >> itself, >> and on the underlying type upon which the template class is >> instantiated. This instantiation mechanism alone is fundamentally >> different than that of C macros. >> >> The type instantiation mechanism applies to non-template functions >> and >> classes as well. >> >> The compiler may or may not decide to eliminate the function call >> altogether, by inlining in the resulting object file, and this is a >> private decision of the compiler. The compiler may or may not decide >> to eliminate the instantiation of the template [ class or function ] >> altogether, based on internal compiler heuristic rules, and/or based >> on whether or not the actual template function or template class is >> actually referenced in the translation unit [ the default compiler >> decision can be overridden with specific compiler flags, but that >> facility is besides the point for this discussion ]. This decision, >> again, is a private decision of the compiler. >> >> At this point, your comparison with C macros has fundamentally broken >> down: there is no guarantee whatsoever that any of the template >> classes or functions, whose interfaces have been imported by the >> translation unit via header files, would have actually created the >> required type and its corresponding instance, and/or that the >> compiler >> has, in fact, generated the corresponding symbol(s) in the binary >> object. >> >> The means by which the implementation achieves the asserted ABI >> compatibility goal is private to the implementation itself. In this >> particular case, under discussion, this compatibility is enforced by >> function calls to private, internal implementations of the facilities >> required by the Language Standard (hence the presence of the shared >> library object). >> >> Attempting to invalidate the ABI compatibility assertion of the >> implementation by drawing comparisons with C Language macros, or with >> the C Programming Language in general, is based on incorrect >> assumptions about the C++ Programming Language, and is bound to fail >> scrutiny. >> >> I am hereby requesting that the PSARC member who has derailed this >> case provides concrete proof of ABI breakage in the Apache Standard >> C++ Library, to the PSARC Committee, for review. Concrete proof >> means: >> source code, accompanied by an explanation of the breakage. >> >> For The Record: KDE has no intention whatsoever to modify the >> Standard >> C++ Library in an incompatible way. >> >> Thank you. >> >> --Stefan >> > > _______________________________________________ > opensolaris-arc mailing list > opensolaris-arc at opensolaris.org