What are the best practices on writing a cross platform library in C++?
My development environment is Eclipse CDT on Linux, but my library should have the possibility to compile natively on Windows either (from Visual C++ for example).
Thanks.
To some extent, this is going to depend on exactly what your library is meant to accomplish.
If you were developing a GUI application, for instance, you would want to focus on using a well-tested cross-platform framework such as wxWidgets.
If your library depends primarily on File IO, you would want to make sure you use an existing well-tested cross-platform filesystem abstraction library such as Boost Filesystem.
If your library is none of the above (i.e. there are no existing well-tested cross-platform frameworks for you to use), your best bet is to make sure you adhere to standard C++ as much as possible (this means don't #include <linux.h> or <windows.h>, for instance). When that isn't possible (i.e. your library reads raw sound data from a microphone), you'll want to make sure the implementation details for a given platform are sufficiently abstracted away so that you minimize the work involved in porting your library to another platform.
To my knowledge, there are a few things you can do:
You can divide the platform specific code into different namespaces.
You can use the PIMPL idiom to hide platform specific code.
You can use macros do know what code to compile (in this case the code will be platform specific). Check this link for more information.
Test your library in multiple environments.
Depending on what you are doing it might be good to use libraries such as Boost because it is not specific to a platform. The downside (or possibly the good side) is that you will force the use of the libraries you included.
Couple of suggestions from my practical experience:
1) Make sure of regular compilation of sources in your targeted platforms. Don't wait till the end. This'd help point to errors early. Use a continuous build system -- it makes life a lot easier.
2) Never use platform specific headers. Not even for writing native code -- for all you know some stuff in a windows header might expect some string which was ABC in XP but got changed to ABC.12 in Win7.
3) Use ideas from STL and BOOST and then build on top of them. Never consider these to be a panacea for problems though -- STL is easy to ship with your code but BOOST is not.
4) Do not use compiler specific constructs like __STDCALL. This is asking for hell.
5) The same code when compiled with similar compiler options in g++ and cl might result in different behavior. Please have a copy of your compiler manual very handy.
Anytime I work on something like this I try and build it in the different environments that I want to be supported. Similarly if you were making a web page and you wanted to make sure it worked in IE, Firefox, and Chrome you'd test it in all three of those browsers. Test it in the different environments you want to support, and you'll know what systems you can safely say it works for.
question as stated is bit abstract.but you can give QT a consideration
It's really just as simple as "don't using anything platform specific". The wealth of freely available tools availalble these days makes writing cross-platform code in C++ a snap. For those rare but occasional cases where you really do need to use platform specific APIs, just be sure to separate them out via #defines or, better in my opinion, distinct .cpp files for each platform.
There are many alternatives for cross platform libraries but my personal preferences are:
GUI: Qt
OS abstraction (though Qt does a great job of this all by itself): Boost
Cross-platform Makefiles: CMake
The last one, CMake, has been a tremendous help for me over the last few years for keeping my build environment sane while doing dual-development on Windows & Linux. It has a rather steep learning curve but once it's up and running, it works exceptionally well.
You mean besides continuous integration and testing on target platforms? Or besides using design to abstract away the implementation details?
No, can't think of anything.
Related
I'm not sure the way I'm organising my library is the most elegant way to organise it. I'm mainly concerned about making all the code that I type compile/run for all systems that I'm targeting (keeping it portable), and also keeping it up-to-date for every system.
For example:
I'm not sure using __declspec(dllexport/dllimport) would be used for Mac or Linux. I assume that it's not, but I don't know what the equivalent is for Mac/Linux is. Or another example might be calling specific Operating System functions, which I try to avoid. However, things such as: measuring how long something takes to happen*, in a precise manner, does require me to call OS specific functions.
*as in getting the user's time precisely (down to micro/milli-seconds).
The systems that I am currently (perhaps more in the future) aiming for is Mac, Windows and Linux. But testing that the code compiles (and runs correctly) for every system just seems like a waste of time. As currently, the way I'm proposing to do it, requires me to make a separate project for every system. i.e. I create a Visual Studio Project for Windows, an Xcode project for Mac, and use the command line for Linux or use some other IDE.
Okay, so my main problems with the way I organise things are:
1. Time Consumption, as in creating the projects for all systems and keeping each indiviual project, for each system up-to-date.
2. Knowledge on all IDE's/Compilers that I require to use
Please note, I've never really used* Linux before, I'm thinking about switching. The only problem that I'm concerned about is finding the right tools for me to use with it, and finding the right Distro that would suit me, for what I need. I would really appreciate if someone that is experienced with Linux could guide me, or give me some advice whether to switch or not.
I really like Visual Studio, and it's been my main IDE for quite a while now. I'm just not sure if I want to ditch Visual Studio or not, for Linux; as I don't know if the tools that are available for Linux can do what Visual Studio can or not. What I mean is, it being as user friendly as Visual Studio is. I'm afraid to learn how to use Linux's tools, I'm just not sure if it's worth doing so. Time isn't a major factor on this library, I have plenty of time, I'm fairly young and determined to program as my career in the future.
*I have used it before, but I've never replaced it for Windows.
I am currently hosting all my source code for my project on BitBucket, but at the moment, I only have the RAW code on my repo. There is no project files or any other tool to compile it with, just the code and a readme file. I was thinking of using Makefiles, since they seem popular. But I've never made a Makefile before, don't get me wrong, I am willing to learn. I'm just not really sure where to start. I've heard that people use CMake to create portable libraries, such as SFML and Ogre3D. I've built a couple of libraries with CMake, but I have no clue on how to actually make my own library with it to make my project/make files. Should I learn and incorporate CMake with my library, or is there a better option available?
EDIT:
I'm not aiming to write a library for actual Software that uses a GUI. I'm mainly aimed to write games.
1 - Boost. Boost will help your portability more than you can imagine. Its only real sticking point is, believe it or not, OS X.
2 - Use CMake. It integrates with Visual Studio project files as the build tool, and you can put most of your different-platform compilation voodoo in there.
3 - If you're seriously writing a portable library, consider writing it in C/writing a C wrapper, or making it header-only, or providing the source-code. Making it a shared or statically linkable library does not mean that it will play nice. Name mangling leads to inconsistencies that will blow your mind.
4 - Always be explicit about the number of bits in each variable.
5 - use git. It'll allow you to setup a crappy local server for a repository very easy and get very fast transfers of the kind of huge changes MSVC will make annoyingly
There are a lot more best-practices that can be discussed about cross-platform development. All of that advice isn't applicable in every case; I have a very code-heavy Linux/Windows library that I code almost exclusively in MSVC2k10 and mostly build/test for in Linux, and it is nowhere close to header-only.
EDIT in response to comments:
git was suggested because I find it very easy to use and manage locally. I've use svn before and liked it, I won't really endorse any others, but there are probably plenty of fine ones.
To expound on point 3,
A C wrapper would make it so that anyone anywhere could use your library - FORTRAN developers, Ruby, even Java.
Otherwise you generally have to have similar compiler versions to link properly and it will only link to other C++ code, outside the case of DLLs, and there are still versioning issues. It's one of the stupidest problems in C++ left over, check "name mangling" on Wikipedia. There is a reason widely-used libraries are written in C or have C wrappers, such as libz, openssl etc.
There are other advantages to it. Exception propagation across dynamic libraries is non-existent; with static libraries it can be inconsistent or non-existent.
You'll find that the most widely-used C++ libraries are mostly header-only, like Boost. A header-only library solves many problems by putting all the code directly into a project in a relatively intuitive way, and modern compilers can still optimize away much (but certainly not all) of the extra compile time associated with it.
With all this said, it is certainly possible to do without a C wrapper or header-only, it is just annoying and very troublesome. DLL hell and its Linux equivalents still exist.
You also asked about Boost. That depends. If you're distributing the sourcecode then you certainly must distribute Boost with your code/have people install it. Having people install libraries in order to compile other libraries or use programs is common practice. Think of how specific versions of DirectX come with games for an example.
However if you are distributing binary versions of your library, statically linking against Boost will eliminate any need to include it as long as you are careful to keep Boost headers out of the outward-facing parts of your library. This is where you start seeing things like void * pointers inside C++ headers; an unfortunate side-effect of some of the shortcomings of C++ compilation and library distribution unfortunately.
CMake is a good choice. You can learn to use it. Read a tutorial:
http://www.cmake.org/cmake/help/cmake_tutorial.html
But, if your targets are Linux and Windows only. It is probably OK, in your case (small/average first multi-platform project), to maintain 2 separate build systems.
On Linux, Use Make. It is standard and has a very good reference manual:
http://www.gnu.org/software/make/manual/make.html
On Windows. Use your IDE project file, be it Visual, DevC++ or other. That is the simplest way to go.
Most important, make it easy to test your library/software on different platforms. Install a virtual machine on your desktop. Or at least compile your library into Cygwin.
Once you are here come back on stackoverflow and we will help !
Personally I'd leverage a framework like Qt, because it is quite portable, it does abstract a lot of OS functionality (files, timing, threads, networking), and you get a decent, free IDE (Qt Creator) that is also portable and runs on Windows, OS X and any Unix flavor that runs Qt. It'd give you the lowest barrier to entry. Qt Creator can leverage the Visual Studio compiler and the CDB debugger if they are available.
You do not need to use OpenGL to use Qt, in fact you're not bound to any particular graphics subsystem. Qt only "uses" OpenGL in Qt 5 for the Qt Quick 2 graphics backend. It's not needed for Qt 4, nor for Qt Quick 1 (even in Qt 5!).
You can use any 2D or 3D framework you fancy to push images and other content to the screen. What Qt is good at is creating the kind of 2D imagery that is often needed in games - menus, configuration screens, HUDs, etc. There's a lot of controls and drawing primitives that Qt makes easy to leverage for your purposes.
Qt also lets you use a reasonably powerful model-view and networking frameworks, thus you'd be able to reasonably easily generate server or client lists that update in real time.
There'd need to be a small amount of shim code between Qt and DirectX, of course. On the output side, you typically end up with a QImage in Qt, and then use DirectX, SDL, OpenGL, etc. to push it to the screen. On the input side, you need to call qApp->processEvents() within your main game loop, and you will need to post user input events from DirectX etc. to Qt's event queue using qApp->postEvent(...). This would be only needed if, say, DirectX main loop consumes all Windows messages and won't let standard winapi/win32 code (Qt's windows event dispatcher) see them. I haven't deal with DirectX much, so others feel free to chime in with details, of course.
Perhaps some of you people have heard of http://suckless.org/ and their set of Unix tools. Basically, they're a set of programs that each aim to do one thing but do it well, while still being as simple and resource-light as possible.
I've been trying to find a way to reproduce this style of programming on Windows with C++ but all the libraries I know of would produce binaries that are huge with respect to their function. Even the simplest of anything Qt, for example, is generally several megabytes large. I'm not against packaging dependencies along with distributables but I wouldn't want to do it to that level.
Binary size is not one of my main goals but simplicity is and big libraries like these are, by construction, not simple. If binary size were your primary concern you could use runtime compression just like kkreiger or malware.
A possibility would be to go commando and use only ISO Standard C++ libraries but rebuilding a sockets or networking system for a small single-purpose application is not really something anyone would want to be troubled with.
For some reason I thought there was some general-purpouse library that Windows developers could count on everyone and their grandma having readily accessible but now I don't know if anything like that exists. What can you use to write code that adheres to the Unix Philosophy but for Windows targets?
You should target the Win32 API directly. You can't get much lower level than that. In the Windows world, everything directly or indirectly wraps the SDK functions, including the so-called "standard C++ libraries".
Alternatively, you could use something like MFC or WTL, which are relatively thin C++ wrappers over the Win32 API. Because of the overhead of the class libraries, such programs will be slightly smaller than those created using only the SDK, but nowadays, the actual overhead is completely insignificant.
The desires expressed in your question are precisely why I learned and still use the Win32 API today, so that's definitely what I would go with. Plus, your programs will look and feel native, which is way better than the crap most "cross-platform GUI toolkits" put out. The advantages of this can't be underestimated.
But if you just open up Visual Studio and compile a simple little SDK "Hello World" app, it'll still be awfully large. Kilobytes, to be sure, but that still seems like a lot for about the simplest app imaginable. If you really need to cut things down further, you can try telling Visual Studio not to link to the C runtime libraries and define your own main entrypoint. This does mean that you'll have to implement all of your own startup initialization code, but this can reduce the size of a trivial app substantially.
Matt Pietrek had this same idea some years ago, although you'll probably want to take time to "modernize" his original code significantly if you decide to go this route.
FLTK is a popular cross platform minimal gui toolkit.
Or a popular alternative if you don't need too much detailed interaction is just to fire up a minimal embedded webserver and do all the 'gui' in html in a browser.
I need to develop a Windows/Linux command line utility. The utility will talk to middleware that has a standard API on both platforms. I have done some cross-platform development before, on FreeBSD/Linux, which was considerably easier - and I had people in the group with experience that I could talk to.
At this point there is no one in my group who has tackled a Windows/Linux development project. I am looking for advice on how to best set it up. I'm kind of a newbie to C++ too, I have mostly developed C#/.Net GUI applications and Linux device driver level "stuff". Kind of a weird mix.
I was thinking that it would be best to define my own data types and not use either the Linux or the Windows defined types - keep the OS specific code in separate folders and include conditionally. That's kind of what we did for the Linux/BSD work. So it seemed like a good start.
One of the developers here is a big fan of Boost... another thought the TCLAP command line parser library was easier to use... Obviously everything has to be compatible with the licensing.
The code will be open sourced, but it is production code - so I don't want to be sloppy. What else should I be doing or looking for? Are there any best practices out there?
Boost is good, as is ACE. Between the 2 of those they cover pretty much anything you would want to do in a cross-platform manner. I have also gone the route of getting posix libraries for windows and using gcc on cygwin, but I don't recommend it.
Use a portable runtime that is supported on both platforms. I have had good luck with the Apache Portable Runtime.
Use standard C or C++ for most of the project. Only use platform specific functions when necessary. If possible, put those in a wrapper in isolated files so that the build (makefile) can substitute in the correct version for the appropriate platform.
Refrain from using #ifdef LINUX or #ifdef WINDOWS or similar conditional compilation. Those get really hard to debug and there are error prone when the keyword is not supplied to the compiler.
Use Boost. Among other things, you'll get a portable implementation of a subset of TR1, which is worth it if only for <cstdint> and the types within - int32_t etc. As well, shared_ptr is essential for many moderately complicated data structures.
Boost also has a slew of helper types which are extremely convenient in day-to-day C++ tasks. Two specific ones that come to mind right away are optional, and ptr_... polymorphic container types come to mind right away. String algorithm library is also very handy, considering the lack of very commonly needed string functions, such as case conversion or trimming, in the standard library.
Speaking of more heavyweight components, Boost.Filesystem is a very decent cross-platform abstraction for filesystem navigation, also a relatively common task in command-line tools. Then there's Boost.MultiIndex is a swiss army knife of containers - rarely truly needed, but when it is, it's indispensable.
I did a gig this summer in .NET and just ported to Mono. Worked great.
Although there are some good cross platform libraries out there (like Boost), remember that they are probably not there by default. This is especially problematic if you are shipping binaries only. The target platform is unlikely to have the library (or correct version of the library) that you need.
First prize is to stick with standard C++ (even if you need to implement simple stuff yourself). This avoid library dependence altogether.
If you must use a library, try statically linking against it (although this may create big binaries). This will allow you to avoid runtime failure due to lack of binaries.
If you must ship DLLs (or .so on some unixes) make sure that the correct version is shipped with your product and some way to avoid conflicts with the wrong version.
If you are shipping code, include the library with the code and build the library as well as your utility.
Also beware of GPL and possibly LGPL code. If you release a library with a GPL dependency (or modify an LGPL library) you will need to supply the code and allow redistribution as per the GPL.
TCLAP is the only header-only CLI parsing option that I'm aware of. As such, it strikes me as the most portable and is probably your best bet (it's currently what I use and recommend for exactly those reasons). It also helps that the API for TCLAP is very developer friendly and automatically generates decently formatted help messages for you.
Boost program_options has a shard library component to it, which is irritating to maintain ABI with. It also gets around nuisance parsing incompatibilities and behaviors from the getopt family of arguments.
I have used libparamset, that is cross platform (Windows, OS X, Linux) CLI parser. It provides flexible and powerful CLI parser and various UI building features (input error handling, wildcards, typo detection, task resolving, help formatting ...) to build a good command-line tool. It is suitable for both C and C++ projects.
I am writing a small C++ program for fun and for extending my C++ skill. Since its scope is relatively small, I also planning to try out cross-platform development by making this program support both Windows and Linux.
I reckon my C++ proficiency is sitting somewhere between casual and intermediate level: OO, a bit of templates and design patterns, used STL before and trying to look into it more in details, ... However, while coding this little program, I find that the deeper I dig into C++, the more pain I feel, especially when I come to understanding and dealing with differences between different platform's/vendor's implementation.
The use of cross-platform frameworks like Qt, ACE, Boost seems help to speed up development a lot thus make life easier, but I worry if this will beat my purpose. Can somebody give some advice if there is any "best practice" for doing C++ cross-platform development? Thanks.
Can somebody give some advice if there is any "best practice" for doing C++ cross-platform development?
There are three things:
Write your own code so that it's portable
Wrap platform-specific APIs behind an abstraction/insulation/utility layer
Choose cross-platform libraries
You can choose option #2 and/or #3.
Advantages of #3 over #2 tend to be things like, "It's already written, debugged, and supported"; and the disadvantages are like, "I have to learn it, I might have to pay for it, I can't necessarily support it myself, and it may not do exactly what I want."
Developers will often prefer option #3 instead of #2, especially if it's free open source (which all three of the libraries that you cited are).
http://blog.backblaze.com/2008/12/15/10-rules-for-how-to-write-cross-platform-code/
Should provide more detail to the answers already given.
Also I suggest using existing libraries that abstract endianness, data type sizes and differences. The following should be considered before starting your cross-platform project.
GUI
Qt
XVT
wxWidgets
General Libraries/frameworks
STL (Incorporated in most platform libraries already)
Boost
Game Development
SDL
Cocos2d-x
Use gcc. It's available on both Windows and Linux and the libraries and language syntax is identical on both platforms.
For cross platform GUI applications, Qt is a good idea. There is no getting away from having a dependency on a GUI framework if you are trying to achieve platform independence.
Unless you are doing GUI stuff cross platform isn't a big problem.
There are some small issues to do with filesystems ( different / \ separators, allowed characters in filenames etc) but these are at the application level rather than the c++.
Doing major applications gets more complex, you need to handle help, file locations an possibly security and user info in a cross platform way. For simple algorithm type programming there isn't a problem.
Qt is mainly a GUI library, although it has extra cross platform filesystems stuff. STL, Boost, ACE are cross platform but that isn't there main point.
Use them! Seriously. The only reason you may not want to use them is if you plan on working in an environment where they're not available. But, given their cross-platform nature, that's not likely.
You will find that the benefit you get from using them is immense, even if they weren't cross-platform. The "best practice" you speak of is to be able to deliver your "product" as quicly and easily as possible.
I once answered a question from someone who stated he didn't want to use GUI libraries at a level above Xlib. If he'd actually ever used Xlib, he'd know the pain we'd all felt when forced to code at such a low level of abstraction. This makes about as much sense as wanting to code in assembler because C/C++?Python/Perl/everthting-else is simply a higher-level abstarction.
this answers are really good and you can make a list for find where is the beginning. but i think you should read some articles about "porting application".not relevant with cross-platform development but this can give you very large perspective about cross platform development. In cross-platform developing, one of more importing thing is memory issues like "endian" (byte order- byte order can show differences for tehnologies or platforms)
use boost. they take care of cross-platform stuff for you.
boost::filesystem is a great example
i think you can learn a lot from using ACE or equivalent libraries. they will boost your understanding of c++ and design patterns. i think this is the best thing you can do to improve your coding skills.
If your are really interested in making your code as cross-platform as possible, use as many compilers as possible. If you are using Windows and Linux, use VC and gcc, at the minimum. This will ensure that you don't use complier specific features, and that you don't rely on system specific behavior. Use more compilers (Intel, IBM, etc) and OSs (OS X, Solaris) if you have access to them.
You can try using U++ > http://www.ultimatepp.org/index.html
With all the fuss about opensource projects, how come there is still not a strong standard that enables you to make portable code (I mean in C/C++ not Java or C#)
Everyone is kind of making it's own soup.
There are even some third party libs like Apache Portable Runtime.
Yes, there is no standard but libraries like Qt and boost can make your life much easier when you do cross-platform development.
wxwidgets is a great abstraction layer on the native GUI widgets of most window managers.
I think the main reason there isn't any single library anyone agrees on is that everyone's requirements are different. When you want to wrap system libraries you'll often need to make some assumptions about what the use cases will be, unless you want to make the wrapper huge and impossible to work with. I think that might be the main reason there's no single, common cross platform runtime.
For GUI, the reason would be that each platform has its own UI conventions, you can't code one GUI that fits all, you'll simply get one that fits just one or even none at all.
There are many libraries that make cross-platform development easier on their own, but making a complete wrapper for all platforms ends up being either small and highly customized, or massive and completely ridiculous.
Carried to it's logical conclusion, a complete wrapper for all aspects of an operating system becomes an entire virtual runtime. You might as well make your own programming language.
The ADAPTIVE Communication Environment (ACE) is an excellent object oriented framework that provides cross-platform support for all of the low level OS functionality like threading, sockets, mutexes, etc. It runs with a crazy number of compilers and operating systems.
C and C++ as languages are standards languages. If you closely follow their rules when coding (That means not using vendor-specific extensions) you're code should be portable and you should be able to compile it with any modern compiler on any OS.
However C and C++ don't have a GUI library, like Java or C#, however there exist some free or commercial GUI libraries that will allow you to write portable GUI applications.
I think the most populars are Qt (Commercial) and wxWidgets (FOSS). According to wikipedia there is a lot more.
There is also boost, while not a GUI library boost is a really great complement to C++'s STL. In fact some of the boost libraires will be added in the next C++ standard.
If you make sure it compiles cleanly with both GCC and MS VC++, it will be little extra effort to port to somewhere else.