Author Topic: Win32 DLL Overhaul Borland Open Watcom Digital Mars MSVC  (Read 28937 times)

Offline severach

  • Multiple posting newcomer
  • *
  • Posts: 44
Win32 DLL Overhaul Borland Open Watcom Digital Mars MSVC
« on: September 21, 2005, 12:51:03 am »
CodeBlocks acts as advertising for these open source compilers so I'd like to see download information provided in the compiler screen to facilitate obtaining them. I'd also like to see DLL creation actually work. Driven by the simple idea that any modern compiler that targets Win32 should be able to produce a simple Win32 DLL, I spent many hours adapting my already working MinGW compiled DLL to each of the 4 remaining compilers and it appears that the Code::Blocks settings for DLL creation are in need of a major overhaul! The following solutions are designed to compile Win32 DLL's and may not work for other DLLs.

**MinGW:

Initially I had the problem where _DllMain@12 doesn't get called if compiling from a C++ source though it was called compiled from a C source. To solve this I added an extern "C":

#ifdef __cplusplus
extern "C"
#endif
BOOL APIENTRY DllMain(HINSTANCE hInst, DWORD reason, LPVOID lpvReserved) {

Now that seems to have fixed itself since I can't reproduce the problem so MinGW32 is the only platform that works OOBE. It does appear that there is no way to debug a DLL so it would be nice if the user was warned that debugging is not possible so they can stop trying. For my small DLL project, out of all the compilers, the always-been-free MinGW -shared produces the smallest DLLs with the greatest number of functions dynamically linked and the least amount of library and C++ baggage. Having gotten MinGW to work so easily and reliably, it came as a surprise that the remaining free compilers listed in CodeBlocks that are offshoots of commercial compilers were between annoying and exceedingly difficult. When CodeBlocks doesn’t mess up the command lines, the compilers themselves have obstacles that should have been caught and fixed years ago.

[edit: False alarm on a false alarm! This MinGW fix is necessary in some cases. An extern "C" declaration for DllMain() can fix this in a .h file if desired.]
 
**Visual C++ Toolkit 2003 VCTK Free:

None of the free compiler websites bothered to mention that the Windows SDK is required to do any Windows development so the free compiler download looks incomplete and useless. I only discovered the SDK when it was casually mentioned in the WiKi http://en.wikipedia.org/wiki/Visual_C_Plus_Plus then I spotted it in the "people also downloaded" messages in the Microsoft download area. It would be nice if C::B detected the SDK and warned that it is needed for Windows development then add the SDK folders to the folder list so I don't need to move the files and merge. At this time all I've needed is to install the SDK base and move the include and lib files over to the VC++ folder. You can't add the SDK folders since the MS compiler does not accept more than one lib folder the way that C::B provides them on the command line. Since Microsoft provides a debugger, can we get support for that in C::B? These are the items you will need to download to make the Visual C++ 2003 Free environment work. With all this the DLL's compile and run without any unreasonable actions on your part.

http://msdn.microsoft.com/visualc/vctoolkit2003/
http://www.microsoft.com/msdownload/platformsdk/sdkupdate/ (I prefer the ISO/IMG install)
http://www.microsoft.com/whdc/devtools/debugging/installx86.mspx

**Borland C++ 5.51 Free:

BCC is the easiest to fix since it has the least amount of problems. _DLlMain@12 doesn't get called and BCC places a leading underscore on exports which is not compliant to the Microsoft standard that everyone using interoperable DLLs expects. The c0d32.lib solution to DllMain was found in the C::B forums which may not be the most desirable library for everyone. The solution to the leading underscores was found in a Google search, many thanks to those trying to compile Q3 (Quake3) sources in BCC. To get rid of these underlines, create a .DEF file. To make it possible to specify on the command line and keep my CLEANUP.BAT from erasing it along with the other temporary .DEF files, I named it $exe_output.BCDEF. It would be nice if C::B would offer to create this .DEF file automatically but at this time it must be created by hand and it’s no hassle as long as you don’t keep expanding the number of functions to export. To utilize this .DEF file, you need to go into the BCC Compiler Advanced Options (Compile | Compiler Options | (select compiler) | Other | Advanced Options) and change:

Link Object Files to Dynamic Library: $linker -Tpd $link_options $libdirs c0d32 $link_objects, $exe_output,, $libs,$exe_output.BCDEF, $link_resobjects

Program.DLL.BCDEF (manually created):
; Corrects the leading underscores on the export names for Borland C and Open Watcom C
EXPORTS
DllFunc1=_DllFunc1
DllFunc2=_DllFunc2
; Watcom C (not C++) exports DllFuncs that return pointers without underscores. REM those out!
DllFunc3=_DllFunc3

Hex viewing your DLL, you'll notice that both _DllFunc1 and DllFunc1 are exported. A poor solution but it's better than a kick in the shorts.

[edit: Some people might prefer to remove c0d32 from the linker line and list it in the libs instead but this won't be possible until we can tell C::B to not append .lib to all libs.]

**OpenWatcom32 Free:

This compiler has more problems to fix. In addition to the leading underscore above, there are trailing underscores, _DllMain@12 isn't called, and none of the advice on the Internet works! You can try to put -bd "build Dynamic link library" in but it won't work. C::B considers it a Linker option and because it has already been selected for you, it is discarded rather than moving it to Linker Options. You can trick C::B into not consuming the -bd by putting it with another compiler option on the same line, like "-bd -3s". -bd should get _DllMain@12 called but doesn't because it is probably intended to be passed as -dll to the linker which would work perfectly, but it isn't passed or the linker I've chosen that works is not the one that wcl386.exe chooses that doesn't. -br "build with dll run-time library" will remove some statically linked DLL support making your DLL smaller but requiring 2 support DLL's to run: clbs13.dll & mt7s13.dll. Most will find this highly undesirable because the savings is minimal and the dll's change with the compile type. Notice there are DLLs of the same name with an "r" instead of an "s". Stay away from -br which will only cover you head to toe in Watcom wierdness.

You must select -3s "386 stack calling conventions" which gets rid of the trailing underscore. It seems that -3r "386 register calling conventions" with the trailing underline is the preferred calling sequence which I suspect is for Fortran compatibility, an efficient calling sequence similar to __fastcall which is subject to change in the future http://support.microsoft.com/kb/100832 which makes both useless calling sequences for programs expected to be interoperable. Open Watcom does not provide the necessary library functions for -3r DLL creation so you get a lot of undefines during link. Simply selecting -3s isn't enough though since Watcom insists on keeping the trailing underscore on exports. To pry a Win32 compliant DLL from Watcom's cold dead options you need to violate the Microsoft standard and alter your DLL defines like this:

#if BUILDING_DLL /* Dev-C++ */ || defined(BUILD_DLL) /* Codeblocks */
#ifdef __WATCOMC__
/* Watcom seems more interested in providing Fortran compatible DLL's than Windows compatible DLL's */
# define DLLIMPORT __declspec(dllexport) __cdecl
#else
# define DLLIMPORT __declspec(dllexport)
#endif
#else
# define DLLIMPORT __declspec(dllimport)
#endif
extern "C" void DLLIMPORT *DllFunc1(void);
//#undef DLLIMPORT /* All compilers except for Watcom C implicitly push DLLIMPORT into the function when it is declared in the code. boo hiss! */

This gets you to the leading underscores on exports which means the light at the end of the tunnel is not the morning sun after DLLs have failed to interoperate all night. To get rid of those underscores, create the .DEF file described in the Borland solution above and to use it you need to go into the WC Compiler Advanced Options and change:

Link Object Files to Dynamic Library: $linker -nologo -dll -out:$exe_output $libs $link_objects -def:$exe_output.BCDEF

... Then go to the WC programs (Compile | Compiler Options | OpenWatcom (W32) Compiler | Programs) and change:
Linker for dynamic libs: link386.exe

**Digital Mars (dm845c) Free:

DMC is the most broken of all the compilers as it requires a step from you that may not always work and can't be done from CodeBlocks. The DMC linker requires a .DEF file produced by the DMC compiler and that .DEF file is only produced if you compile all in one step, from .CPP to .DLL. The .DEF file is not created if you compile a .CPP to a .o then compile all the .o files to a .DLL as CodeBlocks does and as is necessary for any large project. The .DEF file is not similar to the one used to correct Watcom and Borland fubars. If your project is simple you can alter the compiler advanced options to do a one step compile and erase the link line. To get a generic solution you must first manually compile your project all at once to obtain the .DEF file with a command line like this one:

c:\dm\bin\dmc.exe -mn -WD -DBUILD_DLL -I"C:\dm\include" DLLSource.cpp shell32.lib kernel32.lib

Rename the .DEF to DllSource.DLL.DMCdef. Then you need to go into the DMC Compiler Advanced Options

Link Object Files to Dynamic Library: $linker $link_options $link_objects,$exe_output,,$libs,$exe_output.DMCdef,$link_resobjects

In case you have trouble creating a .DMCdef file, you might be able to construct one out of the .DEF that was created for me. It doesn't look too special:
LIBRARY "DLLSource.dll"
DESCRIPTION 'DLLSource as a DLL'
EXETYPE NT
SUBSYSTEM WINDOWS
CODE SHARED EXECUTE
DATA WRITE

Sorry folks, the DMC compiler is so screwed up this is the best I can do for a generic solution that allows compiling within CodeBlocks without crippling DMC for other project types.

[edit: Here's another Compile a Windows DLL command that works fine and doesn't require you to create a .DMCDEF file]
[$compiler -L/subsystem:windows:4.0 -WD -mn $link_options $link_objects -o $exe_output $libs $link_resobjects]
[Compile to a Windows nonconsole executable is the same except you use -WA instead of -WD]
[If the $compiler doesn't recognize any $link_options you will need to prefix with -L/opt manually.]
[Anyone annoyed by the outdated SDK included with DMC should check here: http://cmeerw.org/prog/dm/ms_sdk.html ]
[From that site I created an automated installer for a more current SDK]

****

I hope you all spend less time making Win32 DLLs work than I did and that you get to choose the compiler you want instead of choosing the only compiler you can coax into working. I have working DLL projects in CodeBlocks for every compiler so let me know or post the mods if I missed a step for producing a DLL that compiles correctly or I unwittingly damaged a different compile target.

If anyone could make a wxWidgets IDE that composes like Borland C++ Builder, that would be teh r0xor! In fact, any open source cross platform IDE that produces any kind of windowed applications that composes like Borland C++ Builder would be teh r0xor!
« Last Edit: October 17, 2006, 12:28:29 am by severach »

Offline mandrav

  • Project Leader
  • Administrator
  • Lives here!
  • *****
  • Posts: 4315
    • Code::Blocks IDE
Re: Win32 DLL Overhaul Borland Open Watcom Digital Mars MSVC
« Reply #1 on: September 21, 2005, 09:03:32 am »
Thanks for the nice insight on DLL compiling :)
You have to understand that C::B offers support for all those compilers but, for some it may be better than the others. That is why a compiler framework redesign has been scheduled for post v1.0. To allow more versatility and data-driven operation...

Quote
It does appear that there is no way to debug a DLL so it would be nice if the user was warned that debugging is not possible so they can stop trying.

Well, we debug C::B so DLL debugging is supported :P
Hint: try "Project->Set program's arguments" and set the "Host application"...
Debugger support in C::B, although not excellent, does the job and is constantly improving.

Quote
It would be nice if C::B detected the SDK and warned that it is needed for Windows development then add the SDK folders to the folder list so I don't need to move the files and merge. At this time all I've needed is to install the SDK base and move the include and lib files over to the VC++ folder. You can't add the SDK folders since the MS compiler does not accept more than one lib folder the way that C::B provides them on the command line.

It does detect the Platform SDK. After you 've installed it, go to "Settings->Compiler->[select msvctoolkit]->Programs" and click "Auto-detect". It also detects Microsoft's Debugging Tools for Windows ;)

Anyway,
thanks again for the nice info :)
Be patient!
This bug will be fixed soon...

Offline severach

  • Multiple posting newcomer
  • *
  • Posts: 44
Re: Win32 DLL Overhaul Borland Open Watcom Digital Mars MSVC
« Reply #2 on: September 21, 2005, 08:06:49 pm »
You have to understand that C::B offers support for all those compilers but, for some it may be better than the others. That is why a compiler framework redesign has been scheduled for post v1.0. To allow more versatility and data-driven operation...
Then this post should be valid for a long time and people won't need to wait until the new framework to get their DLL's working. Time will allow people to test these changes to look for the most reliable implementations. In the Borland solution where a startup lib was placed literally on the $linker line, it may be preferrable to list this in the libs so the lib can be changed for anyone needing a different one. We need people compiling DLL's regularly to figure this stuff out.

Quote
Well, we debug C::B so DLL debugging is supported :P
Hint: try "Project->Set program's arguments" and set the "Host application"...
I have that but I'm not developing the host application. I don't think the debugger can figure out when the DLL gets called and jump in with the breakpoints.

Quote
It does detect the Platform SDK. After you 've installed it, go to "Settings->Compiler->[select msvctoolkit]->Programs" and click "Auto-detect". It also detects Microsoft's Debugging Tools for Windows ;)

