¿Cómo verifico el sistema operativo con una directiva de preprocesador?

195

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 alguna forma de hacer esto? ¿Hay una mejor manera de hacer lo mismo?

perimosocordiae
fuente
1
posible duplicado de compilación
Cory Klein
8
@Cory Klein: No, no. esta pregunta se ha hecho años antes
John_West
Esto se trata de CnoC++
ilgaar

Respuestas:

290

El sitio Predefined Macros for OS tiene una lista muy completa de comprobaciones. Aquí hay algunos de ellos, con enlaces a donde se encuentran:

Ventanas

_WIN32   Tanto de 32 bits como de 64 bits
_WIN64    64 bits solamente

Unix (Linux, * BSD, Mac OS X)

Vea esta pregunta relacionada sobre algunas de las trampas del uso de esta verificación.

unix
__unix
__unix__

Mac OS X

__APPLE__
__MACH__

Ambos están definidos; la comprobación de cualquiera de los dos debería funcionar.

Linux

__linux__
linux Obsoleto (no compatible con POSIX)
__linuxObsoleto (no compatible con POSIX)

FreeBSD

__FreeBSD__

Androide

__ANDROID__

Hada lambda
fuente
1
Este sitio no incluye iOS, por lo que no puede distinguir entre iOS y OS X.
Gary Makin
2
Mac OS no define __unix__. ¿Por qué lo incluirías en la lista?
Victor Sergienko
1
CPP -dM / dev / null le dará una lista de todos los macro predefinida del gcc en su versión de gcc instalado
Katta
1
Cygwin define los unixsímbolos y no los define win32, así que tenga cuidado. OTOH lo define __CYGWIN__.
David dado el
es __linux__igual que __ANDROID__??
nadie el
72

show 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 UNIX:

unix __unix__ __unix
qwer
fuente
1
Windows y Unices no son los únicos sistemas operativos
phuclv
35

Basado en nadeausoftware y la 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
const 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)
PADYMKO
fuente
el querido @MD XF, indique las versiones de Windows, MinGW y Cygwin
PADYMKO
Windows 7 Enterprise 6.1.7601. Cygwin 2.7.0-1. No puedo encontrar la versión de MinGW pero la descargué ayer.
MD XF
Sin embargo, probablemente debería tenerlo en cuenta: este programa es estándar C, por lo que debería funcionar en todos los sistemas compatibles.
MD XF
querida @ MD XF, gracias por esta información. Te agregué como colaborador en la parte superior de esta respuesta.
PADYMKO
10

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.

quinmars
fuente
3
¿Hay una manera fácil de verificar si una función está definida?
hayalci
1
Si está utilizando la configuración automática, puede verificar las funciones con AC_CHECK_FUNCS (). AC_CHECK_FUNCS (pipe sqrt) definirá HAVE_PIPE y HAVE_SQRT si las funciones están disponibles. No sé cómo es con otras herramientas de construcción, pero supongo que también lo admiten de alguna manera.
quinmars
@MDXF A partir de C ++ 17, hay __has_include. Todavía no creo que esté estandarizado en C, pero todos los compiladores principales (GCC, Clang, ICC, MSVC) lo implementan como una extensión específica del proveedor, incluso en modo 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
fuente
5

Las macros predefinidas del compilador de Microsoft C / C ++ (MSVC) se pueden encontrar aquí

Creo que estás buscando:

  • _WIN32- Definido como 1 cuando el objetivo 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 objetivo de la compilación es ARM de 64 bits o x64. De lo contrario, indefinido.

compilador gcc Predefined MAcros se puede encontrar aquí

Creo que estás buscando:

  • __GNUC__
  • __GNUC_MINOR__
  • __GNUC_PATCHLEVEL__

Haga un google para sus compiladores apropiados predefinidos.

Martin York
fuente
4

No hay una macro estándar establecida de acuerdo con el estándar C. Algunos compiladores de C establecerá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 también pueden establecer algo, pero no hay una forma general.

Como dijo hayalci, es mejor tener estas macros configuradas de alguna manera en su proceso de construcción. Es fácil definir una macro con la mayoría de los compiladores sin modificar el código. Simplemente puede pasar -D MACROa 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
Mecki
fuente
4

En MinGW, la _WIN32verificación de definición no funciona. 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/

anakod
fuente
3
Gran enlace ---
MD XF
2

Use #define OSsymboly #ifdef OSsymbol donde OSsymbol es un #definesímbolo capaz de identificar su sistema operativo objetivo.

Por lo general, incluiría un archivo de encabezado central que define el símbolo del sistema operativo seleccionado y usaría directorios de biblioteca y de inclusión específicos del sistema operativo para compilar y construir.

No especificó su entorno de desarrollo, pero estoy bastante seguro de que su compilador proporciona definiciones globales para plataformas y sistemas operativos comunes.

Ver también http://en.wikibooks.org/wiki/C_Programming/Preprocessor

devio
fuente
2

Para resumirlo todo, aquí hay un montón de enlaces útiles.

MD XF
fuente
2

Puede usar el Boost.Predefque contiene varias macros predefinidas para la plataforma de destino, incluido el sistema operativo ( BOOST_OS_*). Sí, a menudo se considera que boost es una biblioteca de C ++, pero este es un encabezado 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 reunir de macros predefinidas C, C ++, Objective C y Objective C ++ o aquellas definidas en encabezados generalmente disponibles. La idea de esta biblioteca surgió de una propuesta para extender la biblioteca Boost Config para proporcionar más información consistente que las definiciones de funciones 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)
#elif defined(BOOST_OS_AIX)
#elif defined(BOOST_OS_HAIKU)
...
#endif

La lista completa se puede encontrar en BOOST_OSlas macros del sistema operativo

phuclv
fuente
1

No encontré la definición de Haiku aquí. Para completar, la definición de Haiku-os es simple__HAIKU__

TadejP
fuente
0

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__, GCC tiene algunos que puedes ver contouch foo.h; gcc -dM foo.h

davenpcj
fuente
1
gcc: error: opción de línea de comando no reconocida '--show-define' gcc: error fatal: no se finalizó la compilación de archivos de entrada.
Sebi2020
0

Puede usar directivas de preprocesador como advertencia o error para verificar en el momento de la compilación que no necesita ejecutar este programa, simplemente compílelo .

#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
fuente
0

Escribí una pequeña biblioteca para obtener el sistema operativo en el que se encuentra, se puede instalar usando clib (El administrador de paquetes C), por lo que es realmente simple usarlo como una dependencia para sus proyectos.

Instalar en pc

$ 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 .

Abraham Hernández
fuente