Subject: Re: "-Ldir -lname" vs. "dir/libname.so"
To: Nick Hudson <skrll@netbsd.org>
From: Johnny Lam <jlam@jgrind.org>
List: tech-toolchain
Date: 03/18/2002 13:42:33
I'm going to try to reformulate with a simpler example to try to make
clearer what I perceive to be the problem.  The following example is
distilled from something I received in private email regarding problems
with packages having hidden dependencies on devel/gettext-lib.

Consider a package that builds and installs two things: libbase.la and
libext.la.  Also, libext.la is linked against libbase.la and
/usr/lib/libintl.so.0.0.  Also suppose I have the following on my system:

	/usr/lib/libintl.so.0.0		# from the Citrus project
	/usr/lib/libintl.so.0		# only on ELF
	/usr/lib/libintl.so		# only on ELF

	/usr/pkg/lib/libintl.so.1.0	# from the GNU gettext project
	/usr/pkg/lib/libintl.so.1	# only on ELF
	/usr/pkg/lib/libintl.so		# only on ELF

I'm a developer, so I installed the GNU gettext libintl.so to check for
compatibility problems with using the Citrus one.

Now, when libext.la is linked at _build_ time, the following command is
executed:

	libtool cc -o libext.la -rpath /tmp/lib \
		libbase.la \
		-Wl,-R/usr/pkg/lib -L/buildlink/lib -lintl

which is converted on an ELF system (line-by-line) into:

	cc -shared -Wl,-soname -Wl,libext.so.0 -o .libs/libext.so.0.0 \
		-Wl,-rpath -Wl,/path/to/.libs -L./.libs -lbase \
		-Wl,-R/usr/pkg/lib -L/buildlink/lib -lintl

Note that libext.so.0.0 links against the libraries that we want, namely
libbase.so.0.0 from the uninstalled location and libintl.so from /usr/lib
(assuming that /buildlink/lib/libintl.so points to /usr/lib/libintl.so).
Note also that an extra path /path/to/.libs is added to the run-time
search path so that we can link and run programs, e.g. regression tests,
against libext.la without needing to install anything.

Now at _install_ time, a relink command is automatically executed by
libtool that converts into:

	cc -shared -Wl,-soname -Wl,libext.so.0 -o .libs/libext.so.0.0 \
		-Wl,-rpath -Wl,/usr/pkg/lib -L/usr/pkg/lib -lbase \
		-Wl,-R/usr/pkg/lib -L/buildlink/lib -lintl

This new libext.so.0.0 no longer links against the correct libintl.so.
We want the one that is in /buildlink/lib, but we get the one from
/usr/pkg/lib.  I have a patch for libtool that causes the following
to be executed at relink time instead:

	cc -shared -Wl,-soname -Wl,libext.so.0 -o .libs/libext.so.0.0 \
		-Wl,-rpath -Wl,/usr/pkg/lib /usr/pkg/lib/libbase.so \
		-Wl,-R/usr/pkg/lib -L/buildlink/lib -lintl

Now we link against the correct libintl.so again.  However, I don't
have a good fix for a.out systems, as with my proposed change to libtool,
the relink command executed is:

	ld -Bshareable -o .libs/libext.so.0.0 \
		-R/usr/pkg/lib /usr/pkg/lib/libbase.so.0.0 \
		-R/usr/pkg/lib -L/buildlink/lib -lintl

Here again, we link against the correct libraries, but unfortunately,
this breaks if we link programs against libext.so.0.0, but then update
the libbase.so shared library to 0.1, because (as tested on NetBSD/mac68k)
the program hardcodes needing exactly the 0.0 version of libbase.so.  I
uncertain what the proper workaround on a.out systems looks like.

	Cheers,

	-- Johnny Lam <jlam@jgrind.org>