Creating Compatible Libraries

The GCC 4.0 compiler ships with version 6.0.3 of the dynamic C++ runtime. Future minor versions of the library are guaranteed to retain binary compatibility with version 6.0.3; however, major versions are not guaranteed to be compatible, and developers should assume that a future compiler release will include an incompatible version of libstdc++.dylib.

If you distribute dynamic shared libraries that use the dynamic C++ runtime, changes to that runtime could potentially break clients of your library. For example, this can happen if your library’s interface includes types or classes defined by the dynamic C++ runtime. The following sections explain ways to remain compatible between major updates to the dynamic C++ runtime.

Avoiding libstdc++ in Your Library Interfaces

Because any component of the dynamic C++ runtime may change between major versions, your own dynamic shared libraries must avoid using classes, templates, and structures of the dynamic C++ runtime in their exported interfaces. The size and layout of standard C++ classes may change between different versions of the dynamic C++ standard library. If that happens and your library exports interfaces that rely on the current class information, clients of your library will break and require recompilation with an updated version of your library.

For any symbols your library exports to clients, you should follow these rules.

Keep in mind that the prohibitions on using dynamic C++ runtime classes applies only to your exported symbols. Within your library’s internal implementation, you are free to use the classes of libstdc++ as you choose. Also keep in mind that these rules are to prevent clients of your library from breaking when the dynamic C++ runtime is updated. Your own library might still require recompilation.

Remember that a dynamic shared library’s exported interface consists of all public symbols, not just classes and functions declared in the library’s header files. In particular, template instantiations are public by default. So, if you instantiate a template with the declaration std::vector<my_type>, your library exposes a public instance of std::vector and will experience problems with any major version changes to the dynamic C++ runtime.

As you create your library, you should be mindful of which interfaces you want to make public and mark them appropriately. For information on how to limit the exported symbols in your library, see “Controlling Symbol Visibility.”

Limiting the Scope of Callbacks

In certain cases, a C++ application can supply code that is used by the dynamic C++ runtime itself. The most relevant example of this is when an application replaces the global new and delete operators. Rarer examples include I/O stream callbacks defined through std::ios_base::register_callback and user-defined facets imbued into the global locale.

If you implement your own version of operator new, that version is used by all other libraries that link with the same version of libstdc++.dylib. If this is not what you intended with your implementation, you should mark your version of the method with the __private_extern__ tag to prevent it from ever being seen by other libraries.

For more information on controlling the visibility of symbols in your libraries, see “Controlling Symbol Visibility.”