Как определить платформу / компилятор из макросов препроцессора?

115

Я пишу кросс-платформенный код, который должен компилироваться в Linux, Windows, Mac OS. В Windows я должен поддерживать Visual Studio и Mingw.

Есть некоторые фрагменты кода для конкретной платформы, которые я должен поместить в #ifdef .. #endifсреду. Например, здесь я разместил специальный код для Win32:

#ifdef WIN32
#include <windows.h>
#endif

Но как распознать Linux и Mac OS? Какие имена определений (или т. Д.) Я должен использовать?

Arenim
источник
У этого обманщика есть гораздо лучший ответ.
rubenvb
1
Предлагаемый дубликат - это НЕ тот же вопрос. Этот вопрос касается только идентификации операционной системы, тогда как этот вопрос также касается идентификации компилятора, а это совсем другое дело.
JBentley
@JBentley, но в принятом ответе даже не упоминаются компиляторы, а говорится только об ОС (и одной «платформе»). Не говоря уже о том, что это ужасный ответ по сравнению с тем, что может предложить обманщик.
rubenvb
1
@rubenvb Тогда свяжите другой вопрос в качестве комментария. Тот факт, что у него есть лучший ответ, не делает его дубликатом. Вопрос в том, что определяет, является ли это дубликатом, а не ответы. Закрытие этого только гарантирует, что мы никогда не получим качественный ответ на ту часть вопроса, которая связана с компилятором, на которую так называемый «дубликат» никогда не сможет ответить.
JBentley

Ответы:

133

Для Mac OS :

#ifdef __APPLE__

Для MingW в Windows:

#ifdef __MINGW32__

Для Linux :

#ifdef __linux__

Для других компиляторов для Windows, проверьте эту тему и это для нескольких других компиляторов и архитектуры.

karlphillip
источник
2
Есть ли __APPLE__разница между OSX и iOS?
gman
14
__APPLE__установлен как для OS X, так и для iOS. Вы можете #include <TargetConditionals.h>внутри #ifdef __APPLE__, что затем дает вам TARGET_OS_IPHONE #define.
Ted Mielczarek
2
__MINGW64__также доступно при использовании mingw64
scones
2
Поскольку __MINGW64__упоминается, подумайте _MSC_VERо Windows / MSVC (который также можно использовать для проверки версии MSVC).
ideaman42 04
Извините, но этот ответ неверен для всех аккаунтов и даже не отвечает на вопрос.
rubenvb
59

См. Http://predef.sourceforge.net/index.php

Этот проект предоставляет достаточно полный список предварительно определенных #definesдля многих операционных систем, компиляторов, стандартов языка и платформы, а также стандартных библиотек.

Иоанн Варфоломей
источник
5
Начиная с версии 1.55 Predef теперь включен в библиотеки Boost C ++ .
rvalue
Я знаю, что правила были другими, когда вы это разместили, но мне придется попросить вас отредактировать этот пост, чтобы включить в него более важные детали. Теперь категорически не рекомендуется отвечать только на дневные ссылки, и я хотел бы предложить вам возможность сохранить этот пост перед его удалением.
Mick MacCallum
1
Поскольку это единственный ответ, который на самом деле отвечает на вопрос, указанный в заголовке, и вопрос очень общий и актуальный, я настоятельно рекомендую не удалять его. Я бы тоже не назвал это ответом "только ссылка".
hobb
2
@ 0x7fffffff: Какую возможную выгоду для кого-либо было бы в дублировании содержания других ответов в этот? Если вы считаете, что действительно важно получить единый окончательный ответ, то, возможно, вам следует создать такой ответ самостоятельно (это не должно быть сложно: просто склейте существующие ответы в некотором разумном порядке). Лично у меня есть дела поважнее, но, как модератор, очевидно, что ТАК важнее для вас, чем для меня.
Джон Варфоломей
47

Вот что я использую:

#ifdef _WIN32 // note the underscore: without it, it's not msdn official!
    // Windows (x64 and x86)
#elif __unix__ // all unices, not all compilers
    // Unix
#elif __linux__
    // linux
#elif __APPLE__
    // Mac OS, not sure if this is covered by __posix__ and/or __unix__ though...
#endif

РЕДАКТИРОВАТЬ: Хотя приведенное выше может работать для основ, не забудьте проверить, какой макрос вы хотите проверить, просмотрев справочные страницы Boost.Predef . Или просто используйте Boost.Predef напрямую.

rubenvb
источник
4
используйте вместо этого __linux __, linux не определяется при компиляции с GCC с отключенными расширениями GNU (т.е. -std = c ++ 0x)
Эрбурет говорит: «Восстановите Монику»
1
@Erbureth Исправлено, но на самом деле следует использовать Pref.sourceforge.net/index.php в качестве ответа с наивысшим рейтингом.
rubenvb 01
@rubenvb: действительно. И я думаю, что за него еще слишком мало голосов :) ... Я много раз заходил на их сайт.
0xC0000022L 05
Для последовательности (возможно, немного педантично): первые #ifспрашивают, определено ли, другие проверяют ценность. #elif defined(__unix__) Я думаю, если бы было более последовательным и т. Д.
leonbloy
20

Если вы пишете на C ++, я не могу рекомендовать достаточно сильно использовать библиотеки Boost .

Последняя версия (1.55) включает новую библиотеку Predef, которая охватывает именно то, что вы ищете , а также десятки других макросов распознавания платформ и архитектуры.

#include <boost/predef.h>

// ...

#if BOOST_OS_WINDOWS

#elif BOOST_OS_LINUX

#elif BOOST_OS_MACOS

#endif
Rvalue
источник
Учитывая, что это ускорение, это решение будет работать на разных платформах / ОС И разных компиляторах.
Trevor Boyd Smith
3
«Я не могу рекомендовать использовать библиотеки Boost достаточно сильно…» - я оценил Boost трижды. Он не может пройти оценку ... Большинство отчетов об ошибках были удачными, если они были подтверждены. Отсутствие подтверждения указывает на более глубокие проблемы в процессе разработки. Я считаю, что макросы препроцессора и встроенные стандартные библиотеки C ++ являются более безопасным выбором.
jww