2010-10-10 8 views
4

Je suis en train d'écrire un projet de compilateur qui produira du code assembleur en tant que langue cible. Cependant, il y a quelques petits changements qui doivent être pris en compte selon le système d'exploitation, et je ne suis pas sûr de savoir comment vérifier le système d'exploitation. Au cas où cela compte, je suis préoccupé par seulement 32bit. J'ai vu dans quelque code source quelque chose commeComment vérifier si le système d'exploitation actuel est Windows, Linux ou OSX?

#ifdef WIN32 

mais je n'ai aucune idée comment/si cela fonctionne.

EDIT: Quelques précisions. J'utilise gcc sur les trois plateformes. Je ne sais pas si les macros comme WIN32 sont définies via gcc dans chaque plate-forme. Si oui, ces constantes semblent résoudre mon problème.

+0

Avez-vous l'intention de créer un compilateur croisé, de sorte que votre compilateur fonctionnant sous Windows puisse générer du code pour Linux, etc? –

+0

Non. Je veux seulement qu'il génère du code qui puisse fonctionner dans l'environnement actuel. – Kizaru

Répondre

8

L'utilisation de #ifdef utilise des symboles de préprocesseur pour compiler le code de manière conditionnelle en fonction des symboles définis. Dans votre exemple, le compilateur ou un fichier #include peut définir WIN32, ce qui signifie que le code est compilé dans un environnement Win32. En fonction du compilateur et de la plate-forme, il peut exister différents symboles prédéfinis qui indiquent l'architecture du système d'exploitation ou du processeur (entre autres choses possibles) en rapport avec l'environnement de compilation actuel.

Avec gcc, vous pouvez afficher les symboles prédéfinis en utilisant la ligne de commande suivante:

gcc -E -dM - </dev/null 

Sur ma machine, l'un des symboles définis est:

#define __FreeBSD__ 8 

Cela arrive à dire que je Je suis sous FreeBSD version 8.

(Ce qui précède s'applique aux langages de la famille C et C tels que C++.)

+0

Merci. Cela semble être exactement ce dont j'ai besoin. Je n'étais pas au courant de cette fonctionnalité à l'intérieur de gcc (enfin, je ne sais pas comment l'utiliser au moins). – Kizaru

1

C'est la puissance des préprocesseurs C. Tout d'abord du tout, vous pouvez définir des macros:

#define MY_MACRO 

Après cela, vous pouvez vérifier si une macro est définie:

#ifdef MY_MACRO 
code, code, code 
code, code, code 
#endif 

Cela signifie que le code à l'intérieur #ifdef et #endif blocs ne seront valables que si ce la macro a été définie. Sinon, il sera ignoré, et avec ignoré Je veux dire que ce sera comme si vous ne l'avez jamais écrit. L'inverse de #ifdef est #ifndef. #endif est la même pour les deux cas.

Dans votre cas, vous pouvez utiliser des macros pour changer quelle fonction fera:

#define MY_MACRO 

void my_function() { 
#ifdef MY_MACRO 
    code_for_my_macro(); 
#endif 
#ifdef ANOTHER_MACRO 
    code_for_another_macro(); 
#endif 
} 

..so la seule chose que vous aurez besoin de faire au port de votre code est en train de changer la macro.

Les macros ont plus d'utilités. Recherchez "préprocesseurs C" et vous verrez tout ce que vous pouvez faire avec eux.

+0

Oui, je connais les macros. Ma question était un peu imprécise - je m'excuse. Je n'étais pas sûr à propos des macros pour déterminer le système d'exploitation, mais la réponse de Greg Hewgill aide à résoudre ce problème. Bien que votre réponse n'ait pas été nécessaire, elle est toujours utile pour les autres, donc je vais continuer à la voter. – Kizaru

2

Généralement, les macros prédéfinies essentielles à la détermination de la plate-forme sont définies par le compilateur lui-même, souvent en fonction d'autres commutateurs.

La meilleure façon pour un compilateur donné est de rechercher des "macros prédéfinies" ou des "symboles prédéfinis" dans leur aide. Exemple: googling Les macros prédéfinies Visual Studio donnent this page.

Mes frameworks OOFILE couvraient un large éventail de systèmes. Le fichier oofplat.h est disponible à partir de Sourceforge svn browser et unifie les différentes définitions de compilateur dans _Windows, etc.

Les parties appropriées sont des images copiées ci-dessous. Notez qu'il est assez ignorant quand il s'agit de différencier les versions Unix car il n'y avait pas de built-ins définis par le compilateur.

#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