Cross-platform Developmen

I would like my programs and libraries to work on different platforms, as much as possible. Primary target is always Linux and Unix-like systems of course, though I would like to provide same functionality on Windows and maybe Android and iOS. The platform, should not be a restriction for using softwares. This lead to the idea of Cross-Platform Development. Unfortunately it’s not easy. There is no accepted standardization of operation system APIs or common operations between operating systems. Developers should write code with cross-platform requirements in mind.  I’m going to describe my own experience with cross-platform development in the Artificial Intelligence Toolkit project. I encountered lots of problems and resolved some of them. This article provides a simple check-list to help developers avoid most frequent issues of cross-platform development in C/C++. Let’s go ahead 🙂

The Language

I. So shalt not code in a platform-specific language.

Just don’ do that. Don’t code in C#, C++ CLI or other Microsoft tools.

C++ is cross-platform enough

C++ is cross-platform enough cause it has a compiler on every platform (at least major ones)

The Code

II. So shalt not write platform-dependent code. Even in cost of adding more dependencies.

Rule number one says that your code should not rely on platform-specific staff. That’s not using Berkeley socket API in Linux or its Windows compeer, Winsock for example. Rather than using such APIs, add a third party dependency. For above example, using ASIO to do networking may be a cross-platform solution. ASIO itself is cross-platform so your code will run on both Windows and Linux.

In the case that you are developing an operating system level API, then you have to write code for each platform and specify which code to compile using compile-time conditional directives.

void delay(int ms)
{
#ifdefined(OS_WIN32)
              Sleep(ms);
#elifdefined(OS_LINUX)
             usleep(ms*1000);
#endif
}

In the presence of standard mechanism for any task, developer should consider about using standard way rather than invoking operating system functions. Above code can be replaced with this one:

void delay(int ms)
{
    // Guaranteed to run properly on every platform if it compiles!
    std::this_thread::sleep_for(std::chrono::milliseconds(ms));
}

Second delay need C++11 support. After 2014 guys at Microsoft may decide their compiler suite not to be an outdated one and may support C++11 completely.

The Build System

III. So shalt not use a platform-specific build system. Even in cost of providing more than one build system for different platforms.

Different platforms use different build systems. Most common build systems are GNU make and Microsoft’s NMake. There are plenty of nice build script generation tools like GNU autohell, CMake, Qt’s qmake and Microsoft Visual Studo! Yes that’s true 🙂 Visual Studio is an IDE that generates makefile from solution file. So it can be considered as a build script generator.

Personally I prefer autotools for both Linux and Windows. On windows it can be used with MSYS/MinGW with no problem. After all, from compiler to build system, the GNU toolchain can not be considered as a first degree citizen in Windows. That’s why you may want to compile your code with MSVC. Fortunately build systems do not conflict with each other. Simply add a visual studio project to source sandbox at the same level with your autotools files. If you feel so scrupulous, you can jail build system files in different directories and share source code between them. Such a development ecosystem will happily continue to its life with no trouble.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s