Peter Rosin wrote: > I'm primarily trying to determine what impact this has on my > MSVC branch... > > Den 2009-01-03 02:39 skrev Charles Wilson: > *snip* >> + *cygwin* | *mingw* | *cegcc* ) > > We should strive to have fewer of these in ltmain.m4sh, not more.
Yep. But the problem is, there are really two BIG categories of platforms: those that support ELF-semantics for shared libraries, and those that support PE-DLL semantics. The differences between, say, HP and Linux are in this regard much less significant than the differences between win32 (cygwin, mingw, msvc, even wince) and any *nixoid. And vice verse: cygwin and msvc are much more similar *with regards to the construction of shared libraries* than they are different (even though the implib/static lib formats are non-interchangeable). I'm not sure it would be an improvement, exactly, but we could have a libtool variable $LT_HOST_SUPPORTS_PE_DLL (or a function that takes $host), and replace many of these case $host in *cygwin* | *mingw* | *cegcc* ) ... ;; everything else ) ... ;; esac occurences with 'if host_supports_pe_dll ; then ... ; else ... ; fi' Still ugly, but it means you only have to "fix" the case "$host" pattern in one place. >> + func_warn "Using fallback code to determine dllname for $1; >> consider updating binutils to version 2.20 (2.19.50.20081115), or newer." > > I fail to find that version of binutils in Cygwin setup, so I guess the > fallback code will get exercised. Not exactly. Background: the --identify option is supported only in CVS. There has not yet been an official binutils release containing that code. Furthermore, cygwin's official binutils, while based on a CVS snapshot, is from 20080624. So, no, if you want it you have to compile it yourself. Same for the mingw-provided binutils. But, func_win32_dllname_for_implib is only ever called if we were unable to find the .la file for the implib. Normally, you'd do something like: -dlpreopen foo.la and then, the libfile_$(transliterated implib name) stuff is used, not func_win32_dllname_for_implib. You only use that function if somebody did: -dlpreopen /path/to/foo.dll.a (maybe because they had no .la file, or it was not installed by the system packaging, or whatever). BTW, I'm assuming that func_win32_import_lib_p() works for msvc, because you've got the "correct" $file_magic_command for your toolchain (whatever "correct" means)... > The comments say that "gcc" adds the > dll name in .idata$7, and the fallback code makes use of this fact. How > stable is that? For gcc dll's, very. Hasn't changed in over a decade. pe-ppc (as opposed to pe-i386) uses .idata$6; a dlltool compiled for that toolchain correctly inspects .idata$6. That's why this manual parsing stuff is just a fallback; it'd be better to use a binary tool. But, for msvc, I haven't even thought about trying to parse dumpbin output. Can we (libtool?) provide binary utility programs to go along with msvc to solve some of these issues? Furthermore, can we even assume that binutils progs like objdump and dlltool are available? Or file, for that matter? > What happens if you generate an import library late (if > you only have the dll) with something that is not gcc? First, I'm assuming that you're not talking about mixing between toolchains (e.g. if $CC is gcc, then the libs were generated by gcc/ld. if $CC is cl, then the libs were generated by cl.exe.) So, you're talking about completely non-gcc-based toolchains AND you're dealing with an import library for which you have no .la file. In that case you're stuck using func_win32_dllname_for_implib. Now, dlltool --identify (if you even HAVE dlltool) doesn't work with MSVC lib files (I just checked). I could see different functions defined for each toolchain, and then a libtool variable $pedll_dllname_for_implib_cmd that points to the correct implementation for your toolchain. (mingw and cygwin and probably cegcc would "point" to my implementation, whatever it is renamed to). But remember, this is all a corner case: dlpreopen of a shared library, when you don't have an .la file. Otherwise, it ought to just work(tm). > What if you have > an import library created by e.g. MSVC? Looking at a few import libs in > the Platform SDK suggests that MSVC uses .idata$6 instead. Sortof. I see a LOT of .idata$6 entries. Most of them contain symbol names at offset 2, and offset 0,1 contain a little-endian count. But the one that has the DLL name starts at offset 0. How are you supposed to tell that 'MS' is actually the first two characters of a DLL name, and not an indication that symbol 'VCR80.dll' is entry number 0x534d in the symbol list? Unless "the first member of the archive" is ALWAYS the one that will specify the DLL, and you look in the .idata$LAST of that member. I think it would be better NOT to try to generalize this, and instead go the $LT_pedll_dllname_for_implib_cmd route above. If your msvc port can use objdump, then the following works (and could be put in the func_msvc_dllname_for_implib implementation). It's somewhat different than the existing fallback because in gcc, all .idata$7 except the one we care about are full of nulls. In msvc, all .idata$6 have data, so we need to maintain separation between data from different .idata$6 blobs. But I am assuming that the FIRST archive member that has an .idata&6 section is the one we want: objdump -s --section '.idata$6' "$1" | sed '/^Contents of section .idata\$6:/{ s/.*/====MARK====/ p d } /^====MARK====/p /^.\{43\}/!d s/^.\{43\}//' | sed -n ' /^====MARK====/ b para H $ b para b :para x s/\n//g s/^====MARK====// s/[\. \t]*$// /./p ' | sed -n -e 1p Note that contra my advice to avoid generizing this, the above script works for gcc implibs with only a single change: .idata$6 -> .idata$7 (under the same (valid?) assumption: the FIRST archive member with an .idata$7 member is the one we want). > To me it > seems as if the dllname is in the last .idata segment, can't that be > scripted for a better fallback? But not every object in the archive has an .idata$7 (or .idata$6). Some objects only have a few .idata$N sections, and the "last" one is .idata$4. In other cases, an .idata$7 section is present, but contains only nulls. (try objdump -s libz.dll.a) > Hmm, looking at the the --identify patch for binutils, it seems that it > too simply dumps out .idata$7. That seems to be plain wrong for a whole > bunch of import libs out there in the wild. But I can't use gcc or ld to link against those import libs. That's why the mingw w32api package ships *gcc* format import libraries generated from .def files. THOSE import libraries DO follow the rules that dlltool --identify understands. It's not surprising that a binutils-supplied tool like dlltool is limited to dealing with the same kinds of files that the binutils linker generates/can link to. DLLs (in the C language, at least) are generic for any compiler on the win32 platform. But every compiler has its own import (and sometimes static) library format. In general they are very similar, but not interchangeable. However, the improvements suggested by Ralf -- and implemented in this patch -- should relegate those issues to a dusty back corner. Do you really think it is of *primary* importance that somebody be able to dlpreopen a third-party, non-libtool-generated DLL? (That functionality has been broken on cygwin/mingw for several years now and hardly anyone noticed) The libfile_$(transliterated implib name) stuff *should* make things work for dlpreopening libtool-generated DLLs, even for msvc -- once the 'case "$host" in PATTERN's are corrected (or replaced by something more general). Eventually, yeah, we can and should fix the dlpreopen-third-party case for non-gcc...but is it a showstopper? -- Chuck