Thursday, December 9, 2010

Porting Candle to MinGW and CodeLite

Thanks to CodeLite, porting Candle source code to MingGW was much simpler than I thought.

As I wrote previously, finding the right C/C++ IDE (other than VC Express) was not easy for me, and my last settlement was with Eclipse CDT. So porting Candle source code to other compiler and IDE on Windows, like MinGW, was not of high priority for me.

I was googling for something (I don't remember what it is) and one of the result page recommended CodeLite, and triggered me to give CodeLite a trial.

Importing the Projects

After I installed CodeLite, I was able to import MSVC solution and projects without any problem. There's only one small annoyance. CodeLite imports my C/C++ source files under a default virtual directory 'src'. It seems be a restriction in CodeLite that source file must be under some virtual directory, as it does not allow me to have source files directly under a project.

 

Compiling the Source Code

I was able to compile with almost no change to the source code. The only changes that I can remember were:
  • some typedefs for int64, and uint64, etc;
  • macro for dll export/import declaration;
The biggest hurdle that I encountered during this porting exercise was related to the dll export/import declaration. There were a few lines of source code in one of the module as following:
#if _WINDOWS
    #undef DLLDECL
    #define DLLDECL __declspec(dllexport)
#endif
The source code of this module was able to compile without any problem. But when I compiled another module that depends on this one, all symbols exported from this module were not visible to that importing module. I had to take out source files one by one to finally nail down the cause of the linking problem to these few lines.

The cause of the problem was that GCC accepts MSVC's syntax of dll export declaration, __declspec(dllexport), but the symbols are not really exported. I really hate this kind of half-baked solution. GCC should either reject MSVC's syntax or if it determines to support such it, than it should support both the syntax and semantic properly.

 

Linking the Source Code

There were a few linking options that needed to be specified for GCC to link properly, including:
  • Library import path and Libraries; CodeLite's default conversion was not accurate;
  • -Wl,--out-implib,module.a to export the import library;
  • -Wl,-subsystem,windows to compile the main executable as Windows GUI program;
It is understandable that it might not be easy to translate the library settings correct when importing MSVC solution and projects, but I think CodeLite can be improved to get the other two settings correct. In the VC project file, there is the setting , so it should not be difficult for CodeLite to detect such setting and translate to corresponding GCC configuration properly.


The Final Execution

I was really AMAZED that the compiled executable ran smoothly on the first shoot. NO CRASH! No unexpected execution result, all test cases (although not many) passed. I really did not expect the execution to be so smooth. I thought I would have do some runtime debugging to fix some tricky porting bugs before the whole system runs properly.

This reflects a few things:
  • Firstly, MinGW is indeed  a CLEAN replacement for MSVC on Windows as long as you stick to standard C/C++ features and Win32 API (don't expect MinGW to support MFC/ATL/WTL/COM/ActiveX out-of-box). I even checked the compiled binary with Dependency Walker, and no extra GCC-specific DLLs were introduced.
  • Candle source code is indeed highly portable;
  • CodeLite works reasonably well as a C/C++ IDE:
    • Pros of CodeLite:
      • Able to refactor C/C++ source code (though I have not tried it out);
    • Cons of CodeLite:
      • The debugger is not as friendly as MSVC (this is probably more related to GCC);
      • The Subversion integration seems to conflict with TortoiseSVN;
      • The GUI is noisier than Eclipse CDT or MSVC. For example, in the GUI, we can see names of integrated components like BuildQ, CScope, CppCheck, SnipWiz. I think it is sufficient to just mention these names in the license or other documentation. Putting these names in the GUI is simply distracting. Instead more general names should be used.
The entire porting exercise took me just 3 days, including:
  • the 1st day to install CodeLite, importing MSVC solution, reading CodeLite documentation and getting used to its GUI;
  • the 2nd day to really get hands dirty and fix all the compiling and linking problems. I manged to fix the dll export/import declaration bug at the late night of that day (or probably early morning of the 3rd day), and saw the entire Candle program running nicely at the end. It was a hard-working day for me, but also a rewarding day for me;
  • the 3rd day to clean up the mess. I figured out how to get the debugger working, and linked the main program with the icon resource file;
So what's the moral of the story? The moral is that writing porting C/C++ code might not be so hard, if you:
  • knows what C/C++ features to use and what to avoid;
  • keep your dependencies under tight control;

No comments:

Post a Comment