Issues mixing Fortran, C and CC++ in shared and static libs

Experience with the Silo library is described here as an example of the issues.

The Silo library started as a C library. Soon after it was developed, a hand-coded fortran interface was added to it as a bunch of wrappers, also written in C but obeying Fortran language binding/naming semantics, which turned around and called the equivalent C functions. Eventually, some C++ code was added to the silo library to support some advanced compression features.

The introduction of C++ code to Silo library raised the issue of how does a C or Fortran Silo client properly link to and use static (libsilo.a) and shared (libsilo.so) versions of the Silo library. Of particular concern was whether Fortran users were going to have to make big changes to their Makefiles.

Below, Jeremy Meredith of the VisIt team outlined the issues. Here are the options...

  1. static library built using ar, client executable with g++:
    • build the compression .o's using g++
    • build the silo .o's using gcc
    • build libsilo.a using ar
    • build silo client's .o's using gcc
    • link silo client with libsilo.a using g++ (can't use gcc)
  2. shared library built using gcc, client executable with g++:
    • build the compression .o's using g++
    • build the silo .o's using gcc
    • build libsilo.so using gcc (not g++)
    • build silo client's .o's using gcc
    • link silo client with libsilo.so using g++ (can't use gcc)
  3. shared library built using g++, client executable with gcc:
    • build the compression .o's using g++
    • build the silo .o's using gcc
    • build libsilo.so using g++ (not gcc)
    • build silo client's .o's using gcc
    • link silo client with libsilo.so using gcc (don't need g++ anymore)

In case 1, you built an archive and g++ never resolved the C++ symbols in the library, so you still need to resolve them with g++ in the final link.

In case 2, you built a shared library with gcc, so the C++ symbols were also never resolved. Similar to case 1, but the shared library version.

In case 3, when you linked the shared library with g++, it was able to resolve the outstanding C++ symbols (e.g. against libstdc++.so), so there's no longer a need for a C++ linker for the Silo client.

In other words, by including C++ object code in your Silo library, you're still free to build internal Silo library code with a C-only compiler, and Silo client code with a C-only compiler. However, the C++ symbols will not be resolved until you pass the Silo library through a C++ linker, either when creating a shared library or when creating an executable.

Oh, and obviously if the silo client is already C++, they have to use g++ anyway, so this only makes sense for C-only client codes.