Because you are cross platform developers I ask you how you would do it.
Well, in this project, we went the "easy" way and just used wxWidgets. That's nearly as much trouble as writing your own cross-platform kit, though (and some things still don't work properly on non-Windows).
What I'm using outside this project is a set of headers that implement platform-agnostic wrappers around the most important "concepts". A few typedefs can work wonders for becoming platform agnostic, all that's left then is to call the proper OS functions. In some cases (for example sockets, dns lookup, basically almost everything related to networking), you only need the typedefs and 1-2 helper functions at all, the remainder of the code is identical for all platforms.
If you keep things simple, a surprising amount of your toolkit can be wrapped in 1-2 lines of inline code in the headers. This is not what everyone prefers, but it works nicely and does not bloat up your code, nor does it need any extra files/libraries.
As for #ifdef, I find them extremely ugly and hard to maintain, therefore I clone the entire definition of a class and put everything belonging to one platform into one
#ifdef block (much different to what most people do), or even into separate include files (with only an
#include statement inside
#ifdef in the "real" header).
Whatever is not suitable for being in the headers for some reason is compiled into a static library, which is more convenient than having to add .cpp files to the project. The linker sorts it out just fine.