libtool
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: TODO


From: Daniel Reed
Subject: Re: TODO
Date: Mon, 15 Nov 2004 22:21:16 -0500 (EST)

On 2004-11-15T19:27-0600, Bob Friesenhahn wrote:
) >> Yes.  When you're making a distribution, Libtool's behaviour of directly
) >> linking indirect-dependencies is insane.  For a SONAME change to a
) >> library deep in the stack, that only affects the library immediately
) >> above it, you suddenly need to rebuild your entire desktop environment.

Iteration 1:

libgeneral provides general_utility().

libadmiral provides admiral_electric() and admiral_water().

libcadet provides cadet_dance(), which uses general_utility() and
admiral_electric().

service uses cadet_dance() and admiral_water() in its main().


libcadet is linked to libgeneral and libadmiral.

service is linked to libcadet and libadmiral.

The resulting service executable is indirectly linked to libgeneral to
satisfy libcadet's dependency.


Iteration 2:

libcadet is changed to use libgeneral2's general2_utility().

service is now indirectly linked to libgeneral2 to satisfy libcadet's
dependency, and libgeneral is no longer in use.



(21:43)address@hidden:~/test> make service COMPILE=gcc LINK=gcc
gcc libgeneral.c -c -o libgeneral.o
gcc libgeneral.o -shared -o libgeneral.so
gcc libadmiral.c -c -o libadmiral.o
gcc libadmiral.o -shared -o libadmiral.so
gcc libcadet.c -c -o libcadet.o
gcc libcadet.o -shared -o libcadet.so -L. -Wl,-rpath,. -lgeneral -ladmiral
gcc service.c -c -o service.o
gcc service.o -o service -L. -Wl,-rpath,. -lcadet -ladmiral
(21:44)address@hidden:~/test> ldd service
        libcadet.so => ./libcadet.so (0xf6ffe000)
        libadmiral.so => ./libadmiral.so (0xf6ffb000)
        libc.so.6 => /lib/tls/libc.so.6 (0x00703000)
        libgeneral.so => ./libgeneral.so (0xf6fd9000)
        /lib/ld-linux.so.2 (0x006ea000)
(21:44)address@hidden:~/test> ./service
main
cadet_dance
general_utility
admiral_electric
admiral_water
(21:44)address@hidden:~/test>


The base case is sane.


(21:46)address@hidden:~/test> make service COMPILE="libtool --mode=compile gcc" 
LINK="libtool --mode=link gcc"
libtool --mode=compile gcc libgeneral.c -c -o libgeneral.o
mkdir .libs
 gcc libgeneral.c -c  -fPIC -DPIC -o .libs/libgeneral.o
 gcc libgeneral.c -c -o libgeneral.o >/dev/null 2>&1
libtool --mode=link gcc libgeneral.o -shared -o libgeneral.so
gcc libgeneral.o -shared -o libgeneral.so
libtool --mode=compile gcc libadmiral.c -c -o libadmiral.o
 gcc libadmiral.c -c  -fPIC -DPIC -o .libs/libadmiral.o
 gcc libadmiral.c -c -o libadmiral.o >/dev/null 2>&1
libtool --mode=link gcc libadmiral.o -shared -o libadmiral.so
gcc libadmiral.o -shared -o libadmiral.so
libtool --mode=compile gcc libcadet.c -c -o libcadet.o
 gcc libcadet.c -c  -fPIC -DPIC -o .libs/libcadet.o
 gcc libcadet.c -c -o libcadet.o >/dev/null 2>&1
libtool --mode=link gcc libcadet.o -shared -o libcadet.so -L. -Wl,-rpath,. 
-lgeneral -ladmiral
gcc libcadet.o -shared -o libcadet.so -Wl,-rpath -Wl,.  
-L/home/boston/dreed/test -lgeneral -ladmiral
libtool --mode=compile gcc service.c -c -o service.o
 gcc service.c -c  -fPIC -DPIC -o .libs/service.o
 gcc service.c -c -o service.o >/dev/null 2>&1
libtool --mode=link gcc service.o -o service -L. -Wl,-rpath,. -lcadet -ladmiral
gcc service.o -o service -Wl,-rpath -Wl,.  -L/home/boston/dreed/test -lcadet 
-ladmiral
(21:46)address@hidden:~/test> ldd service
        libcadet.so => ./libcadet.so (0xf6ffe000)
        libadmiral.so => ./libadmiral.so (0xf6ffb000)
        libc.so.6 => /lib/tls/libc.so.6 (0x00703000)
        libgeneral.so => ./libgeneral.so (0xf6fd9000)
        /lib/ld-linux.so.2 (0x006ea000)
(21:46)address@hidden:~/test>


Looks good. Let's try iteration 2's change...


(21:50)address@hidden:~/test> make service2 COMPILE="libtool --mode=compile 
gcc" LINK="libtool --mode=link gcc"
libtool --mode=compile gcc libgeneral2.c -c -o libgeneral2.o
 gcc libgeneral2.c -c  -fPIC -DPIC -o .libs/libgeneral2.o
 gcc libgeneral2.c -c -o libgeneral2.o >/dev/null 2>&1
libtool --mode=link gcc libgeneral2.o -shared -o libgeneral2.so
gcc libgeneral2.o -shared -o libgeneral2.so
libtool --mode=compile gcc libcadet2.c -c -o libcadet2.o
 gcc libcadet2.c -c  -fPIC -DPIC -o .libs/libcadet2.o
 gcc libcadet2.c -c -o libcadet2.o >/dev/null 2>&1
libtool --mode=link gcc libcadet2.o -shared -o libcadet.so -L. -Wl,-rpath,. 
-lgeneral2 -ladmiral
gcc libcadet2.o -shared -o libcadet.so -Wl,-rpath -Wl,.  
-L/home/boston/dreed/test -lgeneral2 -ladmiral
(21:50)address@hidden:~/test> ldd service
        libcadet.so => ./libcadet.so (0xf6ffe000)
        libadmiral.so => ./libadmiral.so (0xf6ffb000)
        libc.so.6 => /lib/tls/libc.so.6 (0x00703000)
        libgeneral2.so => ./libgeneral2.so (0xf6fd9000)
        /lib/ld-linux.so.2 (0x006ea000)
(21:50)address@hidden:~/test> ./service
main
cadet_dance
general2_utility
admiral_electric
admiral_water
(21:50)address@hidden:~/test>


Still good. The service executable is no longer linked to libgeneral.so in
any way and works as expected. Let's try "full blown" Libtool (using .la
files)...


(22:00)address@hidden:~/test> make servicela COMPILE="libtool --mode=compile 
gcc" LINK="libtool --mode=link gcc"
libtool --mode=compile gcc libgeneral.c -c -o libgeneral.lo
mkdir .libs
 gcc libgeneral.c -c  -fPIC -DPIC -o .libs/libgeneral.o
 gcc libgeneral.c -c -o libgeneral.o >/dev/null 2>&1
libtool --mode=link gcc libgeneral.lo -shared -o libgeneral.la -rpath /tmp
gcc -shared  .libs/libgeneral.o   -Wl,-soname -Wl,libgeneral.so.0 -o 
.libs/libgeneral.so.0.0.0
(cd .libs && rm -f libgeneral.so.0 && ln -s libgeneral.so.0.0.0 libgeneral.so.0)
(cd .libs && rm -f libgeneral.so && ln -s libgeneral.so.0.0.0 libgeneral.so)
ar cru .libs/libgeneral.a  libgeneral.o
ranlib .libs/libgeneral.a
creating libgeneral.la
(cd .libs && rm -f libgeneral.la && ln -s ../libgeneral.la libgeneral.la)
libtool --mode=compile gcc libadmiral.c -c -o libadmiral.lo
 gcc libadmiral.c -c  -fPIC -DPIC -o .libs/libadmiral.o
 gcc libadmiral.c -c -o libadmiral.o >/dev/null 2>&1
libtool --mode=link gcc libadmiral.lo -shared -o libadmiral.la -rpath /tmp
gcc -shared  .libs/libadmiral.o   -Wl,-soname -Wl,libadmiral.so.0 -o 
.libs/libadmiral.so.0.0.0
(cd .libs && rm -f libadmiral.so.0 && ln -s libadmiral.so.0.0.0 libadmiral.so.0)
(cd .libs && rm -f libadmiral.so && ln -s libadmiral.so.0.0.0 libadmiral.so)
ar cru .libs/libadmiral.a  libadmiral.o
ranlib .libs/libadmiral.a
creating libadmiral.la
(cd .libs && rm -f libadmiral.la && ln -s ../libadmiral.la libadmiral.la)
libtool --mode=compile gcc libcadet.c -c -o libcadet.lo
 gcc libcadet.c -c  -fPIC -DPIC -o .libs/libcadet.o
 gcc libcadet.c -c -o libcadet.o >/dev/null 2>&1
libtool --mode=link gcc libcadet.lo -shared -o libcadet.la -rpath /tmp -L. 
-Wl,-rpath,. -lgeneral -ladmiral
gcc -shared  .libs/libcadet.o  -Wl,--rpath -Wl,/home/boston/dreed/test/.libs 
-Wl,--rpath -Wl,/tmp -L/home/boston/dreed/test 
/home/boston/dreed/test/.libs/libgeneral.so 
/home/boston/dreed/test/.libs/libadmiral.so  -Wl,-rpath -Wl,. -Wl,-soname 
-Wl,libcadet.so.0 -o .libs/libcadet.so.0.0.0
(cd .libs && rm -f libcadet.so.0 && ln -s libcadet.so.0.0.0 libcadet.so.0)
(cd .libs && rm -f libcadet.so && ln -s libcadet.so.0.0.0 libcadet.so)
ar cru .libs/libcadet.a  libcadet.o
ranlib .libs/libcadet.a
creating libcadet.la
(cd .libs && rm -f libcadet.la && ln -s ../libcadet.la libcadet.la)
libtool --mode=compile gcc service.c -c -o service.o
 gcc service.c -c  -fPIC -DPIC -o .libs/service.o
 gcc service.c -c -o service.o >/dev/null 2>&1
libtool --mode=link gcc service.o -o service -L. -Wl,-rpath,. -lcadet -ladmiral
gcc service.o -o .libs/service -Wl,-rpath -Wl,.  -L/home/boston/dreed/test 
/home/boston/dreed/test/.libs/libcadet.so 
/home/boston/dreed/test/.libs/libgeneral.so 
/home/boston/dreed/test/.libs/libadmiral.so -Wl,--rpath -Wl,/tmp
creating service
(22:00)address@hidden:~/test> env LD_LIBRARY_PATH=.libs ldd .libs/service
        libcadet.so.0 => .libs/libcadet.so.0 (0xf6ffe000)
        libgeneral.so.0 => .libs/libgeneral.so.0 (0xf6ffb000)
        libadmiral.so.0 => .libs/libadmiral.so.0 (0xf6ff9000)
        libc.so.6 => /lib/tls/libc.so.6 (0x00703000)
        /lib/ld-linux.so.2 (0x006ea000)
(22:00)address@hidden:~/test>


We're beginning to see trouble here. Libtool explicitly linked service
against .libs/libgeneral.so, even though I did not specify it as a
dependency of the service executable (no explicit -lgeneral). Let's try
iteration 2...


(22:07)address@hidden:~/test> make servicela2 COMPILE="libtool --mode=compile 
gcc" LINK="libtool --mode=link gcc"
libtool --mode=compile gcc libgeneral2.c -c -o libgeneral2.lo
 gcc libgeneral2.c -c  -fPIC -DPIC -o .libs/libgeneral2.o
 gcc libgeneral2.c -c -o libgeneral2.o >/dev/null 2>&1
