[ # ] Switching from Static to Dynamic Linking
/* Posted March 21st, 2008 at 8:59am *//* Filed under C/C++, Linux, Microsoft, Programming */
Recently I had to modify a library to use dynamic linking in order to cut down on its size. Originally a 8MB file, I was looking at reducing the size to 1.3MB. Pretty great right? So why not dynamically link every time? Well, there are certain times when static linking, though it increases the size of your library, might be preferable. For example, your library may be using some obscure third-party library that your customer does not have. If you dynamically linked this, you’d either require the customer to also have this library on his host, or else ship the third-party library with your own. Perhaps due to licensing reasons, incompatible versions or unavailability, this may not always be possible or even ideal. In my case, the third-party library was 10MB. Shipping it with my 1.3MB library would actually have a net increase in total package size. But since I was actually shipping several of my own smaller libraries which all used to statically link the third-party library, eventually the savings overcame the gain.
To do this is a matter of modifying your Makefile, there is no code change necessary unless you plan to call some functions in the third-party library, in which case you’ll need to use dlopen(). For me there was nothing this complicated, I just needed my third-party header files to be defined… no function calls needed. The original Makefile was doing something like this:
g++ -c -o main.o main.cpp
g++ -L/home/user/tool/static-libs -lstatic_third_party_lib -o main main.o
To make it dynamically link, you first need to find the dynamic version of the third party library. Usually static libraries have a *.a extension. Dynamic libraries have a *.so extension. Once I found the path to the dynamic library, I simply modified my Makefile like so:
g++ -c -o main.o main.cpp
g++ -L/home/user/tool/dynamic-libs -ldyn_third_party_lib -o main main.o
In this way, your own library will be smaller but you have now imposed a requirement on your user. Regardless of how you get your customer the third party lib, he will have to modify his LD_LIBRARY_PATH to include a path to it. But this was not good enough for me, my requirement was to rid the library of that dependency. So what do to? There’s another option that is generally considered good programming convention that you should always use with the -L option, and that is –rpath. This option specifies the run-time path that your library will look for the third-party library, avoiding the need for the customer to set LD_LIBRARY_PATH. The Makefile would be extended like so:
g++ -c -o main.o main.cpp
g++ -L/home/user/tool/dynamic-libs -Wl,--rpath=/home/user/tool/dynamic-libs -ldyn_third_party_lib -o main main.o
Basically, any time you use -L, use -Wl,–rpath with the same path. This is great if you know the absolute path where it will be installed on your customer’s machine, but this may not always be true. For our software, the user is free to install it anywhere, and thus this option would not be useful. There is one more trick you can play to get this to work, and that is to use a relative path using the $ORIGIN variable. This is self-defined to be the path in which your library resides, you do not have to define it in your Makefile. Use it like so:
g++ -c -o main.o main.cpp
g++ -L/home/user/tool/dynamic-libs -Wl,--rpath=\$$ORIGIN/../../my/own/path/dynamic-libs -z origin -ldyn_third_party_lib -o main main.o
For you guys developing on SunOS, replace the -Wl,–rpath= option with -R, like this:
CC -c -o main.o main.cpp
CC -L/home/user/tool/dynamic-libs -R\$$ORIGIN/../../my/own/path/dynamic-libs -z origin -ldyn_third_party_lib -o main main.o
For you Windows guys, how did I manage to hold your attention until here?













Leave a Reply
(* required)