Statically link GMP to an Haskell application using GHC (+ LLVM) - haskell

How can I drop dynamic dependency on libgmp and go from this:
linux-vdso.so.1 => (0x00007fffdccb1000)
libgmp.so.10 => /usr/lib/x86_64-linux-gnu/libgmp.so.10 (0x00007fb01afc1000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007fb01acc7000)
librt.so.1 => /lib/x86_64-linux-gnu/librt.so.1 (0x00007fb01aabe000)
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007fb01a8ba000)
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007fb01a69d000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fb01a2df000)
/lib64/ld-linux-x86-64.so.2 (0x00007fb01b249000)
to this (currently desired):
linux-vdso.so.1 => (0x00007fffdccb1000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007fb01acc7000)
librt.so.1 => /lib/x86_64-linux-gnu/librt.so.1 (0x00007fb01aabe000)
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007fb01a8ba000)
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007fb01a69d000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fb01a2df000)
/lib64/ld-linux-x86-64.so.2 (0x00007fb01b249000)
in a clean and portable way that just works on all GNU/Linux distributions (and not messing up with BSDs (including OS X))?
Do you see any other dependencies that may cause problems in the currently desired list as given above when distributing a single Haskell binary targeting multiple GNU/Linux distributions?
Notes:
my app is GPLv3 so no license violation issues arise regarding GMP
Specifying a path to libgmp.a does not work ( How to selectively link certain system libraries statically into Haskell program binary? ), libgmp is still listed in the ldd output.

If you pass -optl-static -optl-pthread to GHC, it'll statically link all the runtime library dependencies, including GMP. Setting ld-options: -static -pthread in your Cabal file should accomplish the same thing.
That means you'll statically link in glibc too, but that probably won't be a problem, although it might increase binary size quite a bit. Using an alternative libc like musl or uClibc should help counteract that, if it's a problem for you.

Related

Build gcc from sources - GLIBC

we have old Linux distribution and the vendor doesn't support its updates. We want to build our c++ code with a modern compiler, for that we are building GCC compiler from sources (something very similar to https://github.com/darrenjs/howto/blob/master/build_scripts/build_gcc_10.sh)
Now the problem is that we can not deploy the executables because users' machine do not contain libstdc++.so.6 for this GLIBC. Is there a way to compile GCC and make it based on old local GLIBC that the vendor provides?
[EDIT]: After build my executable of xenenterprise 8.0.0 with GCC 10.1.0 that was built from sources:
[root#xen8 sandbox-gcov]# ldd build/main
linux-vdso.so.1 => (0x00007ffddf9fd000)
libstdc++.so.6 => /var/opt/gcc-10.1.0/lib64/libstdc++.so.6 (0x00007fb82155f000)
libm.so.6 => /lib64/libm.so.6 (0x00007fb82125d000)
libgcc_s.so.1 => /var/opt/gcc-10.1.0/lib64/libgcc_s.so.1 (0x00007fb821045000)
libc.so.6 => /lib64/libc.so.6 (0x00007fb820c77000)
/lib64/ld-linux-x86-64.so.2 (0x00007fb82192c000)
Then got error on another machine with native GCC 4.8.5 20150623 (Red Hat 4.8.5-44):
[root#xen8-1 sandbox-gcov]# ldd build/main
build/main: /lib64/libstdc++.so.6: version `CXXABI_1.3.8' not found (required by build/main)
build/main: /lib64/libstdc++.so.6: version `CXXABI_1.3.9' not found (required by build/main)
linux-vdso.so.1 => (0x00007ffeec5fe000)
libstdc++.so.6 => /lib64/libstdc++.so.6 (0x00007f92099db000)
libm.so.6 => /lib64/libm.so.6 (0x00007f92096d9000)
libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x00007f92094c3000)
libc.so.6 => /lib64/libc.so.6 (0x00007f92090f5000)
/lib64/ld-linux-x86-64.so.2 (0x00007f9209ce3000)

locate finds library but ldconfig does not

I am using using Centos 6.6 and there is a shared library the build generates used by number of executable and any executable using this shared library cannot find it as seen by ldd.
I can locate the library:
$ locate libcs.so.1
/opt/cloudshield/lib/libcs.so.1
ldd shows the following:
$ sudo ldd /opt/cloudshield/lib/libcs.so.1
ldd: warning: you do not have execution permission for `/opt/cloudshield/lib/libcs.so.1'
linux-vdso.so.1 => (0x00007ffff4fff000)
libc.so.6 => /lib64/libc.so.6 (0x00007f7a0fd56000)
/lib64/ld-linux-x86-64.so.2 (0x000000340ba00000)
$ sudo ldconfig -v | grep libcs.so.1
Is it because of the kernel library linux-vdso.so.1?
Executable cannot find the library libcs.so.1:
[fpeter#localhost radius]$ ldd radius
`linux-vdso.so.1 => (0x00007fff634b4000)
libconfd.so => /home/fpeter/trunk/thirdparty/tailf/confd/lib/libconfd.so (0x00007f5db20e6000)
libcs.so.1 => not found
libpthread.so.0 => /lib64/libpthread.so.0 (0x000000340c600000)
libc.so.6 => /lib64/libc.so.6 (0x000000340c200000)
libm.so.6 => /lib64/libm.so.6 (0x000000340ce00000)
libcrypto.so.1.0.0 => /usr/lib64/libcrypto.so.1.0.0 (0x0000003ba4a00000)
/lib64/ld-linux-x86-64.so.2 (0x000000340ba00000)
libdl.so.2 => /lib64/libdl.so.2 (0x000000340be00000)
libz.so.1 => /lib64/libz.so.1 (0x000000340d600000)
Add /opt/cloudshield/lib/ to your LD_LIBRARY_PATH environment variable, e.g.:
LD_LIBRARY_PATH=/opt/cloudshield/lib
export LD_LIBRARY_PATH
See also How to build library ithoutsudo or
shared libraries.

Build executable on Linux that does not depend on any shared libraries

Environment: Ubuntu 14.04. gcc 4.8.2
I am working on a C++ console application. When I run "ldd" on the executable, I see the following:
linux-vdso.so.1 => (0x00007fffe495e000)
libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f9ffa754000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f9ffa38e000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f9ffa087000)
/lib64/ld-linux-x86-64.so.2 (0x00007f9ffaa6e000)
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f9ff9e71000
I am wondering if it is possible to define flags on gcc/linker such that the final executable does not depend on any shared libraries.
Simply add -static while linking :-)
Static linking should be avoided not only for security reasons.
BTW: As I know there is no way to create a static lib from a dynamic one. So if you have only the shared lib, you can't link static.

