Как мне проверить операционную систему с помощью директивы препроцессора?
-
02-07-2019 - |
Вопрос
Мне нужно, чтобы мой код выполнял разные действия в зависимости от операционной системы, в которой он компилируется.Я ищу что-то вроде этого:
#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 можно найти здесь:
Я думаю, вы ищете:
__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
Просто чтобы подвести итог всему этому, вот несколько полезных ссылок.
- Общие предопределенные макросы GCC
- Предопределенные Операционные системы SourceForge
- Предопределенные макросы MSDN
- Страница NaudeaSoftware, на которую Много ссылок
- Википедия!!!
- SourceForge "Обзор предопределенных макросов компилятора для стандартов, компиляторов, операционных систем и аппаратных архитектур".
- "Отличительные операционные системы FreeBSD"
- Все виды предопределенных макросов
libportable
Извините за внешнюю ссылку, но я думаю, что она подходит к вашему вопросу:
Вы можете использовать директивы препроцессора как предупреждение или ошибка чтобы проверить во время компиляции, вам не нужно бежать эта программа вообще всего лишь скомпилировать 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.