* libltdl/m4/libtool.m4 (_LT_CHECK_SHAREDLIB_FROM_LINKLIB):
New macro sets sharedlib_from_linklib_cmd variable.
(_LT_DECL_DLLTOOL): New macro ensures DLLTOOL is always set.
* libltdl/config/ltmain.m4sh (func_generate_dlsyms): Use
$sharedlib_from_linklib_cmd instead of directly invoking
func_win32_dllname_for_implib when
libfile_$(transliterated implib name) does not exist.
(func_win32_libid): Accomodate pei-i386 import libs
as well as pe-i386.
(func_dlltool_identify): Removed.
(func_win32_dllname_for_implib): Removed. Replaced by...
(func_cygming_dll_for_implib): this,
(func_cygming_dll_for_implib_fallback): this,
(func_cygming_dll_for_implib_core): ...and this.
(func_cygming_implib_p): New function.
(func_cygming_ms_implib_p): New function.
---
This is a follow-on to:
http://lists.gnu.org/archive/html/libtool-patches/2009-01/msg00002.html

If the end result of these two patches is acceptable, I'll squash it 
before merging to master.  But, here's the rationale for the changes
here:
 1) Try to make it easier for Peter to add MSVC-specific versions
    of this functionality, by invoking the IMPLIB-to-DLL function
    via a libtool variable (*)
 2) Set that variable during configure
 3) While we're at it, even on cygwin/mingw, decide whether to
    use dlltool --identify or the nm/objdump-based shell script
    "fallback" also at configure time
 4) Since Danny Smith reports that even on mingw, ld can link
    against MS-style import libraries, then ensure that both
    versions of the IMPLIB-to-DLL function can perform properly
    whether the implib is binutils- or ms- style.
    a) dlltool (two patches, both already accepted):
       http://sourceware.org/ml/binutils/2009-01/msg00120.html
       http://sourceware.org/ml/binutils/2009-01/msg00179.html
    b) improved sed-fu in func_cygming_dll_for_implib_core
       with wrapper func_cygming_dll_for_implib_fallback.
       Wrapper determines `style' of the implib, and invokes
       the *_core() function with the appropriate arguments.

(*) Peter could implement two functions for msvc, as well: one
that directly invokes the new dllname application, and the other
which uses different, msvc-specific sed-fu on the output of
$NM (which in this case is actually `dumpbin --symbols'?). Then
in _LT_CHECK_SHAREDLIB_FROM_LINKLIB the determination could be
make as to which one to use, when $host is mingw and $CC is msvc.
Of course, if dllname does not become an official part of msys, 
then Peter's additions to _LT_CHECK_SHAREDLIB_FROM_LINKLIB
would just set $sharedlib_from_linklib_cmd to the function 
containing the msvc-sed-fu.

Limitation: although I have beat this sed-fu to death *outside*
of libtool, and am pretty confident it works well, there is no
actual test of that code in the testsuite. This is because well-
behaved libtool clients -- and our tests are actually well-behaved
in this regard -- will only -dlpreopen *libtool*-built libraries.
In that case, Ralf's suggested libfile_$(transliterated implib name)
is used, because we have the .la file available which allows that
shortcut.  The only time we need `dlltool --identify' is when
dlpreopening a non-libtool implib, where we have no .la file.
And the sed-fu is a fallback to THAT fallback.

Also: is there someplace that libtool variables like 
$sharedlib_from_linklib_cmd should be documented?

I did run configure and the demo-shared/demo-make/demo-exec tests
with (a) "old" --identify-less dlltool and (b) "new" --identify
dlltool. In each case, configure "picked" the correct function
for $sharedlib_from_linklib_cmd, and those tests passed.

Full test suite on cygwin in progress. Assuming it passes,
ok for squash and push?

Next step: make an actual "package" out of impgen2/dllname,
upload to mingw/sourceforge, and see if I can't convince Cesar
and Keith that it should be included in the 'base' MSYS for
release 1.0.11.

--
Chuck


 libltdl/config/ltmain.m4sh |  200 +++++++++++++++++++++++++-------------------
 libltdl/m4/libtool.m4      |   50 +++++++++++
 2 files changed, 165 insertions(+), 85 deletions(-)

diff --git a/libltdl/config/ltmain.m4sh b/libltdl/config/ltmain.m4sh
index 503457c..d701436 100644
--- a/libltdl/config/ltmain.m4sh
+++ b/libltdl/config/ltmain.m4sh
@@ -2016,8 +2016,8 @@ extern \"C\" {
                    dlprefile_dlbasename="$func_basename_result"
                  else
                    # no lafile. user explicitly requested -dlpreopen <import 
library>.
-                   func_win32_dllname_for_implib "$dlprefile"
-                   dlprefile_dlbasename=$func_win32_dllname_for_implib_result
+                   eval '$sharedlib_from_linklib "$dlprefile"'
+                   dlprefile_dlbasename=$sharedlib_from_linklib_result
                  fi
                fi
                $opt_dry_run || {
@@ -2217,7 +2217,7 @@ func_win32_libid ()
     ;;
   *ar\ archive*) # could be an import, or static
     if eval $OBJDUMP -f $1 | $SED -e '10q' 2>/dev/null |
-       $EGREP 'file format (pe-i386(.*architecture: 
i386)?|pe-arm-wince|pe-x86-64)' >/dev/null; then
+       $EGREP 'file format (pei?-i386(.*architecture: 
i386)?|pe-arm-wince|pe-x86-64)' >/dev/null; then
       win32_nmres=`eval $NM -f posix -A $1 |
        $SED -n -e '
            1,100{
@@ -2247,99 +2247,129 @@ func_win32_libid ()
   $ECHO "$win32_libid_type"
 }
 