Libtool: Maintain library dependencies in header files

I am using Libtool and the other GNU Autotools (Autoconf, Automake, etc.) to build a shared library. My library has a dependency on another library (hwloc). I allow the user to specify a custom path for hwloc at configuration (the following is in configure.ac):
# Check for hwloc
AC_ARG_WITH([hwloc], [AS_HELP_STRING([--with-hwloc[[=DIR]]], [Location of the hwloc library])])
AS_IF([test "x$with_hwloc" != x],
[CPPFLAGS="-I$with_hwloc/include $CPPFLAGS"
LDFLAGS="-L$with_hwloc/lib $LDFLAGS"])
AC_CHECK_HEADERS([hwloc.h], [], [AC_MSG_ERROR([hwloc is a required library])])
AC_SEARCH_LIBS([hwloc_topology_init], [hwloc], [], [AC_MSG_ERROR([hwloc is a required library])])
After doing the build process (./configure --with-hwloc=...; make; make install), my shared library file successfully links with hwloc (ldd libmylib.so):
linux-vdso.so.1 => (0x00007ffff331c000)
librt.so.1 => /lib64/librt.so.1 (0x00007fa225c63000)
libpthread.so.0 => /lib64/libpthread.so.0 (0x00007fa225a46000)
libhwloc.so.5 => /home/brooks8/bin/hwloc-1.8.1/lib/libhwloc.so.5 (0x00007fa225816000)
libm.so.6 => /lib64/libm.so.6 (0x00007fa225591000)
libxml2.so.2 => /usr/lib64/libxml2.so.2 (0x00007fa22523f000)
libc.so.6 => /lib64/libc.so.6 (0x00007fa224eab000)
/lib64/ld-linux-x86-64.so.2 (0x0000003532000000)
libdl.so.2 => /lib64/libdl.so.2 (0x00007fa224ca6000)
libz.so.1 => /lib64/libz.so.1 (0x00007fa224a90000)
However, one of my header files includes hwloc. This causes problems when I try and test my library and hwloc is in a non-standard location:
mpicc test.c -I/home/brooks8/bin/mylib/include -L/home/brooks8/bin/mylib/lib -lmylib -o test/test -std=c99 -O3 -g3:
/home/brooks8/bin/mylib/include/include/util.h:14:21: fatal error: hwloc.h: No such file or directory
#include <hwloc.h>
^
Is there a way to solve this issue without needing to link hwloc when I use my library?
Thank you in advance, and please let me know if I should provide any more information regarding my situation.

What does version info in ldd -v mean?

Version information:
/usr/lib/lapack/liblapack.so:
libc.so.6 (GLIBC_2.14) => /lib/x86_64-linux-gnu/libc.so.6
libc.so.6 (GLIBC_2.4) => /lib/x86_64-linux-gnu/libc.so.6
libc.so.6 (GLIBC_2.2.5) => /lib/x86_64-linux-gnu/libc.so.6
libgcc_s.so.1 (GCC_4.0.0) => /lib/x86_64-linux-gnu/libgcc_s.so.1
libgfortran.so.3 (GFORTRAN_1.0) => /usr/lib/x86_64-linux-gnu/libgfortran.so.3
libgfortran.so.3 (GFORTRAN_1.4) => /usr/lib/x86_64-linux-gnu/libgfortran.so.3
libm.so.6 (GLIBC_2.2.5) => /lib/x86_64-linux-gnu/libm.so.6
So there are 3 rows of libc.so.6, versioned at GLIBC_2.xx.
What does that mean? What version of libc.so.6 does this liblapack.so require?
How can I get liblapack.so's version?
What does that mean?
It means that liblapack.so requires versioned symbols from libc.so.6 with versions GLIBC_2.2.5, GLIBC_2.4 and GLIBC_2.14. You can read about versioned symbols here.
What version of libc.so.6 does this liblapack.so require?
It requires 2.14 or newer. In general, GLIBC never removes symbols, only adds new ones, and so will still provide symbols versioned at GLIBC_2.2.5 even in the latest GLIBC-2.24.
If it did ever remove such "old" versioned symbol, that would break any old binaries that depended on that symbol (which is why it's not done).
How can I get liblapack.so's version?
It doesn't look like liblapack.so itself is using any versioned symbols. You can look at your package manager to find out what version of liblapack.so you have. Something like:
dpkg -S /usr/lib/lapack/liblapack.so
liblapack-dev: /usr/lib/lapack/liblapack.so
dpkg -l liblapack-dev
...
ii liblapack-dev 3.5.0-2ubuntu1 amd64 Library of linear algebra routines 3 - static version

Resources