bug-libtool
[Top][All Lists]
Advanced

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

Re: [cygwin|mingw] dlpreopen and disable-static


From: Charles Wilson
Subject: Re: [cygwin|mingw] dlpreopen and disable-static
Date: Tue, 27 May 2008 01:35:10 -0400
User-agent: Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US; rv:1.8.1.14) Gecko/20080421 Thunderbird/2.0.0.14 Mnenhy/0.7.5.666

Charles Wilson wrote:\
What is the first 'case $host' expression there for?
That's the c++ section.

Why isn't it folded into the other one?
Different tag.

And why do the two separate 'case $host' blocks specify different export_symbols_cmds for the same $host?
Well, now, THAT's a good question. I've tested the patch below (warning: ugly, horrid code. Proof of concept only. And there Just Has To Be A Better Way.)

It does a number of things;
(1) attempt to exclude _head_*_dll and *_dll_iname symbols from the export list, instead of the nonsensical-on-win32 _GLOBAL_OFFSET_TABLE stuff.

(2) Use _nm_-sensitive export_symbols_cmds for C as well as C++.

(3) if dlpreopen, and no static lib is available, insert the link lib (.dll.a) into the list of dlpreopen files, instead of the DLL -- but only for cygwin|mingw.

(4) Implement a really horrid mechanism to determine the actual DLL name when given only the import lib. If it is done in any way similar to this, it should be abstracted into a function in libtool.m4, and called from ltmain.m4sh. But really, there HAS to be a better way -- but none of the binutils will report this information directly, and the DLL name is *not* necessarily related to the implib name, in the general (non-libtool) case.

I thought of two alternatives:
(a) compile a test exe with -nostdlib, and then use objdump to determine its imports. But you have to first find a symbol in the library, so that the linker doesn't optimize away the dependency. Kinda of chicken and egg.

(b) IF we only allow dlpreopen with libtool libs, then in step (3) above insert the .la file. Then, in the spot modified by (4) above, pick out the dlname and linklib name directly from the .la (which, sadly, is exactly what the code in (3) is currently doing -- we'd just have to do it twice!)

(5) also, borrow some of the stuff from the _nm_-sensitive export_symbol_cmds for use when generating the dlpreopen symbol list on cygwin|mingw. We can't actually USE export_symbol_cmds (because we need the raw symbols so that global_symbol_to_cdecl and global_symbol_to_c_name_address will work), but global_symbol_pipe doesn't QUITE do enough in this case.

(6) Unrelated: libtool --verbose does nothing right now, and opt_verbose is always false. Allow --verbose to set opt_verbose to true, as well as opt_silent to false.

The ONLY positive thing I can say about the attached patch is, it works. It passes the testsuite on cygwin, and fixes the (newly detected) helldl problem in demo-exec after demo-shared.

Final note:
+                    $SED -e ':a;N;$!ba;s/\n//g' -e 's/\.\.\.*//g' \
+                         -e 's/[       ][      ][      ]*//g' \
+                         -e 's/^[      ]*//' -e 's/[   ]*$//'`

should probably be changed (last line) to:
+                    $SED -e ':a;N;$!ba;s/\n//g' -e 's/\.\.\.*//g' \
+                         -e 's/[       ][      ][      ]*//g' \
+                         -e 's/^[      \.]*//' -e 's/[   \.]*$//'`

in case there is a lone preceeding or trailing '.'.

--
Chuck
diff --git a/libltdl/config/ltmain.m4sh b/libltdl/config/ltmain.m4sh
index cfdfdf9..62709a2 100644
--- a/libltdl/config/ltmain.m4sh
+++ b/libltdl/config/ltmain.m4sh
@@ -334,6 +334,7 @@ func_enable_tag ()
 
       --verbose| -v)   preserve_args="$preserve_args $opt"
                        opt_silent=false
+                       opt_verbose=true
                        ;;
 
       --tag)           test "$#" -eq 0 && func_missing_arg "$opt" && break
@@ -1941,10 +1942,73 @@ 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* )
+             # if an import library, we need to obtain dlname
+             # this is a bit of a hack...
+             if eval $file_magic_cmd \"\$dlprefile\" 2>/dev/null |
+                 $SED -e 10q | $EGREP "import" >/dev/null; then
+                # 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.
+                dllname=`$OBJDUMP -s --section '.idata$7' $dlprefile |
+                    $SED -e '/^.\{43\}/!d' -e 's/^.\{43\}//' |
+                    $SED -e ':a;N;$!ba;s/\n//g' -e 's/\.\.\.*//g' \
+                         -e 's/[       ][      ][      ]*//g' \
+                         -e 's/^[      ]*//' -e 's/[   ]*$//'`
+               $opt_dry_run || {
+                  if test -n "$dllname" ; then
+                   eval '$ECHO ": $dllname " >> "$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
+               $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 || {
@@ -5002,10 +5066,21 @@ func_mode_link ()
            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"
+         # Except on mingw|cygwin, where we must use the import library,
+         # so lt_dlopen is handled in another way
          else
-           newdlprefiles="$newdlprefiles $dir/$linklib"
+           case "$host" in
+             *cygwin* | *mingw* )
+               newdlprefiles="$newdlprefiles $dir/$linklib"
+                ;;
+             * )
+               if test -n "$dlname"; then
+                 newdlprefiles="$newdlprefiles $dir/$dlname"
+               else
+                 newdlprefiles="$newdlprefiles $dir/$linklib"
+               fi
+                ;;
+           esac
          fi
        fi # $pass = dlpreopen
 
diff --git a/libltdl/m4/libtool.m4 b/libltdl/m4/libtool.m4
index 654f54a..7e22744 100644
--- a/libltdl/m4/libtool.m4
+++ b/libltdl/m4/libtool.m4
@@ -4142,6 +4142,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.
@@ -4157,12 +4158,12 @@ m4_if([$1], [CXX], [
   ;;
   cygwin* | mingw*)
     _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(exclude_expsyms, $1)=['_head_*_dll|*_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)=
@@ -4301,7 +4302,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/;/^.*[[ ]]__nm__/s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ 
]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols'
+      _LT_TAGVAR(exclude_expsyms, $1)=['_head_*_dll|*_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'

reply via email to

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