Как мне проверить операционную систему с помощью директивы препроцессора?

StackOverflow https://stackoverflow.com/questions/142508

Вопрос

Мне нужно, чтобы мой код выполнял разные действия в зависимости от операционной системы, в которой он компилируется.Я ищу что-то вроде этого:

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

Есть ли способ сделать это?Есть ли лучший способ сделать то же самое?

Это было полезно?

Решение

Тот Самый Предопределенные макросы для операционной системы на сайте есть очень полный список проверок.Вот некоторые из них, со ссылками на то, где их можно найти:

Windows

_WIN32   Как 32-разрядные, так и 64-разрядные
_WIN64   только 64-разрядная версия

Unix (Linux, *BSD, Mac OS X)

Видишь это связанный с этим вопрос о некоторых подводных камнях использования этой проверки.

unix
__unix
__unix__

Mac OS X

__APPLE__
__MACH__

Оба они определены;проверка любого из них должна сработать.

Linux

__linux__
linux Устаревший (не совместимый с POSIX)
__linux Устаревший (не совместимый с POSIX)

FreeBSD

__FreeBSD__

Другие советы

показывать определения GCC в Windows:

gcc -dM -E - <NUL:

в Linux:

gcc -dM -E - </dev/null

Предопределенные макросы в MinGW:

WIN32 _WIN32 __WIN32 __WIN32__ __MINGW32__ WINNT __WINNT __WINNT__ _X86_ i386 __i386

об унификсах:

unix __unix__ __unix

Основанный на программное обеспечение nadeausoftware и Ответ лямбда-феи.

#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;
}

Протестировано с GCC и clang включено:

  • Debian 8
  • Windows (MinGW)
  • Windows (Cygwin)

В большинстве случаев лучше проверить, присутствует ли данная функциональность или нет.Например:если функция pipe() существует или нет.

#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

Предопределенные макросы Microsoft C / C ++ compiler (MSVC) можно найти здесь:

https://docs.microsoft.com/en-us/cpp/preprocessor/predefined-macros

Я думаю, вы ищете:

_WIN32 - определяется как 1, если целью компиляции является 32-разрядная ARM, 64-разрядная ARM, x86 или x64.В противном случае, не определено
_WIN64 - определяется как 1, если целью компиляции является 64-разрядная ARM или x64.В противном случае - не определено.

предопределенные макросы компилятора gcc можно найти здесь:

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

Я думаю, вы ищете:

__GNUC__
__ГНУК_МИНОР__
__GNUC_PATCHLEVEL _GNUC_PATCHLEVEL__

Поищите в Google нужные вам заранее определенные компиляторы.

Не существует стандартного макроса, который был бы настроен в соответствии со стандартом C.Некоторые компиляторы C установят его на некоторых платформах (напримерИсправленный GCC от Apple устанавливает макрос, указывающий на то, что он компилируется в системе Apple и для платформы Darwin).Ваша платформа и / или ваш компилятор C также могут что-то установить, но общего способа не существует.

Как сказал хаялчи, лучше всего каким-то образом настроить эти макросы в вашем процессе сборки.Макрос легко определить в большинстве компиляторов без изменения кода.Вы можете просто пройти мимо -D MACRO в GCC, т.е.

gcc -D Windows
gcc -D UNIX

И в вашем коде:

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

На MinGW, в _WIN32 проверка определения не работает.Вот решение:

#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

Для получения дополнительной информации, пожалуйста, ознакомьтесь: https://sourceforge.net/p/predef/wiki/OperatingSystems/

Использование #define OSsymbol и #ifdef OSsymbol где OSSymbol - это #define'способный символ, идентифицирующий вашу целевую операционную систему.

Обычно вы включаете центральный заголовочный файл, определяющий выбранный символ операционной системы, и используете для компиляции и сборки каталоги include и library, относящиеся к конкретной операционной системе.

Вы не указали свою среду разработки, но я почти уверен, что ваш компилятор предоставляет глобальные определения для распространенных платформ и операционных систем.

Смотрите также http://en.wikibooks.org/wiki/C_Programming/Preprocessor

Извините за внешнюю ссылку, но я думаю, что она подходит к вашему вопросу:

Совет по C /C ++:Как определить тип операционной системы с помощью предопределенных компилятором макросов

Некоторые компиляторы генерируют #defines, которые могут помочь вам в этом.Прочтите документацию к компилятору, чтобы определить, что это такое. MSVC определяет тот, который __WIN32__, ССАГПЗ есть некоторые, которые вы можете увидеть с помощью touch foo.h; gcc -dM foo.h

Вы можете использовать директивы препроцессора как предупреждение или ошибка чтобы проверить во время компиляции, вам не нужно бежать эта программа вообще всего лишь скомпилировать IT.

#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;
}

Я не нашел Хайку определение здесь.Для полноты картины определение Haiku-os простое __HAIKU__

Вы можете использовать Boost.Predef который содержит различные предопределенные макросы для целевой платформы, включая операционную систему.Да, boost часто рассматривается как библиотека C ++, но это заголовок препроцессора, который также работает с C

Эта библиотека определяет набор номеров компилятора, архитектуры, операционной системы, библиотеки и других версий на основе информации, которую она может собрать о предопределенных макросах C, C ++, Objective C и Objective C ++ или тех, которые определены в общедоступных заголовках.Идея создания этой библиотеки возникла из предложения расширить библиотеку Boost Config, чтобы предоставлять больше согласованной информации, чем определения функций, которые она поддерживает.Ниже приводится отредактированная версия этого краткого предложения.

Например

#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

Я написал небольшая библиотека чтобы получить операционную систему, на которой вы работаете, ее можно установить с помощью клиб (Менеджер пакетов C), так что использовать его в качестве зависимости для ваших проектов действительно просто.

Установить

$ clib install abranhe/os.c

Использование

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

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

Он возвращает строку (char*) с указанием названия операционной системы, которую вы используете, для получения дополнительной информации об этом проекте ознакомьтесь с ним документация на Github.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top