* libltdl/config/general.m4sh: Adjust copyright date. (func_tr_sh): New function. * libltdl/config/ltmain.m4sh: Adjust copyright date. (func_dlltool_identify): New function. (func_win32_dllname_for_implib): New function. (func_generate_dlsyms) [cygwin|mingw]: Obtain DLL name corresponding to import library by using value stored in unique variable libfile_$(transliterated implib name). If that fails, use func_win32_dllname_for_implib to extract DLL name from import library directly. Also, properly extract dlsyms from the import library. (func_mode_link) [cygwin|mingw]: Prefer to dlpreopen DLLs over static libs when both are available. When dlpreopening DLLs, Use linklib (that is, import lib) as dlpreopen file, rather than DLL. Store name of associated la file in unique variable libfile_$(transliterated implib name) for later use. * libltdl/m4/libtool.m4: Adjust copyright date. (_LT_COPYING): Adjust copyright date. (_LT_CMD_GLOBAL_SYMBOLS): adjust sed expressions for lt_cv_sys_global_symbol_to_c_name_address and lt_cv_sys_global_symbol_to_c_name_address_lib_prefix as trailing space after module name is optional. (_LT_LINKER_SHLIBS) [cygwin|mingw][C++]: Set exclude_expsyms correctly for $host. Simplify regular expression in export_symbols_cmds. (_LT_LINKER_SHLIBS) [cygwin|mingw|pw32][C]: Set exclude_expsyms correctly for $host. Enable export_symbols_cmds to identify DATA exports by _nm_ prefix. ---
This is a revised version of patch(es) posted here http://lists.gnu.org/archive/html/libtool-patches/2008-11/msg00019.html and here: http://lists.gnu.org/archive/html/libtool-patches/2009-01/msg00001.html In response to a bug reported here: http://lists.gnu.org/archive/html/bug-libtool/2008-05/msg00054.html Please see those threads for a discussion of the need for this patch and the approach taken here. One change reflected in the patch below, but not discussed in the preceeding threads, is that for systems-supporting-PE-DLLs (e.g. cygwin, mingw, cegcc), the linker will automatically link against the import library instead of the static library if both are present in the search path. However, earlier versions of this patch -- and indeed, un-patched libtool -- would, in the both-are-present case, extract symbols from the static library always, even tho the final dlpreopen link was against the import library. This situation led to an erroneous symbol list: lt__PROGRAM__LTX_preloaded_symbols[] = { { "@PROGRAM@", (void *) 0 }, {"libhello.a", (void *) 0}, <<<< HERE {"nothing", (void *) ¬hing}, {"hello", (void *) &hello}, {"foo", (void *) &foo}, {0, (void *) 0} }; when the correct symbol list should be: lt__PROGRAM__LTX_preloaded_symbols[] = { { "@PROGRAM@", (void *) 0 }, {"cyghello-2.dll", (void *) 0}, <<<< HERE {"nothing", (void *) ¬hing}, {"hello", (void *) &hello}, {"foo", (void *) &foo}, {0, (void *) 0} }; The patch below therefore modifies func_generate_dlsyms to prefer the DLL/import library over the static library when both are present -- but only for PE-DLL platforms. Other platforms still prefer to dlpreopen static libraries when both are present. bootstrapped on cygwin, tested the demo-{conf|shared|static} + demo-make + demo-exec test cases with success. Full test suite in progress. ===== libltdl/config/general.m4sh | 15 +++- libltdl/config/ltmain.m4sh | 198 ++++++++++++++++++++++++++++++++++++++----- libltdl/m4/libtool.m4 | 16 ++-- 3 files changed, 201 insertions(+), 28 deletions(-) diff --git a/libltdl/config/general.m4sh b/libltdl/config/general.m4sh index 4bc304c..c4de91a 100644 --- a/libltdl/config/general.m4sh +++ b/libltdl/config/general.m4sh @@ -1,6 +1,6 @@ m4_if([general.m4sh -- general shell script boiler plate -*- Autoconf -*- - Copyright (C) 2004, 2005, 2007, 2008 Free Software Foundation, Inc. + Copyright (C) 2004, 2005, 2007, 2008, 2009 Free Software Foundation, Inc. Written by Gary V. Vaughan, 2004 This file is part of GNU Cvs-utils. @@ -412,5 +412,18 @@ func_show_eval_locale () fi fi } + +# func_tr_sh +# turn $1 into a string suitable for a shell variable name +# result is stored in $func_tr_sh_result +func_tr_sh () +{ + func_tr_sh_result=`echo "$1" | $SED -e 's/[^A-Za-z0-9_]/_/g'` + # ensure result begins with non-digit + case "$func_tr_sh_result" in + [A-Za-z_][A-Za-z0-9_] ) ;; + * ) func_tr_sh_result=_$func_tr_sh_result ;; + esac +} ]]) diff --git a/libltdl/config/ltmain.m4sh b/libltdl/config/ltmain.m4sh index 20ca07b..503457c 100644 --- a/libltdl/config/ltmain.m4sh +++ b/libltdl/config/ltmain.m4sh @@ -5,7 +5,7 @@ m4_divert_push([SCRIPT])# @configure_input@ # Written by Gordon Matzigkeit <g...@gnu.ai.mit.edu>, 1996 # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, -# 2006, 2007, 2008 Free Software Foundation, Inc. +# 2006, 2007, 2008, 2009 Free Software Foundation, Inc. # This is free software; see the source for copying conditions. There is NO # warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. @@ -1988,7 +1988,7 @@ extern \"C\" { eval '$GREP -f "$output_objdir/$outputname.exp" < "$nlist" > "$nlist"T' eval '$MV "$nlist"T "$nlist"' case $host in - *cygwin | *mingw* | *cegcc* ) + *cygwin* | *mingw* | *cegcc* ) eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' eval 'cat "$nlist" >> "$output_objdir/$outputname.def"' ;; @@ -2001,10 +2001,49 @@ extern \"C\" { func_verbose "extracting global C symbols from \`$dlprefile'" func_basename "$dlprefile" name="$func_basename_result" - $opt_dry_run || { - eval '$ECHO ": $name " >> "$nlist"' - eval "$NM $dlprefile 2>/dev/null | $global_symbol_pipe >> '$nlist'" - } + case $host in + *cygwin* | *mingw* | *cegcc* ) + # if an import library, we need to obtain dlname + if func_win32_import_lib_p "$dlprefile"; then + func_tr_sh "$dlprefile" + eval "curr_lafile=\$libfile_$func_tr_sh_result" + dlprefile_dlbasename="" + if test -n "$curr_lafile" && func_lalib_p "$curr_lafile"; then + # Use subshell, to avoid clobbering current variable values + dlprefile_dlname=`source "$curr_lafile" && echo "$dlname"` + if test -n "$dlprefile_dlname" ; then + func_basename "$dlprefile_dlname" + 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 + fi + fi + $opt_dry_run || { + if test -n "$dlprefile_dlbasename" ; then + eval '$ECHO ": $dlprefile_dlbasename" >> "$nlist"' + else + func_warning "Could not compute DLL name from $name" + eval '$ECHO ": $name " >> "$nlist"' + fi + eval "$NM $dlprefile 2>/dev/null | $global_symbol_pipe | + $SED -e '/I __imp/d' -e 's/I __nm_/D /;s/_nm__//' >> '$nlist'" + } + else # not an import lib + $opt_dry_run || { + eval '$ECHO ": $name " >> "$nlist"' + eval "$NM $dlprefile 2>/dev/null | $global_symbol_pipe >> '$nlist'" + } + fi + ;; + *) + $opt_dry_run || { + eval '$ECHO ": $name " >> "$nlist"' + eval "$NM $dlprefile 2>/dev/null | $global_symbol_pipe >> '$nlist'" + } + ;; + esac done $opt_dry_run || { @@ -2208,6 +2247,99 @@ func_win32_libid () $ECHO "$win32_libid_type" } +# func_dlltool_identify +# Determine if $DLLTOOL supports the --identify option +func_dlltool_identify () +{ + $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 +} + +# 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_win32_dllname_for_implib () +{ + $opt_debug + func_win32_dllname_for_implib_result="" + + 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_extract_an_archive dir oldlib @@ -5172,20 +5304,46 @@ func_mode_link () if test -z "$libdir" && test "$linkmode" = prog; then func_fatal_error "only libraries may -dlpreopen a convenience library: \`$lib'" fi - # Prefer using a static library (so that no silly _DYNAMIC symbols - # are required to link). - if test -n "$old_library"; then - newdlprefiles="$newdlprefiles $dir/$old_library" - # Keep a list of preopened convenience libraries to check - # that they are being used correctly in the link pass. - test -z "$libdir" && \ - dlpreconveniencelibs="$dlpreconveniencelibs $dir/$old_library" - # Otherwise, use the dlname, so that lt_dlopen finds it. - elif test -n "$dlname"; then - newdlprefiles="$newdlprefiles $dir/$dlname" - else - newdlprefiles="$newdlprefiles $dir/$linklib" - fi + case "$host" in + # special handling for platforms with PE-DLLs. + *cygwin* | *mingw* | *cegcc* ) + # Linker will automatically link against shared library if both + # static and shared are present. Therefore, ensure we extract + # symbols from the import library if a shared library is present + # (otherwise, the dlopen module name will be incorrect). We do + # this by putting the import library name into $newdlprefiles. + # We recover the dlopen module name by 'saving' the la file + # name in a special purpose variable, and (later) extracting the + # dlname from the la file. + if test -n "$dlname"; then + func_tr_sh "$dir/$linklib" + eval "libfile_$func_tr_sh_result=\$abs_ladir/\$laname" + newdlprefiles="$newdlprefiles $dir/$linklib" + else + newdlprefiles="$newdlprefiles $dir/$old_library" + # Keep a list of preopened convenience libraries to check + # that they are being used correctly in the link pass. + test -z "$libdir" && \ + dlpreconveniencelibs="$dlpreconveniencelibs $dir/$old_library" + fi + ;; + * ) + # Prefer using a static library (so that no silly _DYNAMIC symbols + # are required to link). + if test -n "$old_library"; then + newdlprefiles="$newdlprefiles $dir/$old_library" + # Keep a list of preopened convenience libraries to check + # that they are being used correctly in the link pass. + test -z "$libdir" && \ + dlpreconveniencelibs="$dlpreconveniencelibs $dir/$old_library" + # Otherwise, use the dlname, so that lt_dlopen finds it. + elif test -n "$dlname"; then + newdlprefiles="$newdlprefiles $dir/$dlname" + else + newdlprefiles="$newdlprefiles $dir/$linklib" + fi + ;; + esac fi # $pass = dlpreopen if test -z "$libdir"; then diff --git a/libltdl/m4/libtool.m4 b/libltdl/m4/libtool.m4 index b7b566d..3f658ac 100644 --- a/libltdl/m4/libtool.m4 +++ b/libltdl/m4/libtool.m4 @@ -1,7 +1,7 @@ # libtool.m4 - Configure libtool for the host system. -*-Autoconf-*- # # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, -# 2006, 2007, 2008 Free Software Foundation, Inc. +# 2006, 2007, 2008, 2009 Free Software Foundation, Inc. # Written by Gordon Matzigkeit, 1996 # # This file is free software; the Free Software Foundation gives @@ -10,7 +10,7 @@ m4_define([_LT_COPYING], [dnl # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, -# 2006, 2007, 2008 Free Software Foundation, Inc. +# 2006, 2007, 2008, 2009 Free Software Foundation, Inc. # Written by Gordon Matzigkeit, 1996 # # This file is part of GNU Libtool. @@ -3310,8 +3310,8 @@ esac lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" # Transform an extracted symbol line into symbol name and symbol address -lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\) $/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/ {\"\2\", (void *) \&\2},/p'" -lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n -e 's/^: \([[^ ]]*\) $/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \(lib[[^ ]]*\)$/ {\"\2\", (void *) \&\2},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/ {\"lib\2\", (void *) \&\2},/p'" +lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\)[[ ]]*$/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/ {\"\2\", (void *) \&\2},/p'" +lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n -e 's/^: \([[^ ]]*\)[[ ]]*$/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \(lib[[^ ]]*\)$/ {\"\2\", (void *) \&\2},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/ {\"lib\2\", (void *) \&\2},/p'" # Handle CRLF in mingw tool chain opt_cr= @@ -4108,6 +4108,7 @@ m4_require([_LT_TAG_COMPILER])dnl AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) m4_if([$1], [CXX], [ _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'] case $host_os in aix[[4-9]]*) # If we're using GNU nm, then we don't want the "-C" option. @@ -4122,13 +4123,13 @@ m4_if([$1], [CXX], [ _LT_TAGVAR(export_symbols_cmds, $1)="$ltdll_cmds" ;; cygwin* | mingw* | cegcc*) - _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;/^.*[[ ]]__nm__/s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols' + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols' + _LT_TAGVAR(exclude_expsyms, $1)=['[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname'] ;; *) _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' ;; esac - _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'] ], [ runpath_var= _LT_TAGVAR(allow_undefined_flag, $1)= @@ -4267,7 +4268,8 @@ _LT_EOF _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes - _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/'\'' | $SED -e '\''/^[[AITW]][[ ]]/s/.*[[ ]]//'\'' | sort | uniq > $export_symbols' + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols' + _LT_TAGVAR(exclude_expsyms, $1)=['[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname'] if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' -- 1.6.0.4