¿Cómo verifico el sistema operativo con una directiva de preprocesador?
-
02-07-2019 - |
Pregunta
Necesito mi código para hacer cosas diferentes según el sistema operativo en el que se compila. Estoy buscando algo como esto:
#ifdef OSisWindows
// do Windows-specific stuff
#else
// do Unix-specific stuff
#endif
¿Hay una manera de hacer esto? ¿Hay una mejor manera de hacer lo mismo?
Solución
El sitio Macros predefinidas tiene un Muy completa lista de cheques. Aquí hay algunos de ellos, con enlaces a donde se encuentran:
Windows
_WIN32
& nbsp; & nbsp; & nbsp; Ambos de 32 y 64 bits
_WIN64
& nbsp; & nbsp; & nbsp; solo 64 bits
Unix (Linux, * BSD, Mac OS X)
Consulte esta pregunta relacionada sobre algunos de los inconvenientes del uso de esta comprobación.
unix
__unix
__unix__
Mac OS X
__APPLE__
__MACH__
Ambos están definidos; comprobar si alguno debería funcionar.
Linux
__linux__
linux
Obsoleto (no compatible con POSIX)
__linux
Obsoleto (no cumple con POSIX)
FreeBSD
__FreeBSD__
Otros consejos
muestra que GCC define en Windows:
gcc -dM -E - <NUL:
en Linux:
gcc -dM -E - </dev/null
Macros predefinidas en MinGW:
WIN32 _WIN32 __WIN32 __WIN32__ __MINGW32__ WINNT __WINNT __WINNT__ _X86_ i386 __i386
en UNIXes:
unix __unix__ __unix
Basado en nadeausoftware y Respuesta 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;
}
Probado con GCC y clang en:
- Debian 8
- Windows (MinGW)
- Windows (Cygwin)
En la mayoría de los casos, es mejor verificar si una funcionalidad dada está presente o no. Por ejemplo: si la función pipe ()
existe o no.
#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
Macros predefinidas de Microsoft C / C ++ compiler (MSVC) se pueden encontrar aquí:
https://docs.microsoft.com/en-us / cpp / preprocesador / macros predefinidas
Creo que estás buscando:
_WIN32: definido como 1 cuando el destino de la compilación es ARM de 32 bits, ARM de 64 bits, x86 o x64. De lo contrario, indefinido
_WIN64: definido como 1 cuando el destino de la compilación es ARM de 64 bits o x64. De lo contrario, indefinido.
gcc compiler PreDefined MAcros se puede encontrar aquí:
Creo que estás buscando:
__GNUC__
__GNUC_MINOR__
__GNUC_PATCHLEVEL__
Haga un google para sus compiladores apropiados predefinidos.
No hay una macro estándar que se establezca de acuerdo con el estándar C. Algunos compiladores de C configurarán uno en algunas plataformas (por ejemplo, el GCC parcheado de Apple establece una macro para indicar que se está compilando en un sistema Apple y para la plataforma Darwin). Su plataforma y / o su compilador de C podrían establecer algo también, pero no hay una forma general.
Como dice Hayalci, es mejor tener estas macros en tu proceso de compilación de alguna manera. Es fácil definir una macro con la mayoría de los compiladores sin modificar el código. Simplemente puede pasar -D MACRO
a GCC, es decir,
gcc -D Windows
gcc -D UNIX
Y en tu código:
#if defined(Windows)
// do some cool Windows stuff
#elif defined(UNIX)
// do some cool Unix stuff
#else
# error Unsupported operating system
#endif
En MinGW, la verificación de definición _WIN32
no está funcionando. Aquí hay una solución:
#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
Para obtener más información, consulte: https://sourceforge.net/p/predef/ wiki / OperatingSystems /
Utilice #define OSsymbol
y #ifdef OSsymbol
donde OSsymbol es un símbolo capaz de #define
identificando su sistema operativo de destino.
Normalmente, incluiría un archivo de encabezado central que define el símbolo del sistema operativo seleccionado y usaría los directorios de biblioteca y inclusión específicos del sistema operativo para compilar y construir.
No ha especificado su entorno de desarrollo, pero estoy bastante seguro de que su compilador proporciona definiciones globales para plataformas y sistemas operativos comunes.
Consulte también http://en.wikibooks.org/wiki/C_Programming/Preprocessor
Para resumir, aquí hay un montón de enlaces útiles.
- Gros comunes predefinidos GCC
- Sistemas operativos predefinidos de SourceForge
- Macros predefinidas de MSDN
- La página de software Naudea muy vinculada
- Wikipedia !!!
- Visión general de SourceForge de macros de compilación predefinidas para estándares, compiladores, sistemas operativos y arquitecturas de hardware . "
- FreeBSD " Differentiating Operating Systems "
- Todo tipo de macros predefinidas
-
libportable
Lo siento por la referencia externa, pero creo que se adapta a su pregunta:
Algunos compiladores generarán #defines que pueden ayudarte con esto. Lea la documentación del compilador para determinar cuáles son. MSVC define uno que es __WIN32__
, < a href = "https://gcc.gnu.org/onlinedocs/gcc/Preprocessor-Options.html" rel = "nofollow noreferrer"> GCC tiene algunas que puede ver con touch foo.h; gcc -dM foo.h
Puede usar directivas de preprocesador como advertencia o error para verificar en el momento de la compilación que no necesita ejecutar este programa en absoluto simplemente compila .
#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;
}
No encontré la definición de Haiku aquí. Para completar, la definición de Haiku-os es simple __HAIKU__
Puede usar Boost.Predef
que contiene varias macros predefinidas para la plataforma de destino, incluido el sistema operativo. Sí, el impulso a menudo se piensa como una biblioteca de C ++, pero esta es una cabecera de preprocesador que también funciona con C
Esta biblioteca define un conjunto de compiladores, arquitectura, sistema operativo, biblioteca y otros números de versión a partir de la información que puede recopilar de las macros predefinidas de C, C ++, Objective C y Objective C ++ o aquellas definidas en los encabezados disponibles en general. La idea de esta biblioteca surgió de una propuesta para ampliar la biblioteca de Boost Config para proporcionar más información consistente que las definiciones de características que admite. Lo que sigue es una versión editada de esa breve propuesta.
Por ejemplo
#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
Escribí una pequeña biblioteca para obtener el sistema operativo en el que se encuentra, puede ser se instala usando clib (el gestor de paquetes C), por lo que es realmente sencillo de usar como una dependencia para sus proyectos.
Instalar
$ clib install abranhe/os.c
Uso
#include <stdio.h>
#include "os.h"
int main()
{
printf("%s\n", operating_system());
// macOS
return 0;
}
Devuelve una cadena ( char *
) con el nombre del sistema operativo que está utilizando, para obtener más información sobre este proyecto, consulte la documentación en Github .