* 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