Comment vérifier le système d'exploitation avec une directive de préprocesseur?
-
02-07-2019 - |
Question
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 at-il un moyen de faire cela? Y a-t-il une meilleure façon de faire la même chose?
La solution
Le site Macros prédéfinies pour le système d'exploitation a une liste très complète des contrôles. En voici quelques-unes, avec des liens vers les endroits où elles se trouvent:
Windows
_WIN32
& nbsp; & nbsp; & nbsp; Les deux versions 32 bits et 64 bits
_WIN64
& nbsp; & nbsp; & nbsp; 64 bits uniquement
Unix (Linux, * BSD, Mac OS X)
Consultez cette question connexe sur certains pièges de l'utilisation de cette vérification.
unix
__ unix
__ unix __
Mac OS X
__ APPLE __
__ MACH __
Les deux sont définis; vérifier si cela devrait fonctionner.
Linux
__ linux __
linux
obsolète (non compatible POSIX)
__ linux
obsolète (non compatible POSIX)
FreeBSD
__ FreeBSD __
Autres conseils
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
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
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)
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.
#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
Vous pouvez trouver les macros prédéfinies du compilateur Microsoft C / C ++ (MSVC) ici:
https://docs.microsoft.com/en-us / cpp / preprocessor / predefined-macros
Je pense que vous recherchez:
_WIN32 - Défini sur 1 lorsque la cible de la compilation est ARM 32 bits, ARM 64 bits, x86 ou x64. Sinon, non défini
_WIN64 - Défini à 1 lorsque la cible de la compilation est ARM 64 bits ou x64. Sinon, non défini.
Les compilations gcc du compilateur prédéfini sont disponibles ici:
Je pense que vous recherchez:
__ GNUC__
__GNUC_MINOR__
__GNUC_PATCHLEVEL__
Faites une recherche google pour vos compilateurs appropriés prédéfinis.
Aucune macro standard n'est définie conformément au standard C. Certains compilateurs C en définiront un sur certaines plates-formes (par exemple, le GCC patché d'Apple définit une macro pour indiquer qu'il est en cours de compilation sur un système Apple et pour la plate-forme Darwin). Votre plate-forme et / ou votre compilateur C peuvent définir quelque chose également, mais il n'y a pas de moyen général.
Comme le dit hayalci, il est préférable d’avoir ces macros 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
Sous MinGW, la vérification _WIN32
ne définit 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 / Systèmes d'exploitation /
Utilisez #define OSsymbol
et #ifdef OSsymbol
où OSsymbol est un symbole #define
'identifiant votre système d'exploitation cible.
Généralement, vous incluez un fichier d'en-tête central définissant le symbole du système d'exploitation sélectionné et utilisez les répertoires d'inclusion et de bibliothèque spécifiques au système d'exploitation pour la compilation et la construction.
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/Preprocessor
Pour résumer, voici quelques liens utiles.
- Macros GCC communs prédéfinis
- Systèmes d'exploitation prédéfinis de SourceForge
- Macros prédéfinies MSDN
- La page beaucoup liée du logiciel Naudea
- Wikipedia !!!
- Vue d'ensemble de SourceForge de macros de compilateur prédéfinies pour normes, compilateurs, systèmes d'exploitation et architectures matérielles . "
- Les systèmes d'exploitation de FreeBSD a>
- Toutes sortes de macros prédéfinies
-
libportable
Désolé pour la référence externe, mais je pense que cela convient à votre question:
Certains compilateurs vont générer #defines qui peuvent vous aider. Lisez la documentation du compilateur pour déterminer ce qu’ils sont. MSVC définit celui qui est __ WIN32 __
, < a href = "https://gcc.gnu.org/onlinedocs/gcc/Preprocessor-Options.html" rel = "nofollow noreferrer"> GCC en contient, vous pouvez voir avec touch foo.h; gcc -dM foo.h
Vous pouvez utiliser les directives du pré-processeur comme avertissement ou erreur pour vérifier au moment de la compilation que vous n'avez pas besoin de exécuter ce programme ne fait que simplement compiler ce programme.
#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;
}
Je n'ai pas trouvé la définition de Haiku ici. Pour être complet, la définition de Haiku-os est simple __ HAIKU __
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 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
J'ai écrit une petite bibliothèque pour obtenir le système d'exploitation sur lequel vous vous trouvez, ce 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. / p>
Installer
$ clib install abranhe/os.c
Utilisation
#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 .