This partly works. The debugging folder was detected but the debugger wasn't filled in from blank. It will take some time to figure out which EXE is the debugger that C::B expects or maybe I'll just learn to use the GUI debugger. I added the SDK include and lib paths and this time the compiler accepted them.

Japheth

  • Guest
Re: Win32 DLL Overhaul Borland Open Watcom Digital Mars MSVC
« Reply #3 on: September 21, 2005, 10:48:32 pm »

About Openwatcom:

It may be a better way to create a dll with OW to select WLINK as linker instead of wcl386. I'm not too much engaged in C::B currently, but to make a win32 dll with OW I did:

- change wcl386.exe to wlink.386
- modified value of registry entry "Link object files to dynamic library":
"$linker system nt_dll opt map LibPath $libdirs Library $libs File $link_objects $link_options Name $exe_output"

And that worked on first shot.

Regards

Japheth

 


Offline mandrav

  • Project Leader
  • Administrator
  • Lives here!
  • *****
  • Posts: 4315
    • Code::Blocks IDE
Re: Win32 DLL Overhaul Borland Open Watcom Digital Mars MSVC
« Reply #4 on: September 22, 2005, 12:09:39 am »
Thanks for the info :)
Btw, I hope you didn't edit the registry by hand? You can set these options in "Settings->Compiler->Other->Advanced options".
Be patient!
This bug will be fixed soon...

Japheth

  • Guest
Re: Win32 DLL Overhaul Borland Open Watcom Digital Mars MSVC
« Reply #5 on: September 22, 2005, 08:03:14 am »

> You can set these options in "Settings->Compiler->Other->Advanced options".

Thanks for the hint  :D

> - change wcl386.exe to wlink.386

"wlink.386" should be read as "wlink.exe" of course

Offline tuXXX

  • Multiple posting newcomer
  • *
  • Posts: 13
Re: Win32 DLL Overhaul Borland Open Watcom Digital Mars MSVC
« Reply #6 on: September 17, 2008, 01:46:29 pm »
Sorry, I cant understand how to debug DLL in C::B on windows.
My compiler - GCC (MinGW), I have dll and host application.
I can only "run" dll in c::b, debug not starting...

P.S. I'm also using Code::Blocks as debugging environment for avr-gdb (Host - Linux + Atmel AVR microcontrollers + JTAG ICE). I can debug, wath variables, see CPU registers... BUT - how to see peripheral registers??? Is this supported?
« Last Edit: September 17, 2008, 03:50:31 pm by tuXXX »