Tuesday, April 23, 2013

Building shared libraries with Jam

Jam is one of those tools I really admire: it is small, lean, fast and you don't have to be a rocket scientist to hack it. The best of all, it is so ahead of make you will wonder why you didn't use it before.

Ok, above paragraph very biased, but adding Jam to EDE solved a lot of portability problems we had before and introduced some new, which is story for itself. What matters most, with Jam you can write true build library that you will reuse between projects.

Sure, writing reusable build library with make is possible too; you need autotools and you write a little bit autoconf, then a little bit automake and everything you pack in a nice M4 script. Don't forget to use appropriate shell syntax or odd things will happen between platforms.

No more ranting... One of the most desired feature I find people are looking for Jam is how to build shared library. This isn't packed with stock Jam since shared library making is highly platform/OS specific (that is why we have libtool), but in the recent years things are settled up a bit: odd platforms died, wild compilers vanished and there is good chance you will find gcc (or gcc compatible compiler, like clang) on your target platform.

So, here is rule called SharedLibrary you can use with gcc and compatible compilers:


SUFSHARED ?= ".so" ;

rule SharedLibrary {
  local objs = $(>:S=$(SUFOBJ)) ;
  local lib = $(<:S=$(SUFSHARED)) ;

  # compile it
  ObjectCcFlags $(>) : -fPIC ;
  ObjectC++Flags $(>) : -fPIC ;
  Objects $(>) ;

  # link it
  LINKFLAGS on $(lib) = 
     -Wl,-soname,$(lib) -shared [ on $(lib) return $(LINKFLAGS) ] ;
  
  Link $(lib) : $(objs) ;
  Depends all : $(lib) ;
  Clean clean : $(lib) ;
}
Now, calling it with:

SharedLibrary libfoo : file1.c file2.c file3.c file4.cpp ;
will create libfoo.so ready for consumption. In case you are running Windows or other platform where .so extension is not suitable, setting SUFSHARED variable will fix that. The best of all, we completed it in a couple of seconds... ;)