-# func_dlltool_identify
-# Determine if $DLLTOOL supports the --identify option
-func_dlltool_identify ()
+# func_cygming_dll_for_implib ARG
+#
+# Platform-specific function to extract the
+# name of the DLL associated with the specified
+# import library ARG.
+# Invoked by eval'ing the libtool variable
+#    $sharedlib_from_linklib_cmd
+# Result is available in the variable
+#    $sharedlib_from_linklib_result
+func_cygming_dll_for_implib ()
 {
   $opt_debug
-  if test -z "$func_dlltool_identify_result"; then
-    case `$DLLTOOL --help` in
-    *--identify*) func_dlltool_identify_result=: ;;
-    *) func_dlltool_identify_result=false ;;
-    esac
-  fi
-  $func_dlltool_identify_result
+  sharedlib_from_linklib_result=`$DLLTOOL --identify-strict --identify "$1"`
 }
 
-# func_win32_dllname_for_implib implib
-# Obtain the name of the DLL associated with the
-# specified import library. Result is available
-# in $func_win32_dllname_for_implib_result.
+# func_cygming_dll_for_implib_core SECTION_NAME LIBNAMEs
 #
-func_win32_dllname_for_implib ()
+# The is the core of a fallback implementation of a
+# platform-specific function to extract the name of the
+# DLL associated with the specified import library LIBNAME.
+#
+# SECTION_NAME is either .idata$6 or .idata$7, depending
+# on the platform and compiler that created the implib.
+#
+# Echos the name of the DLL associated with the
+# specified import library.
+func_cygming_dll_for_implib_fallback_core ()
 {
   $opt_debug
-  func_win32_dllname_for_implib_result=""
+  $OBJDUMP -s --section "$1" "$2" 2>/dev/null |
+    sed '/^Contents of section '"$1"':/{
+      # Place marker at beginning of archive member dllname section
+      s/.*/====MARK====/
+      p
+      d
+    }
+    # These lines can sometimes be longer than 43 characters, but
+    # are always uninteresting
+    /:[ \t]*file format pe[i]\{,1\}-i386$/d
+    /^In archive [^:]*:/d
+    # Ensure marker is printed
+    /^====MARK====/p
+    # Remove all lines with less than 43 characters
+    /^.\{43\}/!d
+    # From remoaining lines, remove first 43 characters
+    s/^.\{43\}//' |
+    sed -n '
+      # Join marker and all lines until next marker into a single line
+      /^====MARK====/ b para
+      H
+      $ b para
+      b
+      :para
+      x
+      s/\n//g
+      # Remove the marker
+      s/^====MARK====//
+      # Remove trailing dots and whitespace
+      s/[\. \t]*$//
+      # Print
+      /./p
+      ' |
+    # we now have a list, one entry per line, of the stringified
+    # contents of the appropriate section of all members of the
+    # archive which possess that section. Heuristic: eliminate
+    # all those which have a first or second character that is
+    # a '.' (that is, objdump's representation of an unprintable
+    # character.) This should work for all archives with less than
+    # 0x302f exports -- but will fail for DLLs whose name actually
+    # begins with a literal '.' or a single character followed by
+    # a '.'.
+    #
+    # Of those that remain, print the first one.
+    sed -e '/^\./d' -e '/^.\./d' | sed -n -e '1p'
+}
 
