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>