C++ cross platform code
We our going to start a new project in our small team:
- It's a library which will be used by our other projects (in Linux and Windows).
- It's not platform dependent logically (it's not using any system calls or anything like that).
- It has to be compiled on various platforms (including Windows and Linux at least).
Unfortunately, non of our developers ever wrote any 开发者_开发知识库code in any other platform than Windows! Therefore, I have to give them a "code like this" or "not code like this" list, so the code will stay cross platform.
any guidance?
One way of increasing portability is to use the same compiler, GCC, on both platforms. If you also use the same compiler version, you will probably avoid most, if not all C++ language and Standard Library incompatibilities. You can also use the same build tools, such as GNU make, which means the build process is the same on both platforms.
As for platform incompatibilities - check that their code does not contain includes like:
#include <windows.h>
#include <unistd.h>
#include <sys/almost_anything.h>
unless this is done via conditional compilation.
Make sure that you have automated build processes on all platforms, and write unit and automated functional tests. If possible run automated nightly builds and tests. It's much more important when you are writing cross platform libraries.
I would do the opposite of one of the other answers (Not that i think it's wrong, just a different approach) and if you can choose your platforms make them as different as possible. For example make one 32 bit MCVC and the other 64 bit gcc on unix. If you can have automated tests and builds then this will show up portability issues quickly.
If possible have some developers working on one platform and some on another rather than finishing the code on one platform and then "porting" it to the other. That way they'll learn very quickly what not to do when their co workers come over to complain they broke something.
Technically things to watch out for are
- Don't assume ints are 32 bits
- Don't assume char's are signed or unsigned
- Don't assume characters are in ASCII
- Don't assume anything about data byte order or alignment
- Minimize pointer arithmetic. You'll only get it wrong when you make assumptions that fail.
- Remember file and directory names work differently on different platforms. If you only have to port to windows and unix you might get awayy with it but once you've ported to two platforms then the next port might be to z-series or VMS where these things work quite differently.
Most importantly: have automatic builds and tests running on all supported platforms, all the time, to pick up most non-portable (or just wrong) code straight away.
The language itself, the Standard Library, and Boost should be portable to any widely-used platform (certainly modern versions of Linux/GCC and Windows/MSVC). Be suspicious of any system header file that ends with .h
, and check other libraries for portability before deciding to use them.
Maintain a document of all the incompatibilities you encounter, so hopefully you'll only make each mistake once.
Just tell them not to use Windows API and they should be good to go.
I'd also suggest increasing your warning/error level, if developing in Visual Studio, as it will prevent you from doing some things that gcc (normally) won't allow, assuming you're using gcc to compile for Linux. You can also disable Visual Studio extensions in project settings.
Evidently if someone needs to use something platform-specific, they should use defines that replace the platform-specific code depending on which platform it's being compiled on.
Compile with as many compilers as possible, even if only on a limited number of platforms. Off the top of my head, VC, gcc, intel, pgi. If you can get older versions of some of them, that would help as well. All of the developers don't need to use these, but run them nightly with the results available to all of the developers. Its much easier to fix problems as they come up, rather than trying to fix all of the issues when you are trying to release.
Some suggestions:
Use
static_cast<>
,dynamic_cast<>
andconst_cast<>
instead of C-style casts. Ifreinterpret_cast<>
has to be used, review it, and surround that code with careful unit tests. (The point of this rule is to prohibit clever bit-twiddling and reliance on sizes or alignments.)Use modern standard C++ libraries only: no MS-specific libraries like (brrr!) MFC and its
CString
.
You might add some of the recommendations here, but be aware that some are a bit too pessimistic for reasonably modern compilers (e.g. recommendation #16 on temporary objects, and #18 is directly in conflict with the STL parts of the library).
From experience of developing on Linux amongst Windows developers the main issue normally (provided you really are not using platform dependent code as you say) is just that of case sensitivity in #include file names. Apart from that you will find that gcc is, by default, stricter than MSVC and so you may need to tighten up a few things up but they are usually quite straightforward.
One particular thing to watch out for is that std::map::erase
does not return an iterator.
精彩评论