tags:

views:

57

answers:

2

I'm planning to release some compiled code that shall be linked by client applications on MacOSX.

The distribution is some kind of code library and a set of header files defining the public interface for the library.The code is internally C++ but its public interface (i.e what's being shown in the headers) is completely C.

These are my requirements or atleast what I hope I can accomplish:

  • I want my library to be as agnostic as possible for what version of OSX and GCC the user is running. Having separate libraries for 64 bit and 32 bit is okay though.
  • I want my library to be loadable from languages that supports loading C libraries such as python or similar.
  • I want my libraries internal symbols to be isolated from the code it's being linked into. I don't want to have duplicate symbol errors because we happen to name an internal function in the same way. My C++ code is properly namespaced so this may not be as big of an issue though, but some of the libraries I depend on is C and can be an issue (see next point).
  • I want my library dependencies to be safe. My library depends on some libraries such as libpng, boost and stl and I don't want issues because some users don't necessarily have all of them installed or get problems because they have been compiled with other flags or have different versions than I have.

On Windows I use a DLL with an export library and link all my dependencies statically into the dll. It fulfills all the criteria above and if I can get the same result on OSX it would be great, however I've heard that dynamic libraries tend not to isolate symbols on mac in the same way.

Is there some kind of best practice for this on OSX?

+1  A: 

The key term you need is 'framework'. You need to create a 'universal' framework that is self-contained. ('Universal' is Apple-ease for 'compile several times and package into one library.) It's not as straightforward as on Windows in terms of encapsulation, but the necessary linker options are there.

bmargulies
+1  A: 

A normal OS X .dylib pretty much satisfies your requirements, with the note that you will want to have an exports file that the linker uses to determine exactly which symbols are exported (to prevent leaking your internal symbols).

In order to make your own library dependencies safe, you will probably need to either include those libraries with yours or link them statically into your library.

edit: To answer your follow-up question of how to apply an exports file to a link command, the man page for ld has the following to say:

 -exported_symbols_list filename
     The specified filename contains a list of global symbol names
     that will remain as global symbols in the output file.  All
     other global symbols will be treated as if they were marked
     as __private_extern__ (aka visibility=hidden) and will not be
     global in the output file. The symbol names listed in file-
     name must be one per line.  Leading and trailing white space
     are not part of the symbol name.  Lines starting with # are
     ignored, as are lines with only white space.  Some wildcards
     (similar to shell file matching) are supported.  The *
     matches zero or more characters.  The ? matches one charac-
     ter.  [abc] matches one character which must be an 'a', 'b',
     or 'c'.  [a-z] matches any single lower case letter from 'a'
     to 'z'.

So, if your library had only two functions that you wanted to be public, lets call them foo and bar, and they were C functions (so the symbol names aren't mangled), your exports file (let's call it myLibrary.exports) would contain these two lines:

_foo
_bar

and maybe some comments, etc. When you do the final link step to build the library, you would pass the -exported_symbols_list myLibrary.exports flag to the linker. This has the additional benefit that the link will fail if you don't provide one of the exported symbols; this can catch a lot of "oops, I forgot to include that file in the build" mistakes.

You don't need to use the command-line tools to do all this, of course. In the build settings for a dynamic library in XCode, you will find Exported Symbols File (undefined by default); set it to the path to your exports file there and it will be passed to the linker.

Stephen Canon
This seems like a good solution. Do you have any good reference on how to create an exports file?
Laserallan
I added some detail on how to use an exports file; for how to create one, if the library isn't too big I usually use nm to get a list of all the symbols and then remove the ones that I want to keep private. For large projects, this isn't really a viable approach, so I usually write scripts to generate the file for me.
Stephen Canon
Also note that there's no need for separate 32- and 64-bit libraries; OS X allows dylibs that support multiple architectures. It's a little convoluted from the command line, but if you're using XCode it should Just Work.
Stephen Canon
Thanks. With the addition, it is pretty much exactly what I was looking for!
Laserallan