Garrett D'Amore wrote: > John Plocher wrote: >> Nicolas Williams wrote: >>> It would be >>> nice if we could avoid revisiting this every time a project comes along >>> to integrate some C++ library. >> >> We already have a stake in this sandbox: >> >> Don't use g++ to build/deliver C++ libraries on *Solaris, >> period. Use Studio's C++ instead. > > Oh, cool! Do you happen to know offhand what the case number for that > opinion would be?
LSARC 1993/550 C++ ABI LSARC 1992/026 tools.h++ PSARC 1993/071 Bundling libC.so with Solaris BestPractices/ToDo/20q.C++Guidelines.html has a dated but still valid take on this topic. (Sorry, not out on OS.o, included here for now...) --------------------------------------------------------------------------------------------- Software -> C++ Guidelines --------------------------------------------------------------------------------------------- Background ARC cases for C++ LSARC 1993/550 C++ ABI This case has a specification and an opinion, but the opinion is not yet finalized (at this writing). The C++ Object Binary Interface (OBI) has been split out of this case. LSARC 1992/026 tools.h++ PSARC 1993/071 Bundling libC.so with Solaris --------------------------------------------------------------------------------------------- Advice LSARC Guidelines for Products Using C++ Language Revision: 1.0.3 of July 22th, 1994 Drafted by: Dean Stanton, Evan Adams, Don Woods HTML conversion: John Plocher 1.0 Problem Description LSARC found it necessary to provide guidance to Sun software developers who are considering using the C++ language. Indeed, many Sun groups are already developing in C++, and encountering compatibility problems. C++ has become a widely-used implementation and interface specification vehicle. And yet the C++ language lacks a stable ABI (Application Binary Interface) standard; no two compiler releases (from SunPro or from other vendors) necessarily have compatible binary forms for binary layout of objects or function calling sequences. Hence, the calling sequences generated by one compiler are not guaranteed to be compatible with those generated by another brand of compiler or another major release of compiler from the same provider. And an interface implemented by one compiler may not be usable (or may not function correctly) when invoked by compatible source code compiled by another compiler. An additional binary-compatibility problem plagues software libraries (whether statically linked, dynamically linked, or dlopen-ed): binary object layout is affected not only by the specified description of the object, but also by the private data included in the class (in the header file used at compile time). A library interface specification should be independent of its implementation, so that a revised implementation may be substituted (say, in a later library software release asynchronous to the application), and still function correctly. Most developers address this now by wrapping an interface-only class around the implementation class. This problem may eventually be solved by the C++ Object Binary Interface (OBI) project[Reference 1]. Alan Sloane calls it ``evolution'', and an earlier C++ ABI document addressed it with extern "shared". These Guidelines collect in one place the committee's requirements and advice on using C++, and call out details related to libC, the C++ library. The cfront-based C++ library is bundled into Solaris, starting with 10/93. But each libC is useful only to compatible compiler releases. 1.1 Compiler Background Information The following table presents the current status of SunPro C++ compilers, and their matching C++ libraries. It also shows conjecture that the next release will likely be binary-incompatible with SPARCompilers 3.x, but conforming to a hopefully-standard-and-stable C++ ABI. This ABI is the subject of LSARC case 1993/550[1]. Workshop C++ Release Base libC Dynamic C++ Library C++ Library first Release Number Number Technology Version Bundled 2.0.1 3.0.1 cfront libC.so.3 2.3 (10/93) ``all''[2] 3.0 4.0 cafe compiler libC.so.5[2 2.4 (4/94) ``end-user'' 3.0.1 4.0.1 caf' compiler libC.so.5[3] 2.4.1? ``end-user'' 4.0? 5.0? caf' + ABI[1] libC.so.6? (No Guess) 1.2 Binary Incompatibility Due to Build Platform Solaris 4/94 fixes bug #1091835 by changing a declaration in <sys/types.h> from: typedef enum boolean { B_TRUE, B_FALSE } boolean_t; to: typedef enum { B_TRUE, B_FALSE } boolean_t; to become POSIX-conformant. Unfortunately, the presence/absence of the enum tag affects the C++ name-mangling of function arguments (etc.) involving boolean_t. The mangled name will differ when compiled with pre-4/94 header files, versus 4/94 and later (including the Solaris Developers Conference CD), when using either cfront or caf'. A C++ interface compiled prior to Solaris 4/94 involving boolean_t will be callable only when compiled using a copy of sys/types.h with boolean reinserted, on 4/94 or later. However, distributing such a header file will run up against the PSARC packaging rules[2]. Users may need to be instructed to build their own. They must not build theirs in /usr/include/sys, however, because their system would then be incompatible with POSIX and modern C++ interfaces. 2.0 Introduction to the C++ Guidelines It is critical to differentiate C++ implementation (which may be used to implement a C interface, for which there is a stable ABI) from C++ interfaces (which lack a stable ABI). C++ interfaces are discouraged, but allowed, subject to restrictions specified in these Guidelines. This includes imported C++ interfaces as well as exported. Example imported C++ interfaces are the C++ utility classes from RogueWave, known as Tools.h++[3], and the C++ library itself, libC. There were several issues discussed, some specific to C++, and others dealing with dynamic-linking, compiler revisions, and other topics.[4] The committee discussed many possible differentiators: * Using C++ only for implementation, versus for interface specification * Bundled versus unbundled products * Applications versus libraries * Dynamic (shared) libraries versus static (archive) libraries The committee decided that most of these choices affected only detailed advice and brought up discussion of ancillary issues. Nonetheless, to make these Guidelines more useful, applications are presented separately from libraries. 3.0 Applications May be Implemented in C++ An application development team may use C++ internally, as long as it does not offer any C++-based interfaces. An application commonly has no programming-language-based interface at all, using only a CLI or GUI and non-language-specific file formats. C++ application developers face the following issues: 1. They must ensure that the proper version of libC is available or they must avoid the need for libC. (See section 1.1.) 2. They must ensure that the proper version of any other libraries written in C++ are also available. 3. It is very difficult to use multiple C++ libraries if they have been compiled with different compilers. 3.1 Applications and libC A program written in C++ will, by default, be dynamically linked with libC, the C++ runtime library. This library implements the new and delete operators, the I/O streams routines, exception handling, etc. Therefore, these programs need to have the appropriate libC available at runtime. Section 1.1 shows which C++ libraries are bundled with which Solaris releases. Applications built with a C++ compiler whose library is bundled may depend on the bundled C++ library. If the application does not need to run on prior Solaris releases, then its developers need not worry about C++ library access, except perhaps which clusters must be installed. 3.1.1 When Applications Cannot Depend on the Bundled libC Applications cannot depend on the bundled libC in the following cases: Bundled Products if the libC needed by the compiler you used is not bundled (yet). Unbundled Products if the product supports earlier Solaris releases, previous to those that bundled the libC needed by the compiler you used. Such applications must ensure that the proper version of libC is available. This can be done by co-packaging libC, statically linking with libC, or eliminating the dependency upon libC. 3.1.2 Co-packaging libC.so An unbundled application that needs libC may include the package that contains libC. The package names are SUNWlibC for SC3.x and SUNWlibCf for SC2.x. These packages are now available as patches: 101242-03 for SUNWlibC and 101246-02 for SUNWlibCf. The README file of C++ 4.0 contains information about these patches. Any unbundled product can ship these patches on their CD. 3.1.3 Linking Statically to libC is an Option An application product that chooses to link statically to the appropriate libC would use the -nolib option, as described on the appropriate CC(1) manpage, like: CC -o mycommand my.o other.o -nolib -lsunmath -lm \ -Bstatic -lC -lC mtstubs \ -Bdynamic -lw -lc The trick is to get libC static, but libc dynamic. (The compiler driver adds both of these libraries for you automatically, so it is difficult to find the correct spot for -Bstatic; the -nolib option asks CC not to add in the libraries.) 3.1.4 Eliminating the libC Dependency Projects that wish their C++ implementation software to run on systems prior to the bundling of the matching libC may avoid dependency on libC, as described later for libraries. In this way, their application or library doesn't need to find libC at runtime. 3.2 Unbundled Dynamic Libraries are Problematic, Independent of C++ If an unbundled application[4] depends on an unbundled dynamic library (with a C++ or any other interface), the proper install location for the dynamic library is /opt/some_path/lib, and the application must assure the library is found at runtime. This is typically achieved with the -R link option (or LD_RUN_PATH), with the LD_LIBRARY_PATH environment variable as a last resort. If the package containing the library must be installed somewhere else, system administrators may need to 1. mount the package onto /opt/some_path on each target machine on which the application may be run; or 2. make /opt/some_path a symlink on each target machine to the installation location; or 3. set the users' LD_LIBRARY_PATH environment variable, for each user of the application, perhaps via scripts similar to /usr/dist/exe's. LSARC would welcome a proposal for a better solution, such as including some centrally-administered places into the list of locations automatically searched for dynamic libraries. (Below, there are additional guidelines on delivering dynamic C++ libraries.) 3.3 Multiple Libraries using Different Compilers One awkward case to consider is an application that depends on two or more libraries with C++ interfaces: one that exists only for an older compiler, and one that exists only for a newer compiler with incompatible calling conventions. The C++ calling convention can be side-stepped - for example, using C wrappers. But even then, if the libraries require incompatible C++ runtime libraries, they cannot be co-resident in one process. To build such an application requires sophistication, if it is to be performed at all. Techniques we've identified are: 1. Use two processes, one compiled with each compiler. These could use compiler-independent IPC to communicate. 2. Use a C-callable (i.e., stable-ABI based) ``wrapper'' layer, as described in Appendix F of reference [5], between the portions of the application compiled with each compiler. Even if the two portions did not depend on incompatible libC runtimes, there still might be problems with call-back functions or exceptions, which depend on C++ call-stack details, Because of these problems, option 2 is not recommended. 4.0 C++ May be Used for Library Implementation We first consider the case that is easy to permit: A library development team may use C++ internally, as long as it neither exports nor imports any C++ interfaces, including libC. Generally, this means the library exports a C-callable interface, but sports a C++ implementation. Importing or exporting any C++ interface ties the library to a particular C++ compiler until a stable ABI exists. The dependency on particular C++ calling conventions and/or runtime libraries lead to restrictions on applications using the library, as discussed in section 3.3, even though the C calling sequence is compatible, because the other side of the C++ interface might use a different compiler, and the two runtimes might conflict. See section 3.3. 4.1. Avoiding libC is an Option Projects that wish their C++ implementation software to run on systems prior to the bundling of the matching libC may avoid dependency on libC. Another reason to avoid libC is that a client - even of a library's C interface - may be using C++. If the client wants to use a different compiler and libC from the one the library needs, the two C++ libraries would conflict. The same could arise if the client wanted to use two libraries implemented in C++ that needed different libC versions. Avoiding library dependency on libC is encouraged, but it is difficult to assure that no C++ interfaces are imported. No real tools exist to verify lack of libC importation. Until additional guidelines are provided to help programs avoid accidental dependencies on libC, avoid the following libC features: 1. C++ I/O streams (perhaps use libc I/O instead). 2. C++ exceptions (try, throw, and catch must be avoided - use explicit arguments and tests instead). 3. new and delete operators. Supply class-specific new and delete operators instead.[5] 4. new[], and delete[] operators. Classes cannot provide their own implementations for these array operators; therefore, these operators must be avoided. Do not use arrays of classes in any context - static, automatic, or in a structure; these use library routines to implement construction and destruction. Instead, use arrays of pointers to the objects. Re-implementation of libC public entry points is strongly discouraged, due to support problems of multiple implementations. Any exception would require justification and explicit ARC approval. 4.2. Avoid C++ Exposure in C Interfaces Libraries with C++ interfaces incur additional problems (and hence additional restrictions imposed by these guidelines). In using a C interface and a C++ implementation, care must be taken that no C++ interface sneaks in. Pointers to C++ objects may be handed across a C interface (as an opaque handle), but only the library that produced the pointer can interpret (dereference) it. 4.3. Conventions for Naming Library Symbols The committee regrets that there is not a widely disseminated naming conventions document. The only naming conventions document we know of is from 1987[6], which is pre-C++. A summary is presented here, along with application to C++. When C++ compilers support the namespace feature, we will need additional conventions for their use. 1. All external symbol names in a library and in its public header files should begin with a prefix (e.g., dbm_ or Dbm).[6] In C++, these are symbols that could be referenced with the :: scope resolution operator. A large library may use a handful of prefixes, or sub-prefixes (e.g., dbm_core_ and dbm_util_). C++ class names are external names, and should be prefixed. C++ members, including methods, are effectively prefixed with the class name by the compiler, and therefore do not need special naming. Names that need not be external may be static instead of prefixed. 2. typedef, struct, and enum names, enum tags and constants should all be prefixed, if they have file scope. If these names are scoped within a C++ class, they do not need special naming. Macros should be prefixed, as well. For example, use DBM_MAX_LENGTH, not MAX_LENGTH nor MAX_DBM_LENGTH. Each header file should have a single prefix; multiple header files for the same library may share the same prefix. 3. These prefixes must be documented, so that clients avoid any accidental use of them. 4. Functions or global data symbols that are private to a package must have a prefix that begins with an underscore. The naming convention would also mandate case, underscores, and conventions such as _t (for types) or _H (for header-file guards), which aren't addressed here, but are addressed in the Project DOE C++ Programming Style Guide[7]. While this Style Guide is not universally accepted, PSARC/1992/075 mandated that future Ivy and Trellis C++ interfaces be defined in accordance with this Style Guide. Deviations from the Style Guide in C++ interfaces (but not in implementation) should be pointed out during ARC review. Project DOE intends to update the Style Guide and obtain ARC approval for the new C++ style guidelines. After ARC approval, these guidelines should be used by projects unless the project gains an ARC exemption. 5. Libraries that Export or Import a C++ Interface are Restricted In addition to sharing the problems listed above for C++ implementations, until a stable ABI exists, importing or exporting any C++ interface ties a library to a particular C++ compiler. One notable C++ interface commonly imported is libC. (See first footnote.) 5.1. Precedent - Libraries with C++ Interfaces are Strongly Discouraged until the ABI is Stable In consideration of the restrictions that follow, LSARC strongly discourages libraries from importing or exporting C++ interfaces until C++ compilers offer a stable binary interface. Reasons that a C++ interface might be justified include: 1. Needing client extensibility via subclassing. 2. C++ interface specified by a standard, such as OMG CORBA. 3. Library is intended specifically to support users of C++. 4. Software purchased to fill a need happens to have one or more C++ interfaces. 5.2. Sentiment for Forbidding C++ Interfaces Before ABI is Stable Some committee members wish to forbid libraries with C++ interfaces until there is a stable C++ ABI. The majority, however, feel the risks and advantages may be weighed as a business decision, as long as the architectural limitations are known. The following sections describe restrictions that apply to libraries with C++ interfaces. 5.3. Precedent - C++ Interfaces Could be Classified Public Due to the lack of a C++ ABI, a C++ binary interface might be modified by changes to the compiler, even if the source-code-level interface is stable. Therefore, a project shipping a library with a C++ interface should plan to ship multiple versions of that library for use with different compilers[8] due to market considerations.[7] If this is understood by the project team and steering committee, such an interface could be classified as Public or Standard. These considerations also apply to libraries or applications using a binary interface based on the C++ compiler. Shipping source code might be a reasonable alternative prior to the ABI for a utility library not intended to be used by other libraries. 5.4. Linking Multiple libC Instances is Discouraged When faced with the situation of two pieces of code each requiring a different version of libC, it was deemed impractical to link in both versions of libC and expect things work correctly. While the name-mangling of the different compilers should not conflict, the implementation of the two instances of libC are very likely to conflict. Therefore, a library using libC will be unusable by applications using an incompatible C++ compiler and unusable in the same process as any other library using a different compiler's libC. This may unreasonably limit the library's potential market. 5.5. Libraries Must Not Link Statically to libC As section A.3 explains, both static and dynamic libraries must link dynamically to libC or avoid dependency on it entirely. 5.6. Precedent - Conventions for Naming Libraries with C++ Interfaces To ease support and use of multiple versions of a library offering a C++ API, LSARC requires the following naming convention of such a library. Any exception should be explicitly approved by the appropriate ARC. 1. A brief substring indicating the compiler's binary interface should be established by the compiler vendor and shared by every library offering a C++ API that uses that compiler (or one with a compatible binary interface). One example is ``-SC3'' for SPARCompilers 3.x. SAC should know what strings have been established, and assure that only one string is used for each ABI. The stable, standard C++ ABI (once available) could use the null string. 2. This string must appear in the library name. Following the example, a library might be named ``libfoo-SC3.so.1''. There may be a symbolic link without the version number suffix which points to the latest compatible version of the library (``libfoo-SC3.so -> libfoo-SC3.so.1'' in the example), but there must not be a symbolic link without the binary interface substring. The rationale for this requirement is that users of a library with a C++ interface don't want the ``latest''; they want one compatible with their compiler. 3. Users will be instructed to link with the library name including the binary interface substring. If ``-SC3'' is the substring, users might link with -lfoo-SC3. Using this scheme, a customer could switch library versions in an obvious way when upgrading to a newer compiler. A single Makefile edit could change all libraries. (That is, the user might represent his library references using -lfoo${CPLUSPLUS_ABI} -lbar${CPLUSPLUS_ABI}.) The committee requires this convention for static libraries, as well, so that dynamic and static libraries (if they are ever both offered) will share the same ``root name'' (prior to the .a and .so suffix). 5.6.1. Discussion of Library Naming Convention The convention applies to libraries with C++ Application Programming Interface (API). XGL 3.x and XIL 1.x have C-callable APIs, but C++ System Programming Interfaces. They need not adhere to this naming convention. They may use other versioning techniques to determine whether hardware-specific libraries with C++ interfaces are compatible with the library. The rejected alternative is to merely use library ``version numbers''. (The filenames of the two libraries based on different compilers must be different, so they can be present simultaneously.) The version number would be bumped whenever the binary interface changed. This is either because the source-level interface changed or because an incompatible compiler created it. LSARC notes that the bundled libC chose this alternative. In fact, the naming convention in section 5.6 above came from Chuck McManis' Minority Opinion of the PSARC opinion on bundling libC[8]. The committee rationalizes that libC is a special case because it is not generally mentioned in Makefiles. (It is usually added implicitly by linking via the CC compile driver.) The advantage of the new convention is that library version numbers are still available for identifying source-level compatibility. A filename ``namespace'' separate from the library version number indicates a compiler binary interface version. Library users need not remember which library versions are compatible with their specific compiler; this information is visible. The contrary arguments were that version numbers alone are adequate, few developers are likely to use multiple libraries offering C++ APIs, and that libraries have other distinguishing characteristics (such as MT-safeness and standards-compliance) that are not apparent in the names; names can't encode all library properties without being unwieldy. The committee favored the new convention nonetheless. 5.7. Precedent - Packaging Convention for Libraries Exporting a C++ Interface Projects which have libraries exporting a C++ interface should deliver such libraries in a separate package from non-C++ components, at least until there is a C++ ABI. Any exception should be explicitly approved by the appropriate ARC. It is acceptable for multiple C++ libraries depending on the same compiler to be co-packaged. The rationale for this requirement is that future product releases will likely add libraries for newer compilers, and ``sweep out'' libraries compatible with old compilers to a ``backwards-compatibility'' cluster, deem the old versions Obsolete[9], and eventually remove them completely. Separate packages are good for things we intend to someday ``sweep out''. 5.7.1. Discussion of Packaging Convention The general packaging guideline is that organizing files into more packages is more flexible. Projects should group packages into small clusters, so that the user doesn't have to select every (tiny) package one-by-one, but can select the appropriate cluster instead, killing multiple birds with one stone. The overhead of creating additional packages is a small amount of disk space, and a small packaging-engineering effort. These effects are minor. Files on which the library depends or vice versa need not be co-packaged. Listing the dependent packages is sufficient. 5.8. Bundled Libraries with C++ Interfaces Any bundled dynamic library with a C++ interface must continue to provide a version of the dynamic library compatible with the same compiler binary interface ``forever''.[8] Such a project must get explicit approval from their steering committee before integration. This approval should consider the issues of multiple versions of the library, one for each binary-incompatible version of C++: * Customer Support for multiple versions. * Maintenance and patching of multiple versions. * Disk consumption (on both distribution media and customer disk) of multiple versions. Static libraries might not need to ship old versions of the library ``forever,'' because each application is compiled only with the correct compiler, and is linked with the matching library, after which no runtime library compatibility problem occurs. Nonetheless, there is likely a business case to ship multiple versions, because a portion of the customer base might not be ready or willing to update to the newer compiler release. If a bundled library needs a version of libC, the appropriate dynamic C++ library would need to be bundled. 5.9. Unbundled Libraries with C++ Interfaces Unbundled dynamic libraries might not need to provide a version for the same compiler binary interface ``forever'', because the ISV already has the responsibility of redistributing the library along with the application to all end-users, and a new version of the dynamic library using a newer compiler doesn't change that. Any single application would be compiled with only one compiler, and need to be delivered with only the matching dynamic library. However, multiple versions of any library with a C++ interface might still be needed as a business decision, even for compilers older than current when the library is released. Otherwise, customers who have paid for an older compiler would be unable to use it to invoke the (newer) library. See the issues in the preceding section. An unbundled (static or dynamic) library product that depends on libC may need to ship the appropriate libC if the product supports earlier Solaris releases, previous to those that bundled the libC needed by the compiler you used. 5.10. Interfaces Based on C++ Templates Templates are expanded at compile time. Therefore, the expansion of the template becomes part of the binary interface based on the template source interface, and must not be changed between releases without ARC approval. Templates are equivalent to macros in this respect. Developers should also be aware that multiple generated template expansions could bloat a product. Appendix A: Additional Advice Regarding Dynamic Libraries The following sections provide additional information about dynamic libraries, that is not specific to C++, but may not be widely known. See reference [10] for more information. A.1. Dynamic versus Static Library Performance To oversimplify the performance ramifications, a single application will run slightly faster when statically linked to its support library or libraries. This is partly due to avoiding runtime relocation and indirection, and partly due to compilation for absolute addressing, rather than Position Independent Code (PIC). However, multiple applications can all share the text segment of a shared library, which reduces their size (on disk and in memory), and can avoid page-faulting because some other process has brought in the pages of the shared library text that this application needs, or by using them has kept them from being paged out. This means overall system performance is generally increased by use of dynamic libraries. Hence, for any library expected to be used by more than one process at a time, shared/dynamic libraries are preferable from a performance standpoint. Any such library should be shipped either in dynamic-library form, or in both dynamic and static forms. A.2. Unbundled Dynamic Libraries Unbundled dynamic libraries are problematic, even without use of C++. Both the application and the dynamic library must be provided to its end user, and both must be addressed at runtime. This can't presently be simply handled for the end user by a system administrator, because the application and dynamic library are typically installed on a single server, and then shared by many end users on multiple ``execution'' hosts. It is unfortunate that dynamic libraries are problematic, because a good shared library implementation is one of Sun's value-added strengths. The performance advantage of sharing libraries and the added flexibility of runtime linking in some cases outweighs the distribution problem and the hazard of being unable to locate the dynamic library at runtime due to inadequate installation or incorrect configuration. We impose the following guidelines for unbundled dynamic libraries, whether C++ is involved, or not: 1. The library or libraries must be distributed in a separate package of their own[9], so that multiple applications could distribute them. The installation directory for this package need not match the package name, nor contain the libraries from only a single package. But the directory name should be owned and managed by the provider/owner of the shared library. 2. Use of ld's -R option (or the LD_RUN_PATH environment variable) must be recommended for use by developers of software importing the library or libraries, so that end-users need not use LD_LIBRARY_PATH (if installing everything normally). See section 3.2. A.3. Libraries Must Not Link Statically with Other Libraries Libraries must not statically link in subordinate libraries that anyone else may use in their application. This causes the resultant library to assume the dependencies of both libraries. This issue is not specific to C++. ARC members have seen this problem without involvement of C++. If a dynamic library D links statically to any static library S, only the portions of S used by D are inserted into D. If an application A uses D and also some additional portion of S, the portion of S inserted by D may not be of the same revision as the portion of S inserted by A. The two portions of S may not share compatible internal (e.g., project private) interfaces, and therefore may not work together. This can be very difficult to detect and debug. This comes up when C++ library developers try to solve the libC unstable-binary-interface issue by statically linking in parts of libC. The implementation of libC included by the portion of libC brought in statically at link time may be incompatible with the implementation of additional portions of libC brought in by an application (or another library) implemented in C++, even if they have binary-compatible external interfaces, due to revised implementations. If the functionality is only present in an archive library, the applications should link with the static library. This error can normally be caught by link-editing a dynamic library with -z text. This will flag non-pic code (position independent code), which is what is typically in a static archive library. A dynamic-library developer can also verify that no archive has been linked in by using the LD_OPTIONS environment variable with the value -Ddetail,libs when building the dynamic library. This prints the path of all dependent libraries searched for. If the search for any dependent library finds a .a file before or instead of a .so file, then an archive library will be used. A.4. How the Correct Version of libC.so is Found When a library or application is linked with an implicit or explicit dependency on the dynamic C++ library, libC.so, the presence of other versions of libC.so libraries at link time or run time will not cause an incompatible libC.so to be used. Each compiler driver adds ld -L options to force its own version of libC.so to be found at link time. This may actually be a sym-link to /usr/lib/libC.so.N as described in reference [8]. The version number found in this library (not merely in its filename) is saved in the library or application ELF file that depends on it. At runtime, the dynamic loader selects the C++ library named with this version number.[10] This selection might be influenced by the builder's LD_RUN_PATH environment variable and the user's LD_LIBRARY_PATH environment variable (typically set up by system administrators). Appendix B: Additional Advice for C++ Users B.1. Expected C++ Binary Interfaces SunPro's C++ compiler developers inform us to expect only one more C++ binary interface after SPARCompilers 3.0 (which is caf' ; see footnote 1). The next release will be binary-incompatible with SPARCompilers 3.x, but conforming to a hopefully-standard-and-stable C++ ABI. This ABI is the subject of LSARC case 1993/550[1]. B.2. Name Mangling Differences The C++ name ``mangling'' algorithm is different between cfront (that is, SPARCompilers 2.0 aka C++ 3.0), and caf' (that is, SPARCompilers 3.0 aka C++ 4.0). We have been convinced this incompatibility is a feature (until the C++ ABI is stable). LSARC required future C++ compilers to change the name mangling as well, whenever the ABI is changed incompatibly. In particular, LSARC required that the proposed standard ABI[1] specify name mangling different from that of SPARCompilers 3.0. B.3. Frequently Asked Questions A list of Frequently-Asked-Questions about C++ and their answers is in reference [11]. This is not specific to Sun or Solaris. Appendix C: Reference Material [1] LSARC case 1993/550, C++ ABI, has a specification and an opinion, but the opinion is not yet finalized (at this writing). The C++ Object Binary Interface (OBI) has been split out of this case. [2] PSARC Packaging opinion 1991/061 http://sac.eng/Archives/BestPractices/ToDo/packaging.rules/packaging.rules.txt [3] Tools.h++ case is LSARC/1992/026. Opinion is /shared/sac/LSARC/1992/026/opinion.ms [4] Mail discussion for this case is in /shared/sac/PSARC/1993/571/mail . [5] SPARCompilers C++ 3.0.1 Programmers Guide, part #800-6986-11, is available on-line in the SunPro AnswerBook. The manuals for SPARCompilers C++ 4.0 include: SPARCompiler C++ 4.0 User's Guide 801-4727-05 SPARCompiler C++ 4.0 Language System Product Reference Manual 801-4728-05 Tools.h++ Intro and Reference Manual 801-4317-05 Object Oriented Programming Article 801-5058-05 As Close As Possible to C - But No Closer Article 801-5057-05 [6] Naming Conventions for Software Packages, Evan Adams, et. al., June 21, 1987. This is available on-line only in Interleaf format. SAC would welcome a conversion to a modern form, such as Frame. The authors are willing to send a hardcopy of this document to requesters. [7] Project DOE C++ Programming Style Guide, SunSoft part #801-3842, available in /net/bigdoe.eng/export/DOE/doc/DOEPI/doc/C++_StyleGuide,v2.0.1.ps and the Project DOE C++ Programming Style Guide Quick Reference, SunSoft part #801-3967, /net/bigdoe.eng/export/DOE/doc/DOEPI/doc/C++_StyleGuide.QuickRef,v2.0.1.ps This document includes a Bibliography. Both documents are available in hardcopy from the Copy Center; E-mail a request to ``copyrequest at snail.Sun.COM''. [8] PSARC's opinion on Bundling libC.so with Solaris /shared/sac/PSARC/1993/071/opinion.ms [9] PSARC Interface Taxonomy Addition: the Obsolete classification /shared/sac/PSARC/1993/226/opinion.ms [10] The SunOS 5.1 Linker and Libraries Manual, part #801-2869-10. More recent versions may be available via AnswerBook (instead of paper). [11] The Frequently-Asked-Questions for newsgroup comp.lang.c++ (in plain ASCII text format, but arguably dated) is in /net/bigdoe.eng/export/DOE/doc/DOEPI/doc/comp.lang.C++.FAQ Sun Proprietary: Internal Us1.0.3y LSARC Guidelines for C++ _________________________ FOOTNOTES 1. LSARC case 1993/550. 2. In Solaris 10/93, the intention was to bundle the libC.so.4 from cafe'; however, due to a last-minute change in caf''s name mangling, the bundled libC that should match caf' does not, causing incompatibility and consternation. These libC versions are in different packages, in the ``all'' cluster. Starting with 4/94, both cafe''s libC.so.5 and cfront's libC.so.3 will be moved to the ``end-user'' cluster, so more users will have it installed. Solaris 2.4 for x86 does not bundle libC, though Solaris 2.5 for x86 may. 3. But, alas, the libC.so.5 that is bundled with Solaris 2.4 will work with C++ 4.0 but won't work with C++ 4.0.1. The latest libC.so.5 patch, 101242-06, will work with both C++ 4.0 and 4.0.1. 4. Bundled applications cannot depend on any unbundled component. 5. One might derive all classes from one that implements new and delete. You may want to allow the user to override your implementation, similar to the way caf''s libC allows the user to override its ``default'' implementations. 6. Exceptions may be granted by an ARC for extremely primitive functionality, comparable to the C library, or for names defined by standards. When possible, we should influence standards to abide by these reasonable naming conventions. 7. For instance, the particular compiler that can call a library might be superseded during the life of that library, and cease to be sold. Another version of the same problem: a new compiler might not be readily accepted because some popular bundled library is not yet released in a form callable by this new compiler. 8. The committee explicitly defines ``forever'' to mean ``until a major release'' or until the dynamic library for that binary interface is obsoleted using the Obsolete classification process[9]. 9. Our package installation software will assure that the end-user has one copy of the dynamic library, but not multiple instances in different directories. Furthermore, the installation software will accept an updated version of this package to replace an older version, but not vice versa. Note that any software license agreements from the original library vendor need to permit free redistribution of the shared library (but not necessarily any header files, etc.). 10. As Cris Perdue pointed out, it is interesting to note that there is no such safeguard for multiple versions of the usual system libraries such as the C library, libc.so. If Sun would wish to support incompatible major versions on the same machine, some provision would have to be made. (Users might have to reference the version number explicitly.) _________________________ --------------------------------------------------------------------------------------------- ARC Policies 1. Applications may be implemented in C++. (See Section 3.) 2. Libraries may be freely implemented in C++ as long as they only export C interfaces. (Section 4.) 3. Libraries implemented in C++ may avoid dependence on the C++ library, libC. Otherwise, they should link dynamically to libC, and perhaps ship the required libC package. (Sections 4.1, 5.5, and A.3.) 4. Libraries exporting C++ interfaces are discouraged until they use a stable C++ ABI. (Section 5.) 5. A naming convention requires that a library offering a C++ API include a compiler binary interface identifier in its name, such as libfoo-SC3. (Section 5.6.) 6. A packaging convention requires the separation of libraries exporting C++ interfaces from compiler-independent packages. (Section 5.7.) 7. Information and advice in these guidelines may be useful for languages other than C++. Additional advice and reference materials are also provided in the Appendices.