This is the mail archive of the binutils@sources.redhat.com mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Re: [RFA] [pei-386] prevent ld (auto-import) from generating broken code


DJ Delorie wrote:

>>Are you *sure*
>>
> 
> Suggesting a complex workaround using #defines is worse than just
> having them do the right thing in the first place.  

I'm sorry, I should have been more clear.

Sure, if all you want to do is "link this client code to that DLL" -- 
then yeah, just put

"__declspec(dllimport)" in the DLL's header file which declares the 
variable you want to import.  Or skip the header files completely; just 
declare imported variables yourself in the client code (BAD idea. 
Completely unmaintainable)

Of course, if you want that header file to ALSO work on OTHER platforms, 
you'd need to do something like:

#if defined(__CYGWIN__) || defined(_WIN32)
# define STUPID_WIN32_DECORATOR __declspec(dllimport)
#else
# define STUPID_WIN32_DECORATOR
#endif
extern STUPID_WIN32_DECORATOR int foo

But, if you want the same header file to be usable both when BUILDING 
and when LINKING to the DLL, you'd need to add the following (assuming 
that you don't want to use __declspec(dllexport); just rely on 
--export-all-symbols.  If you DO want to use __declspec(dllexport) when 
building the DLL, it gets even uglier)

#if defined(__CYGWIN__) || defined(_WIN32) && !defined(BUILDING_DLL)
# define STUPID_WIN32_DECORATOR __declspec(dllimport)
#else
# define STUPID_WIN32_DECORATOR
#endif
extern STUPID_WIN32_DECORATOR int foo

But now, let's suppose you want to support both static libraries AND 
DLL's -- on cygwin/win32 -- but using the same header file to declare 
your exported (struct? array?)  Then you need to add another flag to 
your library's header file:

#if defined(__CYGWIN__) || defined(_WIN32) && \
   ! (defined(BUILDING_DLL) || defined(STATIC_LINK))
# define STUPID_WIN32_DECORATOR __declspec(dllimport)
#else
# define STUPID_WIN32_DECORATOR
#endif
extern STUPID_WIN32_DECORATOR int foo

It's these defines I'm talking about:  -DBUILDING_DLL when building a 
dll, -DSTATIC_LINK when building a static library or when building a 
client .o that will be linked to a static library, or (no special 
defines) when building a .o that will be linked to the DLL.

That's "blech".  And unfortunately, the ugliness is absolutely necessary 
to handle the __declsec junk in your library's header files, if you want 
to allow (a) compatibility with other platforms (b) building either 
static or DLL (c) linking to either static or DLL.

 > And I suspect
 > people would get confused and try "extern volatile struct foo f;"
 > which won't work.


Right.  That's why the extra documentation that I added to elaborate on 
this issue said to:

declare a local variable that was volatile
for structs, that local variable should be a pointer to struct, not a 
struct itself.
change struct.field references to local_var->field references.

Okay, so I didn't spell it out that way -- I gave examples that obeyed 
those rules.

Are you saying I need better documentation to help prevent people from 
making the mistake, or are you dead set against anything except 
__declspec?  (Keeping in mind the hell of interlinked #defines 
__declspec requires, if you want to maintain cross-platform compatiblity 
and static/DLL choice)

--Chuck




Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]