Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 09 Mar 2017 09:29:42 +0100
From:      =?utf-8?Q?Dag-Erling_Sm=C3=B8rgrav?= <des@des.no>
To:        Tijl Coosemans <tijl@FreeBSD.org>
Cc:        Baptiste Daroussin <bapt@FreeBSD.org>, ports@FreeBSD.org, arch@FreeBSD.org
Subject:   Re: manpath change for ports ?
Message-ID:  <861su6ont5.fsf@desk.des.no>
In-Reply-To: <20170308204126.6d152c44@kalimero.tijl.coosemans.org> (Tijl Coosemans's message of "Wed, 8 Mar 2017 20:41:26 %2B0100")
References:  <20170306235610.cmpxk27jhoafel6l@ivaldir.net> <86mvcvojzt.fsf@desk.des.no> <20170308204126.6d152c44@kalimero.tijl.coosemans.org>

next in thread | previous in thread | raw e-mail | index | archive | help
Tijl Coosemans <tijl@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:
|=20
| 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=3Dgcc and 'make check' again.  Your tests
| fail.
|=20
| 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=3D-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.
|=20
| Real-world example - a 10.3 system with upstream OpenPAM installed
| because it uses OpenPAM's OATH implementation:
|=20
| with base clang:
|=20
| des@desk ~/src/openpam/trunk% libtool exec ldd ./t/t_openpam_dispatch
| /home/des/src/openpam/trunk/t/.libs/t_openpam_dispatch:
| 	libpam.so.2 =3D> /home/des/src/openpam/trunk/lib/libpam/.libs/libpam.so.=
2 (0x800822000)
| 	liboath.so.2 =3D> /home/des/src/openpam/trunk/lib/liboath/.libs/liboath.=
so.2 (0x800a34000)
| 	libcrypto.so.7 =3D> /lib/libcrypto.so.7 (0x800c39000)
| 	libc.so.7 =3D> /lib/libc.so.7 (0x80102f000)
|=20
| with lang/gcc:
|=20
| des@desk ~/src/openpam/trunk% pkg which =3Dgcc
| /usr/local/bin/gcc was installed by package gcc-4.8.5_2
| des@desk ~/src/openpam/trunk% libtool exec ldd ./t/t_openpam_dispatch
| /home/des/src/openpam/trunk/t/.libs/t_openpam_dispatch:
| 	libpam.so.2 =3D> /usr/local/lib/libpam.so.2 (0x800822000)
| 	liboath.so.2 =3D> /usr/local/lib/liboath.so.2 (0x800a34000)
| 	libcrypto.so.7 =3D> /lib/libcrypto.so.7 (0x800c39000)
| 	libc.so.7 =3D> /lib/libc.so.7 (0x80102f000)
| 	libcrypto.so.8 =3D> /usr/local/lib/libcrypto.so.8 (0x8013dc000)
| 	libthr.so.3 =3D> /lib/libthr.so.3 (0x8017e9000)
|=20
| (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.
|=20
| 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=3D${LOCALBASE} to the configure script).
| If there are gcc-only ports which *don't* do it, they can easily be
| fixed.
|=20
| 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:
|=20
| des@desk ~/src/cryb-to% ./t/t_core
| PATH=3D/home/des/bin:/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin:/b=
in:/sbin
| LD_LIBRARY_PATH=3D/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 =3D> /usr/local/lib/libcryb-test.so.0 (0x80081f000)
| 	libcryb-core.so.0 =3D> /usr/local/lib/libcryb-core.so.0 (0x800a26000)
| 	libc.so.7 =3D> /lib/libc.so.7 (0x800c2a000)
| 1..2
| not ok 1 - version
| ok 2 - no memory leaked
|=20
| 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:
|=20
| des@desk ~/src/cryb-to% ./t/t_core=20=20
| PATH=3D/home/des/bin:/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin:/b=
in:/sbin
| LD_LIBRARY_PATH=3D/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 =3D> /home/des/src/cryb-to/lib/test/.libs/libcryb-test=
.so.0 (0x80081f000)
| 	libcryb-core.so.0 =3D> /home/des/src/cryb-to/lib/core/.libs/libcryb-core=
.so.0 (0x800a27000)
| 	libc.so.7 =3D> /lib/libc.so.7 (0x800c2c000)
| 1..2
| ok 1 - version
| ok 2 - no memory leaked
|=20
| 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.
|=20
| 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=3D/usr/bin/ld, but that
| doesn't make any difference since libtool uses gcc as a linker instead
| of calling ${LD} directly.

DES
--=20
Dag-Erling Sm=C3=B8rgrav - des@des.no



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?861su6ont5.fsf>