Search code examples
linuxstatic-librarieswkhtmltopdf

Build a linux static library


For a website of mine I'm trying to make wkhtmltopdf(Link) work. The website is hosted on a shared hosting, which are a bit troublesome when using libraries not installed.

After a few tries with multiple version of the library(some where supposed to be static but I still got error about shared library not being found) I ended up contacting the provider, who told me that it would work if I have a static version of the library.

Problem is, my linux knowledge is very limited. If I understand correctly, a static library would be a version of wkhtmltopdf, one single file, including all dependencies ?

As the official site mention are the followings : zlib, fontconfig, freetype, X11 libs (libX11, libXext, libXrender)

Second question is, could you point me to where I could find a step by step guide to build such library ? as my research are unsuccessful so far..


Solution

  • my linux knowledge is very limited

    I will assume you are more or less familiar with windows dlls, which are similar to linux .sos (shared objects).

    A shared object can be shared (hence the name) between different programs. In most cases, when the executable is loaded, the library is loaded in memory too. You can see such dependencies with ldd.

    A static library (or statically linked library, or static executable, or whatever) is a library that is embedded in the executable at compile time. To statically link your library, you need to rebuild your executable, and link with a .a static library file, which is similar to .lib files on windows (with the visual studio compiler, at least, IIRC).


    This can be troublesome and time consuming. That's why I advise you to take another route:

    On windows, .dll files that share the same folder as the executable are given a higher preference than the one on the path (IIRC). On Linux (and generally UNIX), this is regarded as a security flaw, as someone could easily drop a rogue .so file and alter the program's behavior. You can however control this behavior with two environment variables: LD_LIBRARY_PATH and LD_PRELOAD. The second one is a bit more powerful, and is just some kind of "dll" injection. The first one, however, controls the path in which .so files will be searched.

    So, I advise you to look for the required dependencies with ldd, and do it once again on your server if you can. Look for every missing .so file. You could do so by issuing the command ldd wkhtmltopdf | grep not found.

    Once you have this list of missing libraries, bundle them together and send them on your server (be aware that they can have some dependencies too). You can probably find them on a local Linux installation of matching architecture, but I encourage you to try to match the distribution with the one of your provider.

    Then, issue the wkhtmltopdf call after setting the LD_LIBRARY_PATH environment variable. You can do it like so:

    LD_LIBRARY_PATH='/home/me/my_libs':$LD_LIBRARY_PATH /home/me/programs/wkhtmltopdf
    

    Note that I append the old LD_LIBRARY_PATH variable at the end. It is rarely set out of the box, but at least you shouldn't have any problem if you do it this way.


    To answer your comment: it is indeed a bit like modifying the PATH on windows (just to make this clear once again: on Linux, you have the same PATH environment variable, but it only works for executables' search path; so we're changing another LD_LIBRARY_PATH environment variable to specify the libraries search path).

    Please note that in the above example, I didn't change it system-wide, but only for calling wkhtmltopdf. On windows, there are multiple ways to change the PATH environment variable. You can open the dedicated gui, which will change the path variable in the registry. But you can also override it locally in a command prompt or batch script. This is exactly what I did here.

    Once LD_LIBRARY_PATH is exported, it will be used for every program you call, so it might be dangerous to set it system wide, if you have some incompatibilities. Moreover, whatever you try, you won't be able to set it system-wide if you don't have root access. So, you will at most affect only your programs.

    As a final note, you might pull a lot of dependencies with this project, since it is Qt-based. If you want to rebuild it statically, you have to build Qt first with -static. Next time, you might be interested in some containerization technology, such as docker (or even appimages/flatpack/snap), which is designed to work around this kind of problems.

    For further reading on dynamic link libraries on Linux, you might be interested in this resource or similar.