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-arch
mailing list