bug-libtool
[Top][All Lists]
Advanced

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

Re: [patch] 1.5.14: Incorrect archive member renaming with GNU ar


From: Peter O'Gorman
Subject: Re: [patch] 1.5.14: Incorrect archive member renaming with GNU ar
Date: Thu, 07 Apr 2005 22:04:17 +0900
User-agent: Mozilla Thunderbird 1.0 (Macintosh/20041206)

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Peter O'Gorman wrote:
| Maciej W. Rozycki wrote:
| | Hello,
| |
| |  A change dated 2004-12-10 broke handling of archives containing multiple
| | members of the same name for GNU binutils.  Unlike what the relevant
| | ChangeLog entry suggests may be true for all ar implementations, GNU ar
| | actually extracts all matching members.  OTOH, it only deletes first
| | matching ones.  As a result, when renaming archive members, all the new
| | files are really copies of the last member.
| |
|
| Aw crap! Oh well, Alexandre Olivia has a patch, applied to gcc, that avoids
| putting duplicate members in the archive in the first place. Seems like a
| good plan. I'll go look for it.

This is Alexandre Oliva's patch with a test case. OK to apply to branch-1-5
and forward port?

Peter
- --
Peter O'Gorman - http://www.pogma.com
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.0 (Darwin)

iQCVAwUBQlUvz7iDAg3OZTLPAQJ4vQP/XXqJUzII2sbcoT/ywGEdm801e+ikLmDy
uLkl17Ii0EQA5WNuSBMWIPDzOiLGdVpOZr/nz5UuZJSEtJyQbQWyJ6eN6phaIo3O
ImDD7WmRSYcYyaJhF0BzrgZWx8jThvE6d0uKvIjuQtkxSSvMlr6O4uUtSlO4gr0u
5F4gT3CqDMU=
=p3VO
-----END PGP SIGNATURE-----
Index: ChangeLog
from  Alexandre Oliva  <address@hidden>,
        Peter O'Gorman  <address@hidden>

        * ltmain.in: Don't add files with the same base name to an
        archive; rename duplicates instead.
        (func_extract_an_archive): Remove section to deal with duplicate
        base names in an archive.
        * tests/func_extract_archives.test: remove.
        * tests/duplicate_members.test: new test.
        * tests/Makefile.am: Add new test, remove old.

Index: ltmain.in
===================================================================
RCS file: /cvsroot/libtool/libtool/Attic/ltmain.in,v
retrieving revision 1.334.2.65
diff -u -r1.334.2.65 ltmain.in
--- ltmain.in 16 Mar 2005 17:31:02 -0000 1.334.2.65
+++ ltmain.in 7 Apr 2005 12:52:10 -0000
@@ -251,37 +251,14 @@
 {
     f_ex_an_ar_dir="$1"; shift
     f_ex_an_ar_oldlib="$1"
-    f_ex_an_ar_lib=`$echo "X$f_ex_an_ar_oldlib" | $Xsed -e 's%^.*/%%'`
 
     $show "(cd $f_ex_an_ar_dir && $AR x $f_ex_an_ar_oldlib)"
     $run eval "(cd \$f_ex_an_ar_dir && $AR x \$f_ex_an_ar_oldlib)" || exit $?
     if ($AR t "$f_ex_an_ar_oldlib" | sort | sort -uc >/dev/null 2>&1); then
      :
     else
-      $echo "$modename: warning: object name conflicts; renaming object files" 
1>&2
-      $echo "$modename: warning: to ensure that they will not overwrite" 1>&2
-      $show "cp $f_ex_an_ar_oldlib $f_ex_an_ar_dir/$f_ex_an_ar_lib"
-      $run eval "cp \$f_ex_an_ar_oldlib \$f_ex_an_ar_dir/\$f_ex_an_ar_lib"
-      $AR t "$f_ex_an_ar_oldlib" | sort | uniq -c \
-       | $EGREP -v '^[         ]*1[    ]' | while read count name
-      do
-       i=1
-       while test "$i" -le "$count"
-         do
-         # Put our $i before any first dot (extension)
-         # Never overwrite any file
-         name_to="$name"
-         while test "X$name_to" = "X$name" || test -f 
"$f_ex_an_ar_dir/$name_to"
-           do
-           name_to=`$echo "X$name_to" | $Xsed -e "s/\([^.]*\)/\1-$i/"`
-         done
-         $show "(cd $f_ex_an_ar_dir && $AR x  $f_ex_an_ar_lib '$name' && $mv 
'$name' '$name_to')"
-         $run eval "(cd \$f_ex_an_ar_dir && $AR x \$f_ex_an_ar_lib '$name' && 
$mv '$name' '$name_to' && $AR -d \$f_ex_an_ar_lib '$name')" || exit $?
-         i=`expr $i + 1`
-       done
-      done
-      $show "$rm $f_ex_an_ar_dir/$f_ex_an_ar_lib"
-      $run eval "$rm \$f_ex_an_ar_dir/\$f_ex_an_ar_lib"
+      $echo "$modename: ERROR: object name conflicts: 
$f_ex_an_ar_dir/$f_ex_an_ar_oldlib" 1>&2
+      exit $EXIT_FAILURE
     fi
 }
 
