PSARC/2008/549 - Apache Standard C++ Library

John Plocher John.Plocher at Sun.COM
Thu Sep 4 12:31:03 PDT 2008


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.





More information about the opensolaris-arc mailing list