libtool-patches
[Top][All Lists]
Advanced

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

Re: [PATCH] tests: import variables for MSVC.


From: Peter Rosin
Subject: Re: [PATCH] tests: import variables for MSVC.
Date: Mon, 27 Sep 2010 10:45:37 +0200
User-agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.2.8) Gecko/20100802 Thunderbird/3.1.2

Den 2010-09-25 07:28 skrev Charles Wilson:
> On 9/24/2010 2:46 PM, Peter Rosin wrote:
>> Now I'm also confused.
> 
> That's not good.
> 
>> /me double checks (see below)
>>
>> WHAT? It doesn't work as I stated!?!
>>
>> *ponders that for a bit*
>> *scratches head*
>>
>> Ahh, you said "libtool does this by default IIRC". If that's actually the
>> case than that is what has have me fooled for years.
> 
> Pay close attention to how libtool compiles (the single, only) main.o.
> Does it get the picflag (-DDLL_EXPORT) or not?
> 
> As I've always understood it, *without* auto-import magic, you MUST have
> the following:
> 
> 1) shared:
>   a) a dll, compiled with declspec(dllexport) [or, create the DLL with
> an explicit .def file listing the exported symbols]
>   b) the client *must* be compiled with declspec(dllimport) decorators
> on all symbols the client wants to use from the DLL
> 
> 2) static
>   a) a lib. Nothing should be compiled with declspec(dllexport), and
> obviously there is no .def file involved
>   b) the client must NOT be compiled with declspec(dllimport) -- because
> then you get the missing __imp__foo error.
> 
> So, your test case below doesn't surprise me.  What DOES surprise me, is
> that it ever worked at all with MSVC (or gcc + -disable-auto-import),
> since it appears that Ralf is correct and the *_PROGRAM objects are
> built in only one "mode".  Whether that is "picflag" (-DDLL_EXPORT) or
> not, one or the other linking modality should fail (static linking if
> main.o is compiled with -DDLL_EXPORT; dynamic linking if main.o is NOT
> compiled with -DLL_EXPORT).
> 
> So, yeah, I'm a little confused as well.  I think you need to do some
> archeology on the *_PROGRAM objects (nm -B or whatever the equivalent is
> in msvc land), and figure out what symbols are undefined.  I'd take a
> hard look at demo/.

I have done some more digging and am no longer confused.  As it happens,
you could say that we are both right.  The little sample I quoted was
a little bit too small, so it behaved according to your mental image.
If you "flesh out" the example so that the program also uses a function
from the library, it magically starts to find the variable too, making
it behave according to my mental image.  Now, libraries that only
export data items are /rare/, and clients that only use data items are
also /rare/.  So, in theory you're correct and in practice I'm correct.

So, this works:

$ cat << EOF > dllfoo.c
extern __declspec(dllexport) int variable;
int variable = 2;
int foo(void) { return 0; }
EOF
$ cl -nologo -Fefoo.dll -MD dllfoo.c -link -dll -export:variable,DATA 
-export:foo -implib:foo.dll.lib
dllfoo.c
   Creating library foo.dll.lib and object foo.dll.exp
$ cat << EOF > bar.c
extern __declspec(dllimport) int variable;
int foo(void);
int main(void) { foo(); return variable; }
EOF
$ cl -nologo -Febardll.exe -MD bar.c foo.dll.lib
bar.c
$ ./bardll
$ echo $?
2
$ cat << EOF > libfoo.c
extern int variable;
int variable = 2;
int foo(void) { return 0; }
EOF
$ cl -nologo -c -MD libfoo.c
libfoo.c
$ lib -nologo -out:foo.lib libfoo.obj
$ cl -nologo -Febarlib.exe -MD bar.c foo.lib
bar.c
bar.obj : warning LNK4217: locally defined symbol _variable imported in 
function _main
$ ./barlib
$ echo $?
2

Note, I only added the -export options when building the dll as libtool
adds those automatically, and I wanted to eliminate as many differences
as possible from what libtool is doing.

GCC does not have the ability to find "locally defined symbols" when
it is looking for imports.

> NOTE: Bruno Haible's method worked around this by ALWAYS defining
> symbols in a library as declspec(dllimport), when building the library
> shared, building the library static, OR building a client.
> 
> BUT...to make linking the DLL itself work (with internal references to
> these "dllimported" symbols!), he uses some nm and asm magic to (a)
> manually define the __imp_* redirection symbol values and set them to
> point to the address of the actual symbol, and (b) explicitly export
> each "exported" symbol using an asm .drective, even tho it was marked
> dllimport.
> 
> It's really rather clever, but I've never really figured out how to
> merge it into the typical auto*/libtool process (Bruno's libiconv and
> gettext do it, but with a lot of Makefile.am hackery).  Second, I don't
> know if it would work with MSVC easily; certainly the asm magic would
> need modification.  Third, it almost *requires* to build *everything*
> with --disable-auto-import.  Which would NOT go over well with the
> larger community.  So, I've never pursued it, and obviously Bruno hasn't
> pushed the issue.

Note that since libtool does add the -export options when linking the
dll, it will work to unconditionally declare (for MSVC) any variables
with __declspec(dllimport), and then rely on the -export option when
linking to "win" and make it an export.  But, I suspect that any
references to the variable will go through an indirection, as I suspect
will be the case when the library consumer is using __declspec(dllimport)
even when linking statically.

That indirection (if indeed present) is a small price in my book.  Others
might have a different opinion of course.

>> *deep sigh*
>>
>> Thanks for setting me straight.
>>
>> What now?  Is the patch still good?  (with a reworded changelog of course)
> 
> Well, I think so.  It's possible we might need a follow-on patch for
> "strict correctness" -- but this patch appears to be correct as far as
> it goes.
> 
>> But now I'm really confused.  What made the original patch work?  It had
>> "#define EXTERN extern __declspec(dllimport)" unconditionally for MSVC.
>> And that patch also had two SKIPs and one FAIL (libfoo.a vs. foo.lib).
>> I.e. the exact same result, which means I can't be completely wrong.  Or
>> is the testsuite not doing any static builds?  But that seems highly
>> unlikely indeed.  WTF?
> 
> Look really closely at how hell_static.exe is built in demo/.
> 
> But, to sum up, I see no problems with THIS patch, as far as it goes.
> 
> 
> 
> With regards to Ralf's question re: _MSC_VER.  Well, technically you'd
> probably be "more" correct to do:
> 
> #if (defined(_WIN32) || defined(_WIN32_WCE)) && !defined(__GNUC__)
> ...
> 
> rather than _MSC_VER; that formula would indicate "any win32 or wince
> platform, using any compiler EXCEPT gcc" -- because only gcc has
> "auto-import" on win32.

I agree, it should be more stable, so I'm going with your #if.  Pushing
with that squashed in (but I'm still waiting on the testsuite, so if
anybody objects there's still some time).

> But nobody does that; pretty much all source code with pretensions of
> both cross-platform use, AND windows support, uses _MSC_VER (*badly*
> ported code uses _WIN32 to mean "MSVC" which causes no end of cygwin and
> mingw headaches!).
> 
> Because of that, IIUC most users of "other" compilers for win32 (Intel
> C/C++, Watcom, Borland, etc) either (a) routinely
> s/_MSC_VER/__WATCOMC__/g, or (b) add -D_MSC_VER anyway.

Little reason for us to follow that pattern.

Cheers,
Peter



reply via email to

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