manpath change for ports ?

Dag-Erling Smørgrav des at des.no
Thu Mar 9 08:29:55 UTC 2017


Tijl Coosemans <tijl at FreeBSD.org> writes:
> If you want to run a program from its build directory and the program
> links to a library also in the build directory then you have to run the
> program with LD_LIBRARY_PATH environment variable set to the build
> directory.  Or, you could link the program with -rpath <builddir>, but
> then you should relink it before installation.  It's one of the things
> libtool takes care of automatically.
>
> If this is the problem you have then it has nothing to do with gcc.  If
> you're not using libtool then your program probably does not have any
> rpath or runpath so it falls back on rtld/ldconfig which may find it in
> /usr/local/lib.

You are correct in theory, but I am using libtool and it doesn't work.

Here's a series of emails I wrote to the maintainer a little over six
months ago explaining the problem:

1)

| I discovered that lang/gcc48 (and presumably the other gcc ports as
| well) not only have /usr/local/include in their default include path,
| but actually place it ahead of /usr/include.  This is causing me no end
| of grief with software that uses iconv, because GNU libiconv's <iconv.h>
| f*s up your namespace so the build fails unless you explicitly link with
| GNU libiconv instead of using the libc version.  [...]

2)

|                              [...] I realized over the weekend that the
| situation is even worse than I initially thought.  Basically, ports gcc
| is unusable for any other purpose than to build ports which don't
| support clang.  Let me explain with a hypothetical scenario:
| 
| You are developing a library which is important enough that you need to
| have the stable version installed on your development system.  It is
| installed in /usr/local as usual.  You've been working on fixing a bug,
| and have written a unit test which exercises the relevant code and
| verified that it can deterministically trigger the bug.  You fix the bug
| and 'make check' again, all green.  Then you clean out your working
| copy, re-run configure with CC=gcc and 'make check' again.  Your tests
| fail.
| 
| What happened is that when you built your code with gcc, the tests were
| linked and run with the stable version of the library, where the bug is
| not fixed.  You can build with LDFLAGS=-L$(top_builddir)/lib, you can
| even specify the full path to the library in LDADD for each individual
| test, it doesn't matter.  It will *always* pick the installed version
| first.  The only way to get your tests to pass is to not have the
| library installed.
| 
| Real-world example - a 10.3 system with upstream OpenPAM installed
| because it uses OpenPAM's OATH implementation:
| 
| with base clang:
| 
| des at desk ~/src/openpam/trunk% libtool exec ldd ./t/t_openpam_dispatch
| /home/des/src/openpam/trunk/t/.libs/t_openpam_dispatch:
| 	libpam.so.2 => /home/des/src/openpam/trunk/lib/libpam/.libs/libpam.so.2 (0x800822000)
| 	liboath.so.2 => /home/des/src/openpam/trunk/lib/liboath/.libs/liboath.so.2 (0x800a34000)
| 	libcrypto.so.7 => /lib/libcrypto.so.7 (0x800c39000)
| 	libc.so.7 => /lib/libc.so.7 (0x80102f000)
| 
| with lang/gcc:
| 
| des at desk ~/src/openpam/trunk% pkg which =gcc
| /usr/local/bin/gcc was installed by package gcc-4.8.5_2
| des at desk ~/src/openpam/trunk% libtool exec ldd ./t/t_openpam_dispatch
| /home/des/src/openpam/trunk/t/.libs/t_openpam_dispatch:
| 	libpam.so.2 => /usr/local/lib/libpam.so.2 (0x800822000)
| 	liboath.so.2 => /usr/local/lib/liboath.so.2 (0x800a34000)
| 	libcrypto.so.7 => /lib/libcrypto.so.7 (0x800c39000)
| 	libc.so.7 => /lib/libc.so.7 (0x80102f000)
| 	libcrypto.so.8 => /usr/local/lib/libcrypto.so.8 (0x8013dc000)
| 	libthr.so.3 => /lib/libthr.so.3 (0x8017e9000)
| 
| (and don't ask me why the gcc version is linked with two different
| versions of libcrypto!)

3)

| I honestly thought this was a recent change, but I realize now that the
| recent change is that I switched from developing on systems that still
| had gcc in base (without /usr/local in the search path) to systems that
| don't, and therefore use gcc from ports.
| 
| The correct solution, in my opinion, is to remove /usr/local from all
| search paths.  There is no need for it, even for ports, because most
| ports add /usr/local to CPPFLAGS and LDFLAGS, either explicitly or
| implicitly (by passing --prefix=${LOCALBASE} to the configure script).
| If there are gcc-only ports which *don't* do it, they can easily be
| fixed.
| 
| I initially thought that merely changing the library search order would
| be sufficient, but apparently gcc somehow forces /usr/local/lib to take
| precedence even over ${LD_LIBRARY_PATH}, which is what causes my unit
| tests to fail.  Here is an example from another project where I modified
| the libtool wrapper to show its environment and run ldd before executing
| the binary:
| 
| des at desk ~/src/cryb-to% ./t/t_core
| PATH=/home/des/bin:/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin:/bin:/sbin
| LD_LIBRARY_PATH=/home/des/src/cryb-to/lib/test/.libs:/home/des/src/cryb-to/lib/core/.libs
| /home/des/src/cryb-to/t/.libs/t_core:
| 	libcryb-test.so.0 => /usr/local/lib/libcryb-test.so.0 (0x80081f000)
| 	libcryb-core.so.0 => /usr/local/lib/libcryb-core.so.0 (0x800a26000)
| 	libc.so.7 => /lib/libc.so.7 (0x800c2a000)
| 1..2
| not ok 1 - version
| ok 2 - no memory leaked
| 
| This is a skeleton test which only verifies that the library it's linked
| with has the same version as the one it was compiled with.  Here's the
| same test, with the same modifications, built with clang:
| 
| des at desk ~/src/cryb-to% ./t/t_core  
| PATH=/home/des/bin:/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin:/bin:/sbin
| LD_LIBRARY_PATH=/home/des/src/cryb-to/lib/test/.libs:/home/des/src/cryb-to/lib/core/.libs
| /home/des/src/cryb-to/t/.libs/t_core:
| 	libcryb-test.so.0 => /home/des/src/cryb-to/lib/test/.libs/libcryb-test.so.0 (0x80081f000)
| 	libcryb-core.so.0 => /home/des/src/cryb-to/lib/core/.libs/libcryb-core.so.0 (0x800a27000)
| 	libc.so.7 => /lib/libc.so.7 (0x800c2c000)
| 1..2
| ok 1 - version
| ok 2 - no memory leaked
| 
| Please understand that the *only* way I can think of to work around this
| is to set --nostdinc and --nostdlib and explicitly pass the correct
| search path and list of libraries (-lgcc -lc) to gcc, and even then I'm
| not sure it would work.  I don't find that reasonable at all.
| 
| Note that I am not sure whether this problem is limited to gcc or if ld
| is also involved.  The iconv problem which I originally reported is
| caused by gcc picking up iconv.h from /usr/local/include instead of over
| /usr/include, but I'm not sure whether the linking problem is caused by
| gcc passing its search path on to ld, or to ld having its own incorrect
| search path.  I tried explicitly setting LD=/usr/bin/ld, but that
| doesn't make any difference since libtool uses gcc as a linker instead
| of calling ${LD} directly.

DES
-- 
Dag-Erling Smørgrav - des at des.no


More information about the freebsd-ports mailing list