-  if func_dlltool_identify ; then
-    func_win32_dllname_for_implib_result=`$DLLTOOL --identify "$1" 2>/dev/null`
-    # if this fails, the fallback code is unlikely to succeed, so
-    # we don't bother...
-  else
-    # use fallback dlltool does not have the --identify option.
-    # make sure argument is actually an import library
-    if func_win32_import_lib_p "$1"; then
-      func_warn "Using fallback code to determine dllname for $1; consider 
updating binutils to version 2.20 (2.19.50.20081115), or newer."
-      # gcc puts dllname in the .idata$7 section of ONE member
-      # of the import library -- but the name of that member is
-      # random. No other member contains an .idata$7 section.
-      # So, use objdump to print the contents. We get something
-      # like the following (blank lines elided):
-      #
-      #  |In archive /usr/lib/libncurses++.dll.a:
-      #  |d000253.o:     file format pe-i386
-      #  |Contents of section .idata$7:
-      #  | 0000 6379676e 63757273 65732b2b 2d382e64  cygncurses++-8.d
-      #  | 0010 6c6c0000                             ll..____________
-      #  |d000006.o:     file format pe-i386
-      #  |d000252.o:     file format pe-i386
-      #  |Contents of section .idata$7:
-      #  | 0000 00000000                             ....____________
-      #
-      # where '_' represents a space character. So, we delete all
-      # lines that have less than 43 characters, and chomp the
-      # first 43 characters of the remaining lines. This gives us
-      #
-      #  |cygncurses++-8.d
-      #  |ll..____________
-      #  |....____________
-      #
-      # We are not guaranteed that the name we want is first. So,
-      # remove all newlines, then remove all sequences of two
-      # or more . characters, then remove all sequences of two
-      # or more whitespace characters. Finally, remove leading and
-      # trailing whitespace. This would be simpler if we could
-      # assume that the dllname does not contain whitespace, but we
-      # DO assume the dllname doesn't contain *multiple* adjacent
-      # whitespace, nor *multiple* adjacent . characters.
-
-      func_win32_dllname_for_implib_result=`$OBJDUMP -s --section '.idata$7' 
"$1" |
-        $SED '/^[^      ]*\.o:/{
-           s/.*//
-           p
-           d
-         }
-         /^.\{43\}/!d
-         s/^.\{43\}//' |
-        $SED -n '
-         :more
-         N
-         /\n$/b work
-         $!b more
-         :work
-         s/\n//g
-         s/\.\.\.*//g
-         s/[      ][      ][      ]*//g; s/^[     ]*//; s/[       ]*$//
-         /./{
-           p
-           q
-         }
-         '`
-    fi
-  fi
+# func_cygming_implib_p ARG
+# This predicate returns with zero status (TRUE) if
+# ARG is a GNU/binutils-style import library. Returns
+# with nonzero status (FALSE) otherwise.
+func_cygming_implib_p ()
+{
+  $opt_debug
+  func_cygming_implib_tmp=`eval "\$NM \$1 | \$global_symbol_pipe | \$EGREP ' 
(_head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname)\\\$'"`
+  test -n "$func_cygming_implib_tmp"
 }
 
+# func_cygming_ms_implib_p ARG
+# This predicate returns with zero status (TRUE) if
+# ARG is an MS-style import library. Returns
+# with nonzero status (FALSE) otherwise.
+func_cygming_ms_implib_p ()
+{
+  $opt_debug
+  func_cygming_ms_implib_tmp=`eval "\$NM \$1 | \$global_symbol_pipe | grep 
'_NULL_IMPORT_DESCRIPTOR'"`
+  test -n "$func_cygming_ms_implib_tmp"
+}
 
