Sunday, August 10, 2008

MinGW and Unicode support?

Recently I've been working on a program called RuntimeTester. And since it is a small and simple C++ program working in Win32 environment, I decided to port it to different C++ compilers. The original was written using Microsoft Visual C++ 2008, it has a free version which I believe is using the same optimizing compiler, but my idea was to give a chance to some free compilers and check the results. So I tried the following compilers: MinGW (compiler version 3.4.5), OpenWatcom 1.7a and Digital Mars C++ 8.42n. I've created simple batch files to run the compilers and convert a single source file to a single executable file. All went without problems. And then I remembered my idea was to make it Unicode (I've used "tchar.h" functionality in the source code). I made a copy of my batch files and added both _UNICODE and UNICODE macros, then ran the compilers. Open Watcom and Digital Mars C++ went without a problem but MinGW gave me a strange message stating: "undefined reference to `WinMain@16'". Since I'm using "_tmain(...)" a quick check at MinGW's tchar.h showed the following code when _UNICODE is defined:

/* for porting from other Windows compilers */
#if 0 /* no wide startup module */
#define _tmain wmain
#define _tWinMain wWinMain
#define _tenviron _wenviron
#define __targv __wargv
#endif
I did some Google around and found some ideas about how to fix it. I also found some solutions that worked in the past but not working with the new versions so I did a quick and dirty fix to my code using ANSI startup for MinGW in all environments. Here is how the main(...) function looks like:

#ifdef __GNUC__
int main(int argc, char **a_argv)
#else // !__GNUC__
int _tmain(int argc, TCHAR **argv)
#endif // __GNUC__

{
// some variables defined here
// ...

#ifdef __GNUC__
TCHAR **argv;
#ifdef UNICODE
// MinGW doesn't support wmain() directly (shame on its CRT!)
int a_argc;
argv = CommandLineToArgvW(GetCommandLineW(), &a_argc);
#else // !UNICODE
argv = a_argv;
#endif // UNICODE
#endif // __GNUC__
This is quite strange. Why there is no support for Unicode startup code in MinGW? I don't believe this is too hard to achieve! Here is a patch done in 2003. Looks like it never made it to the official build: http://osdir.com/ml/gnu.mingw.patches/2003-05/msg00001.html .

You can get the program and play with it if you like. There is more info about it inside the readme.txt file.

No comments: