Development experience between Windows and Linux
It all started in 2012 when I had a chance to port my all image processing codes from Windows to Linux. That includes all C++ codes with lots of GUI implementation, not to mention several COM model architecture and several Windows-only technologies. For now, I'm very happy to work between these two platforms under the same code base. This might be very normal to some of you, but with 10+ years of Windows codes, it is still a struggle to migrate all to Linux in 4 months. Here is the story:
What I have in Windows in 2012:
1. Lots of C++ codes, few assembly codes.
2. Windows MFC GUI
3. WIndows Direct-X
4. WIndows WIC image I/O
5. 60% of my shared module are exposed as COM objects (COM dlls)
6. All my codes are not x64 ready.
7. It also links to several 3rd-party libraries (Intel TBB, open-source libraries, ...)
1. all non-GUI C++ codes should work in Linux and Android native.
2. should be compliant to gcc 4.4
3. should be x64 ready
4. all performance should meet the same levels as on Windows.
I pick some modules as pilot run. They are
(a) One application in MFC, Direct-X, WIC, COM, Intel TBB, OpenMP and several open-source libraries.
(b) One application we are going to make it in Android.
I set one month (around 20 working days) to make it.
Here are the steps I did:
1. Make all codes as x64 ready: it is pretty much to fix all data-type casting, parameter types mismatching, use intrinsic asm functions to replace embedded asm codes, and re-buld all open-source library to be x64 compliants. With help of Visual Studio, I can fix it quickly with several useful compiler options. It took me 5 days to fix all and test.
2. For non-GUI codes, need to remove all system-dependent functions. It took me around 2 days to make it. Some of them are done while doing x64 porting. In my cases, string-handling, file I/O handling, memory handling, and system information query are the key points. For string, I/O, and memory functions, I replace everything in C++ counterparts. For system-dependent system information query codes, I define a new abstraction layers to call system functions. It was a two-day jobs. Note: I did not finish system codes for linux or Android at this moment. New codes are tested in Windows only. It is worth to mention that, Linux has no unicode supports like windows SDK, I need to use i18L libraries to make it, and it works well in Windows. I also use boost libraries to replace several system-dependent codes.
3. Fix COM calling issue: COM is only available in Windows, not in Linux or Android. Luckily, COM is just a object-model concept, and most of them are done in C macro. That means I can do the same thing with my COM layer. I dig into Windows ATL codes a lot, and re-use several of them for my own layers. It took me about 4 days to make it. That means, I don't have to call CoInitialize() to use my own COM objects.
4. Fix WIC image I/O. It is by far the hardest parts for me. There is no "standard" image I/O libraries in Linux or Android native, so my first idea is to find a good-quality image libraries to make it. FreeImage, ImageMagick are the choices. I finally use FreeImage since it also claims to support Android. The result result is good, however the loading speed is far slow than Windows WIC. It tooks me one day to switch to FreeImage, but 3 more days to adjust the performance, especially JPEG, PNG, and TIFF.
5. Before I want to fix GUI and DirectX codes, I decide to move all non-GUI code to Linux and see how it works. I do have several test program for my codes in Windows console mode, which is quite suitable for testing purpose in Linux, which I don't need to face GUI at this moment. The first experience to compile those codes in GCC is not compiler itself, but the makefile. I am a Windows developers, which is familiar with compile C codes to obj, setup all options to linker and make it a static libraries, dll or exe. I can do it in command line also. But with makefile, it is like a new language to me. Even I worked with several open-source project, but do not study it deeply.
By googling around, I can find several ready-to-use template and several tutorials to help me come out a draft makefile for my test program. It turns on very simple, more like a macro definitions. Then, it is time to call gcc to work. Not bad, just few error about type casting, template definition issue, C++ language compliance issue, and system-dependent functions.
I also face lots of filename issue while include header files in my C codes. Linux filesystem is case-sensitive, that includes C++ header files. I spent several hours to find and replace them to correct filename. I think it is a good practices for me to use all lower-case for header filename in the future to prevent from this issue.
This step took me around 2 days. And, the result is quite acceptable.
6. GUI code porting: that includes MFC and DirectX. I asked for help from online forum, and all suggestions to me go to Qt. I did a quick installation and review several examples, it turns out that Qt is a quite good framework. The downside is, it is not free for commercial purpose. I also survey wxWidgets, it is ok, but compared to Qt, Qt is a full-framework along with several system-independent data structures, functions, also, it has a full-function IDE QtCreator to help my GUI works. Furthermore, Qt has built-in OpenGL support, which I can migrate my Direct-X codes in OpenGL easily.
Once I decided to use Qt, my initial plan is to follow some tutorial to migrate my MFC codes to Qt. But I finally do it from scratch. The reason is I do want to have a fresh experience about how Qt GUI is working, and how developers should work with art/UE designers later. If I just mapping MFC calls to Qt, I don't have that kind of experience.
Qt Creator is quite a easy-to-learn tool, I can layout my UI in few minutes. Even my MFC program is MDI or dialog-base, I can always find a good way to fit them. MFC message mechanism can also be replaced by signal-slot concept. Multi-language is also easy in Qt. This steps took me 5 days to make the first GUI program to run in Linux (Ubuntu actually.)
7. Till now, I am satisfied with the performance on my Ubuntu 14.04 box (the same hardware as my Windows 8 box.)
8. Next step is to port to Android native. Theoretically, it should be no problem for your Linux-compliant codes to work in Android since most Android device use Linux as base OS. It just took me quite a while to setup Android Studio, and setup NDK. Also, because Android Studio does not support NDK, I need to learn gradle and Android make file (again!) to compile my C++ codes for Android.
I used latest NDK at that moment (r9), the compiling process is quite smooth, no major errors. Then I layout a simple test program to test it on Android, it starts and worked perfectly, however, found out that OpenMP does not work well if I run my C codes in non-main thread. So, It is time to stripe all openMP codes for Android build.
That is the whole steps I migrate my Windows codes to LInux and Android. I do not steps into very details, but they are the steps I did to my all other codes. Let me know if you have any questions.