web-dev-qa-db-fra.com

Comment vérifier le système d'exploitation avec une directive de préprocesseur?

J'ai besoin que mon code fasse différentes choses en fonction du système d'exploitation sur lequel il est compilé. Je cherche quelque chose comme ça:

#ifdef OSisWindows
// do Windows-specific stuff
#else
// do Unix-specific stuff
#endif

Y a-t-il un moyen de faire cela? Y a-t-il une meilleure façon de faire la même chose?

144
perimosocordiae

Le site Macros Predefined for OS contient une liste très complète de vérifications. En voici quelques-unes, avec des liens vers les endroits où elles se trouvent:

Les fenêtres

_WIN32 32 bits et 64 bits
_WIN64 64 bits uniquement

Unix (Linux, * BSD, Mac OS X)

Voir cette question liée sur certains des pièges de l’utilisation de cette vérification.

unix
__unix
__unix__

Mac OS X

__Apple__
__MACH__

Les deux sont définis; rechercher l'un ou l'autre devrait fonctionner.

Linux

__linux__
linux Obsolète (non compatible POSIX)
__linux Obsolète (non compatible POSIX)

FreeBSD

__FreeBSD__

218
Lambda Fairy

show GCC définit sous Windows:

gcc -dM -E - <NUL:

sous Linux:

gcc -dM -E - </dev/null

Macros prédéfinies dans MinGW:

WIN32 _WIN32 __WIN32 __WIN32__ __MINGW32__ WINNT __WINNT __WINNT__ _X86_ i386 __i386

sous UNIX:

unix __unix__ __unix
62
qwer

Basé sur nadeausoftware et réponse de Lambda Fairy .

#include <stdio.h>

/**
 * Determination a platform of an operation system
 * Fully supported supported only GNU GCC/G++, partially on Clang/LLVM
 */

#if defined(_WIN32)
    #define PLATFORM_NAME "windows" // Windows
#Elif defined(_WIN64)
    #define PLATFORM_NAME "windows" // Windows
#Elif defined(__CYGWIN__) && !defined(_WIN32)
    #define PLATFORM_NAME "windows" // Windows (Cygwin POSIX under Microsoft Window)
#Elif defined(__Android__)
    #define PLATFORM_NAME "Android" // Android (implies Linux, so it must come first)
#Elif defined(__linux__)
    #define PLATFORM_NAME "linux" // Debian, Ubuntu, Gentoo, Fedora, openSUSE, RedHat, Centos and other
#Elif defined(__unix__) || defined(__Apple__) && defined(__MACH__)
    #include <sys/param.h>
    #if defined(BSD)
        #define PLATFORM_NAME "bsd" // FreeBSD, NetBSD, OpenBSD, DragonFly BSD
    #endif
#Elif defined(__hpux)
    #define PLATFORM_NAME "hp-ux" // HP-UX
#Elif defined(_AIX)
    #define PLATFORM_NAME "aix" // IBM AIX
#Elif defined(__Apple__) && defined(__MACH__) // Apple OSX and iOS (Darwin)
    #include <TargetConditionals.h>
    #if TARGET_IPHONE_SIMULATOR == 1
        #define PLATFORM_NAME "ios" // Apple iOS
    #Elif TARGET_OS_IPHONE == 1
        #define PLATFORM_NAME "ios" // Apple iOS
    #Elif TARGET_OS_MAC == 1
        #define PLATFORM_NAME "osx" // Apple OSX
    #endif
#Elif defined(__Sun) && defined(__SVR4)
    #define PLATFORM_NAME "solaris" // Oracle Solaris, Open Indiana
#else
    #define PLATFORM_NAME NULL
#endif

// Return a name of platform, if determined, otherwise - an empty string
char *
get_platform_name() {
    return (PLATFORM_NAME == NULL) ? "" : PLATFORM_NAME;
}

int main(int argc, char *argv[]) {
    puts(get_platform_name());
    return 0;
}

Testé avec GCC et clang sur:

  • Debian 8
  • Windows (MinGW)
  • Windows (Cygwin)
17
Seti Volkylany

Dans la plupart des cas, il est préférable de vérifier si une fonctionnalité donnée est présente ou non. Par exemple: si la fonction pipe() existe ou non.

10
quinmars
#ifdef _WIN32
// do something for windows like include <windows.h>
#Elif defined __unix__
// do something for unix like include <unistd.h>
#Elif defined __Apple__
// do something for mac
#endif
7
Arjun Sreedharan

Les macros prédéfinies du compilateur MS peuvent être trouvées ici:

http://msdn.Microsoft.com/en-us/library/b0084kay(VS.80).aspx

Je pense que vous recherchez:

_WIN32
_WIN64

vous pouvez trouver ici les MAcros prédéfinis du compilateur gcc:

http://gcc.gnu.org/onlinedocs/cpp/Predefined-Macros.html

Je pense que vous recherchez:

__GNUC__
__GNUC_MINOR__
__GNUC_PATCHLEVEL__

Faites un google pour vos compilateurs appropriés prédéfinis.

5
Martin York

Sur MinGW, la vérification _WIN32 define ne fonctionne pas. Voici une solution:

#if defined(_WIN32) || defined(__CYGWIN__)
    // Windows (x86 or x64)
    // ...
#Elif defined(__linux__)
    // Linux
    // ...
#Elif defined(__Apple__) && defined(__MACH__)
    // Mac OS
    // ...
#Elif defined(unix) || defined(__unix__) || defined(__unix)
    // Unix like OS
    // ...
#else
    #error Unknown environment!
#endif

Pour plus d'informations, veuillez consulter: https://sourceforge.net/p/predef/wiki/OperatingSystems/

3
anakod

Il n'y a pas de macro standard définie selon le standard C. Certains compilateurs C en définiront un sur certaines plates-formes (par exemple, le correctif GCC d'Apple définit une macro pour indiquer qu'il compile sur un système Apple et pour la plate-forme Darwin). Votre plate-forme et/ou votre compilateur C peuvent également définir quelque chose, mais il n'y a pas de moyen général.

Comme le dit hayalci, il est préférable que ces macros soient définies dans votre processus de construction. Il est facile de définir une macro avec la plupart des compilateurs sans modifier le code. Vous pouvez simplement passer -D MACRO à GCC, c.-à-d.

gcc -D Windows
gcc -D UNIX

Et dans votre code:

#if defined(Windows)
// do some cool Windows stuff
#Elif defined(UNIX)
// do some cool Unix stuff
#else
#    error Unsupported operating system
#endif
3
Mecki

Désolé pour la référence externe, mais je pense que cela convient à votre question: 

Astuce C/C++: Comment détecter le type de système d'exploitation à l'aide de macros prédéfinies du compilateur

2
bruziuz
2
MD XF

Utilisez #define OSsymbol et #ifdef OSsymbol Où OSsymbol est un symbole capable #define 'identifiant votre système d'exploitation cible.

En règle générale, vous devez inclure un fichier d’en-tête central définissant le symbole du système d’exploitation sélectionné et utiliser les répertoires d’inclusion et de bibliothèque propres à un système d’exploitation pour la compilation et la création.

Vous n'avez pas spécifié votre environnement de développement, mais je suis presque sûr que votre compilateur fournit des définitions globales pour les plates-formes et les systèmes d'exploitation courants.

Voir aussi http://en.wikibooks.org/wiki/C_Programming/Preprocessor

2
devio

Certains compilateurs vont générer #defines qui peuvent vous aider avec ceci. Lisez la documentation du compilateur pour déterminer ce qu’ils sont. MSVC définit celui qui est __WIN32__, GCC a certains que vous pouvez voir avec touch foo.h; gcc -dM foo.h

1
davenpcj

Vous pouvez utiliser Boost.Predef qui contient diverses macros prédéfinies pour la plate-forme cible, y compris le système d'exploitation. Oui, boost est souvent considéré comme une bibliothèque C++, mais celle-ci est un en-tête de préprocesseur qui fonctionne aussi avec C

Cette bibliothèque définit un ensemble de compilateurs, d'architectures, de systèmes d'exploitation, de bibliothèques et d'autres numéros de version à partir des informations qu'elle peut rassembler sur les macros prédéfinies C, C++, Objective C et Objective C++ ou celles définies dans les en-têtes généralement disponibles. L'idée de cette bibliothèque est née d'une proposition visant à étendre la bibliothèque Boost Config afin de fournir davantage d'informations cohérentes que les définitions de fonctionnalités qu'elle prend en charge. Ce qui suit est une version révisée de cette brève proposition. 

Par exemple

#include <boost/predef.h>

#if defined(BOOST_OS_WINDOWS)
#Elif defined(BOOST_OS_Android)
#Elif defined(BOOST_OS_LINUX)
#Elif defined(BOOST_OS_BSD)
...
#endif
0
phuclv

J'ai écrit une petite bibliothèque pour obtenir le système d'exploitation utilisé. Il peut être installé à l'aide de clib (le gestionnaire de paquets C), il est donc très simple de l'utiliser comme dépendance pour vos projets.

Installer

$ clib install abranhe/os.c

Usage

#include <stdio.h>
#include "os.h"

int main()
{
    printf("%s\n", operating_system());
    // macOS
    return 0;
}

Il renvoie une chaîne (char*) avec le nom du système d'exploitation que vous utilisez. Pour plus d'informations sur ce projet, consultez-le la documentation sur Github .

0
Carlos Abraham

Je n'ai pas trouvé Haiku définition ici. Pour être complet, la définition de Haiku-os est simple __HAIKU__

0
TadejP

Vous pouvez utiliser les directives du préprocesseur aswarning ou errorpour vérifier au moment de la compilation que vous n'avez pas besoin de lancer ce programme du tout simplement compiler il .

#if defined(_WIN32) || defined(_WIN64) || defined(__WINDOWS__)
    #error Windows_OS
#Elif defined(__linux__)
    #error Linux_OS
#Elif defined(__Apple__) && defined(__MACH__)
    #error Mach_OS
#Elif defined(unix) || defined(__unix__) || defined(__unix)
    #error Unix_OS
#else
    #error Unknown_OS
#endif

#include <stdio.h>
int main(void)
{
    return 0;
}
0
HaSeeB MiR