+# func_cygming_dll_for_implib_fallback ARG
+# Platform-specific function to extract the
+# name of the DLL associated with the specified
+# import library ARG.
+#
+# This fallback implementation is for use when $DLLTOOL
+# does not support the --identify-strict option.
+# Invoked by eval'ing the libtool variable
+#    $sharedlib_from_linklib_cmd
+# Result is available in the variable
+#    $sharedlib_from_linklib_result
+func_cygming_dll_for_implib_fallback ()
+{
+  $opt_debug
+  if func_cygming_implib_p "$1" ; then
+    # binutils import library
+    sharedlib_from_linklib_result=`func_cygming_dll_for_implib_fallback_core 
'.idata$7' "$1"`
+  elif func_cygming_ms_implib_p "$1" ; then
+    # ms-generated import library
+    sharedlib_from_linklib_result=`func_cygming_dll_for_implib_fallback_core 
'.idata$6' "$1"`
+  else
+    # unknown
+    sharedlib_from_linklib_result=""
+  fi
+}
 
 
 # func_extract_an_archive dir oldlib
diff --git a/libltdl/m4/libtool.m4 b/libltdl/m4/libtool.m4
index 3f658ac..bf76bbe 100644
--- a/libltdl/m4/libtool.m4
+++ b/libltdl/m4/libtool.m4
@@ -168,6 +168,7 @@ m4_require([_LT_FILEUTILS_DEFAULTS])dnl
 m4_require([_LT_CHECK_SHELL_FEATURES])dnl
 m4_require([_LT_CMD_RELOAD])dnl
 m4_require([_LT_CHECK_MAGIC_METHOD])dnl
+m4_require([_LT_CHECK_SHAREDLIB_FROM_LINKLIB])dnl
 m4_require([_LT_CMD_OLD_ARCHIVE])dnl
 m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl
 
@@ -3190,6 +3191,45 @@ dnl aclocal-1.4 backwards compatibility:
 dnl AC_DEFUN([AM_PROG_NM], [])
 dnl AC_DEFUN([AC_PROG_NM], [])
 
+# _LT_CHECK_SHAREDLIB_FROM_LINKLIB
+# ----------------------
+# how to determine the name of the shared library
+# associated with a specific link library.
+#  -- PORTME fill in with the dynamic library characteristics
+m4_defun([_LT_CHECK_SHAREDLIB_FROM_LINKLIB],
+[m4_require([_LT_DECL_EGREP])
+m4_require([_LT_DECL_OBJDUMP])
+m4_require([_LT_DECL_DLLTOOL])
+AC_CACHE_CHECK([how to associate runtime and link libraries],
+lt_cv_sharedlib_from_linklib_cmd,
+[lt_cv_sharedlib_from_linklib_cmd='unknown'
+
+case $host_os in
+cygwin* | mingw* | pw32* | cegcc*)
+  # two different shell functions defined in ltmain.sh
+  # decide which to use based on capabilities of $DLLTOOL
+  case `$DLLTOOL --help 2>&1` in
+  *--identify-strict*)
+    lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib
+    ;;
+  *)
+    lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib_fallback
+    ;;
+  esac
+  ;;
+*)
+  # fallback: assume linklib IS sharedlib
+  lt_cv_sharedlib_from_linklib_cmd="$ECHO"
+  ;;
+esac
+])
+sharedlib_from_linklib_cmd=$lt_cv_sharedlib_from_linklib_cmd
+test -z "$sharedlib_from_linklib_cmd" && sharedlib_from_linklib_cmd=$ECHO
+
+_LT_DECL([], [sharedlib_from_linklib_cmd], [1],
+    [Command to associate shared and link libraries])
+])# _LT_CHECK_SHAREDLIB_FROM_LINKLIB
+
 
 # LT_LIB_M
 # --------
@@ -6970,6 +7010,16 @@ _LT_DECL([], [OBJDUMP], [1], [An object symbol dumper])
 AC_SUBST([OBJDUMP])
 ])
 
+# _LT_DECL_DLLTOOL
+# --------------
+# If we don't have a new enough Autoconf to choose the best dlltool
+# available, choose the one first in the user's PATH.
+m4_defun([_LT_DECL_DLLTOOL],
+[AC_CHECK_TOOL(DLLTOOL, dlltool, false)
+test -z "$DLLTOOL" && DLLTOOL=dlltool
+_LT_DECL([], [DLLTOOL], [1], [DLL creation program])
+AC_SUBST([DLLTOOL])
+])
 
 # _LT_DECL_SED
 # ------------
-- 
1.6.0.4



Reply via email to