@@ -5106,6 +5083,63 @@
       if test -n "$old_archive_from_new_cmds" && test "$build_libtool_libs" = 
yes; then
        cmds=$old_archive_from_new_cmds
       else
+       # POSIX demands no paths to be encoded in archives.  We have
+       # to avoid creating archives with duplicate basenames if we
+       # might have to extract them afterwards, e.g., when creating a
+       # static archive out of a convenience library, or when linking
+       # the entirety of a libtool archive into another (currently
+       # not supported by libtool).
+       if (for obj in $oldobjs
+           do
+             $echo "X$obj" | $Xsed -e 's%^.*/%%'
+           done | sort | sort -uc >/dev/null 2>&1); then
+         :
+       else
+         $echo "copying selected object files to avoid basename conflicts..."
+
+         if test -z "$gentop"; then
+           gentop="$output_objdir/${outputname}x"
+           generated="$generated $gentop"
+
+           $show "${rm}r $gentop"
+           $run ${rm}r "$gentop"
+           $show "$mkdir $gentop"
+           $run $mkdir "$gentop"
+           status=$?
+           if test "$status" -ne 0 && test ! -d "$gentop"; then
+             exit $status
+           fi
+         fi
+
+         save_oldobjs=$oldobjs
+         oldobjs=
+         counter=1
+         for obj in $save_oldobjs
+         do
+           objbase=`$echo "X$obj" | $Xsed -e 's%^.*/%%'`
+           case " $oldobjs " in
+           " ") oldobjs=$obj ;;
+           *[\ /]"$objbase "*)
+             while :; do
+               # Make sure we don't pick an alternate name that also
+               # overlaps.
+               newobj=lt$counter-$objbase
+               counter=`expr $counter + 1`
+               case " $oldobjs " in
+               *[\ /]"$newobj "*) ;;
+               *) if test ! -f "$gentop/$newobj"; then break; fi ;;
+               esac
+             done
+             $show "ln $obj $gentop/$newobj || cp $obj $gentop/$newobj"
+             $run ln "$obj" "$gentop/$newobj" ||
+             $run cp "$obj" "$gentop/$newobj"
+             oldobjs="$oldobjs $gentop/$newobj"
+             ;;
+           *) oldobjs="$oldobjs $obj" ;;
+           esac
+         done
+       fi
+
        eval cmds=\"$old_archive_cmds\"
 
        if len=`expr "X$cmds" : ".*"` &&
@@ -5119,20 +5153,7 @@
          objlist=
          concat_cmds=
          save_oldobjs=$oldobjs
-         # GNU ar 2.10+ was changed to match POSIX; thus no paths are
-         # encoded into archives.  This makes 'ar r' malfunction in
-         # this piecewise linking case whenever conflicting object
-         # names appear in distinct ar calls; check, warn and compensate.
-           if (for obj in $save_oldobjs
-           do
-             $echo "X$obj" | $Xsed -e 's%^.*/%%'
-           done | sort | sort -uc >/dev/null 2>&1); then
-           :
-         else
-           $echo "$modename: warning: object name conflicts; overriding 
AR_FLAGS to 'cq'" 1>&2
-           $echo "$modename: warning: to ensure that POSIX-compatible ar will 
work" 1>&2
-           AR_FLAGS=cq
-         fi
+
          # Is there a better way of finding the last object in the list?
          for obj in $save_oldobjs
          do
Index: tests/Makefile.am
===================================================================
RCS file: /cvsroot/libtool/libtool/tests/Makefile.am,v
retrieving revision 1.32.2.3
diff -u -r1.32.2.3 Makefile.am
--- tests/Makefile.am 26 Jan 2005 17:53:51 -0000 1.32.2.3
+++ tests/Makefile.am 7 Apr 2005 12:52:10 -0000
@@ -46,7 +46,7 @@
        pdemo-make.test pdemo-exec.test pdemo-inst.test \
        mdemo-conf.test mdemo-make.test mdemo2-conf.test \
        mdemo2-make.test mdemo2-exec.test \
-       func_extract_archives.test 
+       duplicate_members.test 
 
 
 if HAVE_CXX
Index: tests/duplicate_members.test
===================================================================
RCS file: tests/duplicate_members.test
diff -N tests/duplicate_members.test
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ tests/duplicate_members.test 7 Apr 2005 12:52:10 -0000
@@ -0,0 +1,58 @@
+#! /bin/sh
+# duplicate members
+
+need_prefix=no
+if test -z "$srcdir"; then
+  srcdir=`echo "$0" | sed 's%/[^/]*$%%'`
+  test "$srcdir" = "$0" && srcdir=.
+  test "${VERBOSE+set}" != "set" && VERBOSE=yes
+fi
+. $srcdir/defs || exit 1
+
+test -d duplicate_members.dir && rm -rf duplicate_members.dir
+mkdir duplicate_members.dir
+# we don't want to use whole_archive_flag_spec, even if available
+sed -e 's|^whole_archive_flag_spec=.*|whole_archive_flag_spec=|g' < $libtool > 
duplicate_members.dir/libtool
+
+cd duplicate_members.dir
+chmod +x ./libtool
+
+for a in 1 2 3 4 5
+do
+  mkdir $a
+  echo "int foo$a() {return $a;}" > $a/a.c
+done
+eval `./libtool --config | grep ^CC`
+
+for a in 1 2 3 4 5
+do
+  ./libtool --mode=compile --tag=CC $CC -c $CFLAGS -o $a/a.lo $a/a.c
+done
+
+./libtool --mode=link --tag=CC $CC $CFLAGS $LDFLAGS -o libconv.la 1/a.lo 
2/a.lo 3/a.lo 4/a.lo 5/a.lo
+
+cat <<EOF > bar.c
+int bar() {
+    int result=foo1() +foo2() +foo3() +foo4() +foo5();
+    return result;
+}
+EOF
+
+./libtool --mode=compile --tag=CC $CC -c $CFLAGS -o bar.lo bar.c
+./libtool --mode=link --tag=CC $CC $CFLAGS $LDFLAGS -o libbar.la bar.lo 
libconv.la -rpath /notexist
+
+cat <<EOF > main.c
+int bar();
+int main()
+{
+if (bar() == 15) return 0;
+return 1;
+}
+EOF
+./libtool --mode=compile --tag=CC $CC -c $CFLAGS -o main.lo main.c
+./libtool --mode=link --tag=CC $CC $CFLAGS $LDFLAGS -o main main.lo ./libbar.la
+./main
+retcode=$?
+cd ..
+rm -rf duplicate_members.dir
+exit $retcode
Index: tests/func_extract_archives.test
===================================================================
RCS file: tests/func_extract_archives.test
diff -N tests/func_extract_archives.test
--- tests/func_extract_archives.test 5 Feb 2005 13:59:49 -0000 1.1.2.3
+++ /dev/null   1 Jan 1970 00:00:00 -0000
@@ -1,46 +0,0 @@
-#! /bin/sh
-# func_extract_archives.test
-
-need_prefix=no
-if test -z "$srcdir"; then
-  srcdir=`echo "$0" | sed 's%/[^/]*$%%'`
-  test "$srcdir" = "$0" && srcdir=.
-  test "${VERBOSE+set}" != "set" && VERBOSE=yes
-fi
-. $srcdir/defs || exit 1
-rm -f foo.o bar.o libfoo.a
-SED=${SED-sed}
-Xsed="$SED -e s/^X//"
-for afile in baz foobar foobaz
-do
-    echo "$afile" > $afile.o
-    ar -q libfoo.a $afile.o
-    rm -f $afile.o
-done
-for anum in 1 2 3 4 5 6 7 8 9 10 11 12
-do
-    echo "foo $anum" > foo.o
-    echo "bar $anum" > bar.o
-    ar -q libfoo.a foo.o bar.o
-done
-test -d .libs || mkdir .libs
-
-eval "`$SED -n -e '/^# Shell function definitions:'$z'$/,/^# End of Shell 
function definitions'$z'$/p' < $libtool`"
-
-modename=libtool
-show=echo
-run=
-mkdir=mkdir
-rm="rm -f"
-mv=mv
-echo=echo
-AR=${AR-ar}
-func_extract_archives ".libs/libfoo" "libfoo.a"
-for anum in 1 2 3 4 5 6 7 8 9 10 11 12
-do
-  test -f ".libs/libfoo/libfoo.a/foo-$anum.o" || exit 1
-  $EGREP -v "foo-$anum" ".libs/libfoo/libfoo.a/foo-$anum.o" || exit 1
-  rm -f ".libs/libfoo/libfoo.a/foo-$anum.o"
-done
-rm -rf ".libs/libfoo" libfoo.a bar.o foo.o
-exit 0

reply via email to

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