Friday, January 12, 2018

Pre-compiled libraries in nix-shell

I've been using nix-shell as a way to have an easily reproducible environment.  I was using Docker but it's overkill for what I was looking for and it gave me the opportunity to explore the Nix ecosystem a little further.

The project I'm currently working on used Elm for the front-end, Elixir for managing the API and connecting to SQL Server.  Microsoft have open sourced the necessary libraries to use ODBC through Erlang so I was able to get it working on my development environment pretty quickly. 

The MS libraries are here with complete installation instructions.

However, when I tried to incorporate into my actual project I ran into a few issues.  I am using nix-shell to load up my environment so I know that its the same across machines and it's been working very well.  After I had everything installed, I attempted to connect to the database only to be informed by the ODBC Driver Manager that /opt/microsoft/msodbcsql/lib64/libmsodbcsql-13.1.so.9.2 did not exist.  I checked the filesystem and the file was there so I used the ldd utility to inspect the libraries and found that most of the required libraries could not be found:

$> ldd /opt/microsoft/msodbcsql/lib64/libmsodbcsql-13.1.so.9.2
linux-vdso.so.1 (0x00007fff71ba5000)
libdl.so.2 => /nix/store/.../lib/libdl.so.2 (0x00007f8c4ce9a000)
libodbcinst.so.2 => not found
libcrypto.so.1.0.0 => not found
libkrb5.so.3 => not found
libgssapi_krb5.so.2 => not found
libcurl.so.4 => not found
libssl.so.1.0.0 => not found
libuuid.so.1 => not found
libstdc++.so.6 => not found
libm.so.6 => /nix/store/.../lib/libm.so.6 (0x00007f8c4cb4e000)
libgcc_s.so.1 => /nix/store/.../lib/libgcc_s.so.1 (0x00007f8c4c938000)
libpthread.so.0 => /nix/store/.../lib/libpthread.so.0 (0x00007f8c4c71a000)
libc.so.6 => /nix/store/.../lib/libc.so.6 (0x00007f8c4c368000)
/nix/store/.../lib64/ld-linux-x86-64.so.2 (0x00007f8c4d49a000)

After doing some research I found a few links to help me better understand the problem.  From this StackOverflow issue
"So, the path to the dynamic linker is hard-coded in the binary. And the dynamic linker being used is from the system (from the host glibc), not from nix. And because the dynamic linker doesn't match the glibc which we want and need to use, it doesn't work.
A simple and working solution is patchelf."
So I followed along and tried to get these tools to work with the MS libraries but no glory.  I kept getting "cannot find section .interp" when attempting to set the interpreter using patchelf.  I wasn't able to get past this issue as I had limited time and was already pretty deep down the rabbit hole.  I was able to find the source for the MSODBC drivers version 11 but the compiled version was 13 and I was still unable to get the older code to compile.  Again, limited time and pressure to move on.
So undoing the nix-shell environment did allow me to get everything working.  I hope to have time to figure this out in the future but wanted to post my findings in the event anyone else is experiencing these issues with the MS drivers.

Other links: