This is the mail archive of the cygwin@cygwin.com mailing list for the Cygwin project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

libtool: make install DESTDIR + dependent shared libraries = relinkproblem


When using 'make install DESTDIR' to build an installable package (cygwin tarballs, linux rpm's, etc), dependent libraries get relinked against 'old' versions in <prefix> and not against the 'new' version in <destdir>/<prefix>. See attached testcase, and problem description below.

Any ideas on how this problem should be addressed -- other than 'Don't do that' ?

--Chuck

------------------------------------------------------
Demonstrates the problems with dependent shared libraries
and 'make install DESTDIR=...' on cygwin.

This problem affects cygwin AND linux -- and I assume
it affects most other unixes.

To demonstrate the issue, we have two different "releases"
of a package.  This package contains two sharedlibs.
This is obviously a contrived example, but the error HAS
been observed 'in the wild' on cygwin: pcre-4.2.

The 1.0.0 release of the package has the following version
numbers for its libraries:
  libone:  -version-info 1:0:1
  libtwo:  -version-info 2:0:1
libtwo depends on libone.  On cygwin, this results in a
'DLLVER' of 'c' - 'a', or
  libone:  cygone-0.dll
  libtwo:  cygtwo-1.dll
If you have questions about how -version-info works, and how
it interacts with DLL versioning on cygwin, see this page:
http://home.att.net/~perlspinr/libversioning.html

The 1.0.1 release of the package has the following version
numbers for its libraries:
  libone:  -version-info 2:0:0 (*)
  libtwo:  -version-info 2:1:1 (**)
(*) We changed the API of libone (renamed some of its exported
    functions -- one_*_square() were renamed to one_*_SQR() )
    so we increment 'c', reset 'a' to zero  and leave 'r' at zero.
(**) The API of libtwo doesn't change (it didn't happen to USE
     the functions in libone that got renamed), but its internal
     code did change. So, we increment 'r' but leave 'c'
     and 'a' alone.  [If you're interested, the change was
     simply to modify the initial value of one_global_int_var.
     It was 22, it is now 33]
Using the 'c' - 'a' formula, we have
  libone:  cygone-2.dll
  libtwo:  cygtwo-1.dll

The problem manifests when version 1.0.0 has been installed, and
we're trying to build version 1.0.1 using 'make install DESTDIR='

So, here's the test procedure: After unpacking,

   cd destdir-relinklib-demo-1.0.0
   ./bootstrap
   ./configure --prefix=/usr
   make
   make install DESTDIR=`pwd`/inst

So far, no problems.  Now, you need write access to /usr/lib,
/usr/include, and /usr/bin for the next step.

make install

which will install the following files (which probably won't
conflict with anything on your system, but you might want to
check, first)
   /usr/include/destdir-relinklib-demo/libone.h
   /usr/include/destdir-relinklib-demo/libtwo.h
   /usr/lib/libone.a
   /usr/lib/libtwo.a
   /usr/lib/libone.la
   /usr/lib/libtwo.la
   /usr/lib/libone.dll.a
   /usr/lib/libtwo.dll.a
   /usr/bin/cygone-0.dll
   /usr/bin/cygtwo-1.dll

Okay, now it's time to build the 'next release' of
destdir-relinklib-demo. So,

   cd ../destdir-relinklib-demo-1.0.1
   ./bootstrap
   ./configure --prefix=/usr
   make

Stop here.  If you check in libtwo/.libs and use (on cygwin)
'cygcheck cygtwo-1.dll' -- or objdump libtwo*so* on other
unixes -- you'll see that libtwo is indeed linked against
THIS build of libone.  In cygwin, that means
  cygtwo-1.dll depends on cygone-2.dll
Now, do

make install DESTDIR=`pwd`/inst

Then, look once again in libtwo/.libs/ (or in inst/usr/[bin|lib])
and check the shared version of libtwo's dependencies.  On cygwin,
that means 'cygcheck cygtwo-1.dll'

!!! It depends on cygone-0.dll, NOT cygone-2.dll. !!!

That is, on relink, when doing a 'make install DESTDIR', the
dependent library is linked against the dependee in <prefix>/,
not <DESTDIR>/<prefix>!

If you watch the 'make install DESTDIR' output carefully, you'll
see the relink command for libtwo.  On cygwin, it appears as:

/bin/bash ../libtool --mode=install /usr/bin/install -c libtwo.la /usr/src/libtool/devel/DEMO/tmp/destdir-relinklib-demo-1.0.1/inst/usr/lib/libtwo.la
libtool: install: warning: relinking `libtwo.la'
(cd /usr/src/libtool/devel/DEMO/tmp/destdir-relinklib-demo-1.0.1/libtwo; /bin/bash ../libtool --mode=relink gcc -g -O2 -o libtwo.la -rpath /usr/lib -version-info 2:1:1 -no-undefined two.lo ../libone/libone.la -inst-prefix-dir /usr/src/libtool/devel/DEMO/tmp/destdir-relinklib-demo-1.0.1/inst)
gcc -shared .libs/two.o -L/usr/lib -L/usr/src/libtool/devel/DEMO/tmp/destdir-relinklib-demo-1.0.1/inst/usr/lib -lone -o .libs/cygtwo-1.dll -Wl,--image-base=0x10000000 -Wl,--out-implib,.libs/libtwo.dll.a
Info: resolving _one_global_int_var by linking to __imp__one_global_int_var (auto-import)
Creating library file: .libs/libtwo.dll.a


Here's the important bit:
  'gcc -shared  .libs/two.o  -L/usr/lib -L<the instdir>/usr/lib -lone ...'
That is, we use -lone to locate libone, and search -L/usr/lib FIRST.

Now, this doesn't happen if you do a straight 'make install' -- because
the dependee library (libone) does actually get installed into <prefix>,
overwriting the old one, before we try to relink libtwo.  So, the
relinked libtwo, in THAT case, gets the proper linkage against cygone-2.dll.

Also, during the initial build of libtwo, we get the 'proper' linkage
because during *build* phase (as opposed to relink phase), the link
command is

/bin/bash ../libtool --mode=link gcc -g -O2 -o libtwo.la -rpath /usr/lib -version-info 2:1:1 -no-undefined two.lo ../libone/libone.la
gcc -shared .libs/two.o ../libone/.libs/libone.dll.a -o .libs/cygtwo-1.dll -Wl,--image-base=0x10000000 -Wl,--out-implib,.libs/libtwo.dll.a
Info: resolving _one_global_int_var by linking to __imp__one_global_int_var (auto-import)
Creating library file: .libs/libtwo.dll.a


Here's the important bit from THAT command:
  'gcc -shared  .libs/two.o  ../libone/.libs/libone.dll.a ...'
That is, we use explicitly use ../libone/.libs/libone.dll.a to
locate libone, and don't mess around with -Lthis -Lthat -lone.

------------------------------------------------------
Now, similar behavior occurs on linux:  The offending relink
command is

libtool: install: warning: relinking `libtwo.la'
(cd /home/cwilson/foo/destdir-relinklib-demo-1.0.1/libtwo; /bin/sh ../libtool --mode=relink gcc -g -O2 -o libtwo.la -rpath /usr/lib -version-info 2:1:1 -no-undefined two.lo ../libone/libone.la -inst-prefix-dir /home/cwilson/foo/destdir-relinklib-demo-1.0.1/inst)
gcc -shared .libs/two.o -L/usr/lib -L/home/cwilson/foo/destdir-relinklib-demo-1.0.1/inst/usr/lib -lone -Wl,-soname -Wl,libtwo.so.1 -o .libs/libtwo.so.1.1.1
/usr/bin/install -c .libs/libtwo.so.1.1.1T /home/cwilson/foo/destdir-relinklib-demo-1.0.1/inst/usr/lib/libtwo.so.1.1.1


Complete with the 'bad'
  'gcc -shared  .libs/two.o  -L/usr/lib -L<the instdir>/usr/lib -lone ...'
(The rebuilt .so is in libtwo/.libs/libtwo.so.1.1.1T and in
<the instdir>/usr/lib/, while the original .so is in
libtwo/.libs/libtwo.so.1.1.1)

objdump -p on the original libtwo.so.1.1.1 shows that it depends on
libone.so.2 -- which is correct -- while the rebuilt libtwo
(libtwo.so.1.1.1T) depends on libone.so.0 -- which is incorrect.
-------------------------------------------------



Attachment: destdir-relink.tar.bz2
Description: BZip2 compressed data

--
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple
Problem reports:       http://cygwin.com/problems.html
Documentation:         http://cygwin.com/docs.html
FAQ:                   http://cygwin.com/faq/

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]