tags:

views:

787

answers:

6

I am writing a program that is cross platform. There are a few spots where I have to specify an operating system dependent call.

#ifdef WINDOWS
..do windows only stuff
#endif
#ifdef LINUX
..do linux only stuff    
#endif

Are there any preprocesser directives that get defined by the compiler so I don't have to explicitly define them when I use the command line compiler. ie.

cl -DWINDOWS program.cpp

or

g++ -DLINUX program.cpp

I realize I could easily write a makefile or have a shell/batch script that will do this automatically. But I would prefer to use the same ones as the compiler (if they exist) by default.

A: 

Yes. I believe WIN32 is, but I'm not on a windows right now to test it :D

See: http://en.wikipedia.org/wiki/C_preprocessor (it mentions WIN32)

luiscubal
It says it is defined by Win32 compilers only. Not Unix/Linux.
Lucas McCoy
This doesn't seem to work using visual studios command line compiler. I checked it by saying#ifndef WIN32#error This compiler does not define WIN32#endifand it printed out an error
DHamrick
Weird. I'm quite sure WIN32 is defined by Mingw, though.
luiscubal
+3  A: 

I found a complete list for all g++'s on this website.

  • #define __HAVE_BUILTIN_SETJMP__ 1
  • #define __unix__ 1
  • #define unix 1
  • #define __i386__ 1
  • #define __SIZE_TYPE__ unsigned int
  • #define __ELF__ 1
  • #define __GNUC_PATCHLEVEL__ 3
  • #define __linux 1
  • #define __unix 1
  • #define __linux__ 1
  • #define __USER_LABEL_PREFIX__
  • #define linux 1
  • #define __STDC_HOSTED__ 1
  • #define __EXCEPTIONS 1
  • #define __GXX_WEAK__ 1
  • #define __WCHAR_TYPE__ long int
  • #define __gnu_linux__ 1
  • #define __WINT_TYPE__ unsigned int
  • #define __GNUC__ 3
  • #define __cplusplus 1
  • #define __DEPRECATED 1
  • #define __GNUG__ 3
  • #define __GXX_ABI_VERSION 102
  • #define i386 1
  • #define __GNUC_MINOR__ 2
  • #define __STDC__ 1
  • #define __PTRDIFF_TYPE__ int
  • #define __tune_i386__ 1
  • #define __REGISTER_PREFIX__
  • #define __NO_INLINE__ 1
  • #define _GNU_SOURCE 1
  • #define __i386 1
  • #define __VERSION__ "3.2.3 20030502 (Red Hat Linux 3.2.3-47.3)"

And Visual C++ already has Win32 defined to use for any Widnows version.

Lucas McCoy
+2  A: 

Yes, there are such pre-defined symbols but I don't recommend you use them unless you never, ever, forsee supporting more platforms, compilers or operating system versions. Here's the logic.

First, you're better off with your own minimal set of defined compilation constants for use within your code. Because you might start with things like this:

#if defined(_WIN32)
    // do windows stuff
#endif
#if defined(_linux)
    // linux stuff
#endif

Suppose you allow compilation under a new compiler for windows that doesn't define _WIN32 automatically? You can change every _WIN32 line to something like:

#if defined(_WIN32) || defined(ming)

Which is a real pain in the butt if you have more than one of those to change. You could put something like this at a high level:

#if defined(ming)
#define _WIN32
#endif

But you'll likely discover that some system or library header file freaks out because they happen to use _WIN32. Better you had abstracted it in a common header file:

#if defined(_WIN32) || defined(ming)
    #define PLAT_WINDOWS
#endif

And then simply use #if defined(PLAT_WINDOWS) where needed.

But what about that common header file? Well, when a new compiler/OS/whatever comes along you have to start tweaking it to make sure it says the right things. Pretty soon it is a comical hairball of condition that can only be understood if you know about every version of every compiler on every operating system on the planet. And gee, who doesn't but nevertheless any changes made have to be tested everywhere and that is painful.

So, better you just have some high level setting inside the makefile or even outside it that says "if you're on windows, -DPLAT_WINDOWS" and be done with it.

Of course, all this is minimized if you use the most commonly available functions and features in your code.

George Phillips
+1  A: 

All of these answers were very good. The solution that worked for me was the following.

#ifdef _WIN32

#endif

#ifdef linux

#endif

WIN32 was not defined by cl but _WIN32 was. linux was defined by g++.

DHamrick
Glad to see you answer your problem by combining or solutions, but that doesn't solve my problem on gaining rep because you can't accept all our answers. ;-)
Lucas McCoy
_WIN32 may be defined in Visual C++, but I'm quite sure it's defined in Mingw.
luiscubal
A: 

Instead of having two macros for specific platforms, you may have the code in #ifndef #else block. For example:

#ifndef _WIN32
// linux specific code
#else
// windows specific code
#endif

With this solution, the ifndef-else block will make sure that you don't accidentally add code in between the two #ifdef blocks (which supposedly be handling the program execution flow in same manner).

The above code will also give you independence of compiling this code not just for linux but any unix platform, provided it supports the call, without changing the macro label from linux to unix or something else.

Rahul