[Top][All Lists]
[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'