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