Compiling – Open-Source Way to Make a Static from a Dynamic Executable

compilinglibrariesshared library

Let me explain the problem with an example. I use some old program in my day to day work, like for example xfig and pdfedit.

Now, these programs are quite old and not updated too often; my fear is that one day or the other they will not work anymore for lack of some library or some incompatible update.

If the program is easy to compile now, on a running system, the solution is handy: try to hack a bit the source and compile it statically — the resulting executable will be big and not so efficient, but it will work for the foreseeable future(1). This seem to be the case for xfig and I will try it as soon as possible.

But, for example, pdfedit depends on Qt3, and setting up a system to compile it is quite complex at this time. Fortunately it can be run right now, thanks to the fact that the library it needs do not conflict with anything. But this can change in the future, so I would like to solve this problem:

How can can I make a static binary (or similar thing) if I have a dynamic one and all the libraries, but no source code, on Ubuntu?

I searched around. One possibility is statifier(2), but it has a lot of problems with the address randomization, so it's a no-no. The non-free version, Ermine, seems to work, but I would really prefer an open source option.

Another possibility is to use docker or a similar packaging system. But all the tutorial I found are quite RedHat-oriented; and, honestly, quite complex to follow.


Footnotes:

(1) is not so crazy. I use a static ffmpeg for example, works ok and without any compatibility problems…

(2) to compile statifier, see https://stackoverflow.com/questions/23498237/compile-program-for-32bit-on-64bit-linux-os-causes-fatal-error

Best Answer

You can solve your problem in another and more simple way:

Use ldd on your executable to see the linked libraries, for example:

$ ldd /bin/bash
linux-vdso.so.1 =>  (0x00007fffb2fd4000)
libtinfo.so.5 => /lib/x86_64-linux-gnu/libtinfo.so.5 (0x00007fac9ef91000)
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007fac9ed8d000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fac9e9c6000)
/lib64/ld-linux-x86-64.so.2 (0x00007fac9f1e1000)

Then collect all the libraries in a folder and set the LD_LIBRARY_PATH environment variable before running your program to point at this folder:

$ LD_LIBRARY_PATH="/opt/my_program/lib" /opt/my_program/start

Alternatively you can add an entry for the lib folder to /etc/ld.so.conf.d/. But that would apply the change systemwide.

Related Question