Search code examples
gcclibxml2include-pathnix

Include directory off-by one in libxml2 for nix


I'm bundling a .cpp program that depends on libxml, but g++ cannot find it. I've done the appropriate steps to make libxml available, however the directory structure is slightly different than the source expects. I want to know about nix-based solutions to this problem.

The compiler (from a nix-shell session) says that libxml is not in my system path:

fatal error: libxml/encoding.h: No such file or directory
#include <libxml/encoding.h>

However, it should be. In my .nix file I made sure to included libxml2

buildInputs = [ ... libxml2 ...];

and my nix-shell environment confirms that the library is present:

NIX_CFLAGS_COMPILE= [...] -isystem /nix/store/zf1nyqyx2zd6y944ln2rxnhd5m4265n4-libxml2-2.9.9-dev/include  [...]

If I look in that directory, I find the search path is off. The path to the file is actually (relative to NIX_CFLAGS_COMPILE path):

libxml2/libxml/encoding.h

I found that I can compensate for this off-by-one path error by adding the following option to my compile command:

-isystem /nix/store/zf1nyqyx2zd6y944ln2rxnhd5m4265n4-libxml2-2.9.9-dev/include/libxml2

(The same path as the NIX_CFLAGS_COMPILE, but starting at the libxml2 directory.)

Given that information, I am wondering about a nix-based solution to this problem. The source is not mine, so changing them is the last thing I want to do. I see two other options.

First, I could add the path in the makefile that is triggered during buildPhase. However, I'm not exactly sure how to simply grab that path. For instance, inheriting libxml2 in my derivation makes the libxm2-2.9.9-bin directory available, when I need the libxml2-2.9.9-dev. I suppose I could grep or sed on the NIX_CFLAGS_COMPILE path, but I'd rather not.

My preferred solution would be to make a simple libxml derivation based off the libxml2 and just add that to my buildInputs, but that seems like it might not be simple either.


Solution

  • Try running pkg-config --cflags libxml-2.0 to get the appropriate compiler options.

    If everything is configured correctly, it will find the appropriate /nix/store/*-libxml2-2.9.9-dev/lib/pkgconfig/libxml-2.0.pc file on your computer, and extract the needed compiler options from that.

    You could invoke GCC using a one-liner like this:

    g++ program.cpp $(pkg-config --libs --cflags libxml-2.0) -o program
    

    This is a general solution that doesn't just apply to Nix, but you should be able to get it to work in Nix by ensuring you have the pkg-config utility on your PATH and ensuring the proper environment variables are set so that it can find libxml2. Nix probably has a bunch of shell scripts or something to help you set up your environment in that way, because this is a common need.