I'm writing a compiler project which will produce assembly code as the target language. However, there are some small changes that need to be accounted for depending on the operating system, and I'm not sure how to check for the OS. In case it matters, I am concerned with only 32bit. I've seen in some source code something like
#ifdef WIN32
but I have no idea how/if this works.
EDIT: Some clarification. I am using gcc on all three platforms. I don't know if macros like WIN32 are defined via gcc in each platform. If so, these constants seem to solve my issue.
The use of #ifdef
uses preprocessor symbols to conditionally compile code depending on which symbols are defined. In your example, the compiler or an #include
file may define WIN32
, which means the code is being compiled in a Win32 environment.
Depending on the compiler and the platform, there may be different predefined symbols that indicate the operating system or processor architecture (among many other possible things) that relate to the current compilation environment.
With gcc
, you can show the predefined symbols using the following command line:
gcc -E -dM - </dev/null
On my machine, one of the defined symbols is:
#define __FreeBSD__ 8
This happens to mean that I'm running FreeBSD version 8.
(The above applies to C and C-family languages such as C++.)
Generally the essential platform-determinign predefined macros are defined by the compiler itself, often depending on other switches.
Best way for a given compiler is to search for "predefined macros" or "predefined symbols" in their help. eg: googling visual studio predefined macros yields this page.
My OOFILE frameworks covered a wide range of systems. The oofplat.h is available from Sourceforge svn browser and unifies the different compiler definitions into _Windows etc.
Relevant portions copied below. Note that it's fairly ignorant when it comes to differentiating Unix versions as there weren't built-ins defined by the compiler.
#ifndef _Windows
#if defined(_WIN32)
#define _Win32
#define _Windows
#elif defined(WIN32)
#define _Win32
#define _Windows
#elif defined(__WIN32__)
#define _Win32
#define _Windows
#elif defined(__Win32__)
#define _Win32
#define _Windows
#elif defined(_WINDOWS)
#define _Windows
#elif defined(__INTEL__) && defined(__MWERKS__)
// Metrowerks CodeWarrior doesn't build anything other than Win32 on INTEL, no DOS
#define _Windows
#define _Win32
#endif
#else
#if defined __Win32__ || defined _WIN32
#ifndef _Win32
#define _Win32
#endif
#endif
#endif
#ifndef _MSDOS
#ifdef _Windows
#define _MSDOS
#elif defined(MSDOS)
#define _MSDOS
#elif defined(__MSDOS__)
#define _MSDOS
#endif
#endif
#ifdef _Windows
#ifndef STRICT
// some Windows headers define STRICT. In Visual C++ at least having it defined
// affects how static member signatures are mangled, so we define it up front
#define STRICT
#endif
#endif
// if not a DOS machine by now, may be Mac or Unix
// cope with Metrowerks and Symantec (and MPW?)
#ifndef _MSDOS
#ifndef _Macintosh
#ifdef macintosh
#define _Macintosh
#endif
#endif
#ifndef _Macintosh
#define _Unix
#endif
#endif
This is the power of the C preprocessors. First at all, you can define macros:
#define MY_MACRO
After this, you can check if a macro is defined:
#ifdef MY_MACRO
code, code, code
code, code, code
#endif
That means the code inside #ifdef
and #endif
blocks will be valid only if that macro was defined. Else it'll be ignored, and with ignored I mean it'll be like you haven't never written it.
The opposite of #ifdef
is #ifndef
. #endif
is the same for both cases.
In your case, you can use macros in order to change what a function will do:
#define MY_MACRO
void my_function() {
#ifdef MY_MACRO
code_for_my_macro();
#endif
#ifdef ANOTHER_MACRO
code_for_another_macro();
#endif
}
..so the only thing you'll need to do to port your code is changing the macro.
Macros have more utilities. Search for "C preprocessors" and you'll see all what you can do with them.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With