Reputation: 1746
I want to make the source of my program cross-platform, and so far so good. I have a couple of functions that only really differ in syntax, so I am checking some defines at the start to see if its windows or linux and setting a variable to 1 or 0 depending on which one it is. My thinking was that I could do an if statement check on that variable to skip the incorrect syntax usage. I have realised now that it won't compile because the compiler still 'sees' the offending code. Can you you
#ifdef
to compartmentalize certain functions and call them within the code? Any suggestions?
Upvotes: 1
Views: 848
Reputation: 640
Yes, in the simplest case and assuming for example a function called foo() you can do something like that...
/* Are we on a Windows platform ? */
#if defined(_WIN32) || defined(_WIN64) || defined(__WINDOWS__) || defined(__TOS_WIN__)
void foo( ... ) {
/* windows implementation */
}
/* Are we on a Linux platform ? */
#elif defined(__linux__) || defined(__linux) || defined(linux) || defined(__gnu_linux__)
void foo( ... ) {
/* linux implementation */
}
/* Are we on a Unix platform ? */
#elif defined(__unix__) || defined(__unix) || defined(unix) \
|| defined(__CYGWIN__) || ( defined(__APPLE__) && defined(__MACH) )
void foo( ... ) {
/* unix implementation */
}
/* Are we on Unsupported platform? */
#else
void foo( ... ) {
/* generic implementation */
}
#endif
Another option is to have different header files for each OS that implement the different versions of the function(s), and then conditionally #include
the appropriate one.
Assuming some header files called: myproj_win32.h, myproj_linux.h, myproj_unix.h, myproj_generic.h you could do something like this...
/* Are we on a Windows platform ? */
#if defined(_WIN32) || defined(_WIN64) || defined(__WINDOWS__) || defined(__TOS_WIN__)
#include "myproj_win32.h"
/* Are we on a Linux platform ? */
#elif defined(__linux__) || defined(__linux) || defined(linux) || defined(__gnu_linux__)
#include "myproj_linux.h"
/* Are we on a Unix platform ? */
#elif defined(__unix__) || defined(__unix) || defined(unix) \
|| defined(__CYGWIN__) || ( defined(__APPLE__) && defined(__MACH) )
#include "myproj_unix.h"
}
/* Are we on Unsupported platform? */
#else
#include "myproj_generic.h"
#endif
Only the correct version of the implementation will be compiled. There are more options, but those should be fine to get you started.
EDIT
Here is a useful link with pre-defined macros for common C/C++ compilers.
Upvotes: 1
Reputation: 16389
cpp -d M < /dev/null > somefile
will show the default feature test macro settings (#define values) you can expect from a compiler - for the macros (#ifdef) stuff you want to test for. You have to run this on every system, plus some compilers add macros by default e.g. gcc.
#ifdef _SUN_OS
// put all Sun OS code here
#endif
You will have to find the macros to identify all of your platforms.
Upvotes: 1
Reputation: 22796
Of course you can, that's pretty much the standard way of doing that, at least for small parts of code. For bigger chunks, you might want to use the buildsystem instead, and have platform-specific code in separated files (foo_win.c, foo_unix.c); then, depending on the OS, you compile and link in the application only the right ones.
There are a lot of preprocessor defines that will tell you OS, compiler, architecture and other things; take a look at how Qt detects the OS or the compiler.
Upvotes: 1
Reputation: 32933
You have to enclose the entire non cross-platform section between #ifdef
s.
For instance:
int gettimeofday(struct timeval *tp, void *tzp)
{
#ifdef WIN32
struct _timeb timebuffer;
_ftime(&timebuffer);
tp->tv_sec = timebuffer.time;
tp->tv_usec = timebuffer.millitm * 1000;
return 0;
#else
tp->tv_sec = time(NULL);
tp->tv_usec = 0;
return 0;
#endif
}
Like this the compiler won't see the offending code since it is removed at the preprocessing step.
Upvotes: 4