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

208

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?

perimosocordiae
la source
1
duplication possible de la compilation C ++ sous Windows et Linux: commutateur ifdef
Cory Klein
9
@Cory Klein: Non-non. cette question a été posée des années auparavant
John_West
Il s'agit de Cne pasC++
ilgaar
@CoryKlein Non, cette question est une copie de cette question.
Akib Azmain

Réponses:

313

Le site Macros prédéfinies pour OS a une liste très complète de vérifications. En voici quelques-uns, avec des liens vers où ils se trouvent:

les fenêtres

_WIN32   32 bits et 64 bits
_WIN64   64 bits uniquement

Unix (Linux, * BSD, Mac OS X)

Voir cette question connexe 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; vérifier l'un ou l'autre devrait fonctionner.

Linux

__linux__
linux Obsolète (non conforme POSIX)
__linuxObsolète (non conforme POSIX)

FreeBSD

__FreeBSD__

Android

__ANDROID__

Fée Lambda
la source
1
Ce site fourni n'inclut pas iOS, il ne parvient donc pas à faire la distinction entre iOS et OS X.
Gary Makin
2
Mac OS ne définit pas __unix__. Pourquoi l'incluriez-vous dans la liste?
Victor Sergienko
1
cpp -dM / dev / null vous donnera une liste de toutes les macros prédéfinies gcc sur votre version de gcc installé
katta
1
Cygwin définit les unixsymboles et ne définit pas win32ceux, donc soyez prudent. OTOH, il définit __CYGWIN__.
David donné le
est le __linux__même que __ANDROID__??
noone
73

show GCC définit sur 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
qwer
la source
1
Windows et Unices ne sont pas les seuls systèmes d'exploitation
phuclv
39

Basé sur nadeausoftware et la 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
const 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 retentit sur:

  • Debian 8
  • Windows (MinGW)
  • Windows (Cygwin)
PADYMKO
la source
le cher @MD XF, veuillez indiquer les versions de votre Windows, MinGW et Cygwin
PADYMKO
Windows 7 Entreprise 6.1.7601. Cygwin 2.7.0-1. Je ne trouve pas la version MinGW mais je l'ai téléchargée hier.
MD XF
Vous devriez probablement être averti cependant - ce programme est standard C, il devrait donc fonctionner sur tous les systèmes conformes.
MD XF
cher @MD XF, merci pour ces informations. Je vous ai ajouté comme contributeur en plus de cette réponse.
PADYMKO
10

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.

quinmars
la source
3
existe-t-il un moyen simple de vérifier si une fonction est définie?
hayalci le
1
Si vous utilisez autoconfig, vous pouvez vérifier les fonctions avec AC_CHECK_FUNCS (). AC_CHECK_FUNCS (pipe sqrt) définira HAVE_PIPE et HAVE_SQRT si les fonctions sont disponibles. Je ne sais pas comment c'est avec d'autres outils de construction, mais je suppose qu'ils le supportent également d'une certaine manière.
quinmars
@MDXF À partir de C ++ 17, il existe __has_include. Je ne pense pas que ce soit encore standardisé en C, mais tous les principaux compilateurs (GCC, Clang, ICC, MSVC) l'implémentent comme une extension spécifique au fournisseur, même en mode C.
Alcaro
7
#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
Arjun Sreedharan
la source
7

Les macros prédéfinies du compilateur Microsoft C / C ++ (MSVC) peuvent être trouvées ici

Je pense que vous recherchez:

  • _WIN32- Défini comme 1 lorsque la cible de compilation est ARM 32 bits, ARM 64 bits, x86 ou x64. Sinon, indéfini
  • _WIN64- Défini comme 1 lorsque la cible de compilation est ARM 64 bits ou x64. Sinon, indéfini.

Les MAcros prédéfinis du compilateur gcc peuvent être trouvés ici

Je pense que vous recherchez:

  • __GNUC__
  • __GNUC_MINOR__
  • __GNUC_PATCHLEVEL__

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

Martin York
la source
4

Il n'y a pas de macro standard définie selon la norme C. Certains compilateurs C en définiront un sur certaines plates-formes (par exemple, le GCC corrigé 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 l'a 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'est-à-dire

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
Mecki
la source
4

Sur MinGW, la _WIN32vérification de définition 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/

anakod
la source
3
Excellent lien. ---
MD XF
2

Utilisez #define OSsymbolet #ifdef OSsymbol où OSsymbol est un #definesymbole capable identifiant votre OS cible.

En règle générale, vous incluez un fichier d'en-tête central définissant le symbole du système d'exploitation sélectionné et utilisez des répertoires d'inclusion et de bibliothèque spécifiques au système d'exploitation pour compiler et construire.

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

devio
la source
2

Pour résumer le tout, voici un tas de liens utiles.

MD XF
la source
2

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

Cette bibliothèque définit un ensemble de compilateurs, d'architecture, de système d'exploitation, de bibliothèque 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 d'étendre la bibliothèque Boost Config pour fournir plus d'informations et plus cohérentes que les définitions de fonctionnalités qu'elle prend en charge. Ce qui suit est une version modifié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)
#elif defined(BOOST_OS_AIX)
#elif defined(BOOST_OS_HAIKU)
...
#endif

La liste complète se trouve dans BOOST_OSles macros du système d'exploitation

Voir aussi Comment obtenir des identifiants de plateforme à partir de boost

phuclv
la source
1

Je n'ai pas trouvé de définition de Haiku ici. Pour être complète, la définition Haiku-os est simple__HAIKU__

TadejP
la source
0

Certains compilateurs généreront des #defines qui peuvent vous aider. Lisez la documentation du compilateur pour déterminer ce qu'ils sont. MSVC en définit un qui est __WIN32__, GCC en a que vous pouvez voir avectouch foo.h; gcc -dM foo.h

davenpcj
la source
1
gcc: erreur: option de ligne de commande non reconnue '--show-define' gcc: erreur fatale: pas de compilation des fichiers d'entrée terminée.
Sebi2020
0

Vous pouvez utiliser des directives de pré-processeur comme avertissement ou erreur pour vérifier au moment de la compilation que vous n'avez pas du tout besoin d' exécuter ce programme, il suffit de le compiler .

#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;
}
HaseeB Mir
la source
0

J'ai écrit une petite bibliothèque pour obtenir le système d'exploitation sur lequel vous êtes, elle peut être installée en utilisant clib (le gestionnaire de paquets C), donc c'est vraiment 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 .

abandonner
la source