libtool --mode=link gcc libgeneral2.lo -shared -o libgeneral2.la -rpath /tmp
gcc -shared  .libs/libgeneral2.o   -Wl,-soname -Wl,libgeneral2.so.0 -o 
.libs/libgeneral2.so.0.0.0
(cd .libs && rm -f libgeneral2.so.0 && ln -s libgeneral2.so.0.0.0 
libgeneral2.so.0)
(cd .libs && rm -f libgeneral2.so && ln -s libgeneral2.so.0.0.0 libgeneral2.so)
ar cru .libs/libgeneral2.a  libgeneral2.o
ranlib .libs/libgeneral2.a
creating libgeneral2.la
(cd .libs && rm -f libgeneral2.la && ln -s ../libgeneral2.la libgeneral2.la)
libtool --mode=compile gcc libcadet2.c -c -o libcadet2.lo
 gcc libcadet2.c -c  -fPIC -DPIC -o .libs/libcadet2.o
 gcc libcadet2.c -c -o libcadet2.o >/dev/null 2>&1
libtool --mode=link gcc libcadet2.lo -shared -o libcadet.la -rpath /tmp -L. 
-Wl,-rpath,. -lgeneral2 -ladmiral
rm -fr  .libs/libcadet.a .libs/libcadet.la .libs/libcadet.lai .libs/libcadet.so 
.libs/libcadet.so.0 .libs/libcadet.so.0.0.0
gcc -shared  .libs/libcadet2.o  -Wl,--rpath -Wl,/home/boston/dreed/test/.libs 
-Wl,--rpath -Wl,/tmp -L/home/boston/dreed/test 
/home/boston/dreed/test/.libs/libgeneral2.so 
/home/boston/dreed/test/.libs/libadmiral.so  -Wl,-rpath -Wl,. -Wl,-soname 
-Wl,libcadet.so.0 -o .libs/libcadet.so.0.0.0
(cd .libs && rm -f libcadet.so.0 && ln -s libcadet.so.0.0.0 libcadet.so.0)
(cd .libs && rm -f libcadet.so && ln -s libcadet.so.0.0.0 libcadet.so)
ar cru .libs/libcadet.a  libcadet2.o
ranlib .libs/libcadet.a
creating libcadet.la
(cd .libs && rm -f libcadet.la && ln -s ../libcadet.la libcadet.la)
(22:07)address@hidden:~/test> env LD_LIBRARY_PATH=.libs ldd .libs/service
        libcadet.so.0 => .libs/libcadet.so.0 (0xf6ffe000)
        libgeneral.so.0 => .libs/libgeneral.so.0 (0xf6ffb000)
        libadmiral.so.0 => .libs/libadmiral.so.0 (0xf6ff9000)
        libc.so.6 => /lib/tls/libc.so.6 (0x00703000)
        libgeneral2.so.0 => /home/boston/dreed/test/.libs/libgeneral2.so.0 
(0xf6fd7000)
        /lib/ld-linux.so.2 (0x006ea000)
(22:07)address@hidden:~/test>

Brilliant. Because service was not recompiled against the new libcadet.la,
it now links against both libgeneral.so and libgeneral2.so (the latter by
way of the new libcadet.so) :(


In situations where only the .so is present, Libtool arguably does the right
thing. (It does not try to guess dependency dependencies based on ldd or
anything like that; it just doesn't link in dependency dependencies.)

In situations where the .la is present, Libtool *does* try to link in
dependency dependencies, even though that isn't necessary.

I believe the point of this proposed change is to eliminate that latter
behavior. It would be a benefit on Linux and similar systems without
directly hindering dissimilar systems (as the behavior would not change on
those systems).

As far as encouraging developers to list dependencies incorrectly or not at
all, in the above scenario, even if the package developer had caused the
service executable's build scripts to link explicitly against its
dependencies dependencies (libgeneral, in this case), it still would have
broken on systems that do not implicitly link dependencies dependencies at
run time (as service would have been explicitly linked with libgeneral, not
libgeneral2, just as with the current Libtool behavior when dealing with .la
files). I do not believe there is a developer education danger from this
proposed change.

-- 
Daniel Reed <address@hidden>    http://people.redhat.com/djr/   
http://naim.n.ml.org/
"Murphy's Law is recursive. Washing your car to make it rain doesn't
work."




reply via email to

[Prev in Thread] Current Thread [Next in Thread]