Як визначити платформу / компілятор з препроцесорних макросів?


115

Я пишу код крос-платформи, який слід компілювати в Linux, Windows, Mac OS. У вікнах я повинен підтримувати візуальну студію та mingw.

Є деякі фрагменти коду, що залежить від платформи, який я повинен розмістити в #ifdef .. #endifоточенні. Наприклад, тут я розмістив специфічний код win32:

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

Але як розпізнати linux та mac OS? Що визначає імена (або тощо), які я повинен використовувати?



У дупі є набагато краще прийнята відповідь.
rubenvb

1
Пропонований дублікат НЕ є тим самим питанням. Це питання задається лише питанням ідентифікації операційної системи, тоді як це питання також задає ідентифікацію компілятора, що зовсім інша річ.
JBentley

@JBentley, але прийнята відповідь навіть не згадує компіляторів, а говорить лише про ОС (і одну "платформу"). Не кажучи вже про страшну відповідь щодо того, що може запропонувати дуп.
rubenvb

1
@rubenvb Потім зв’яжіть інше питання як коментар. Тільки тому, що він має кращу відповідь, не робить його дублікатом. Питання полягає в тому, що визначає, чи це дублікат, а не відповіді. Закриття цього лише гарантує, що ми ніколи не отримаємо якісної відповіді на частину питання, що стосується компілятора, на який так званий «дублікат» ніколи не може відповісти.
JBentley

Відповіді:


133

Для Mac OS :

#ifdef __APPLE__

Для MingW в Windows:

#ifdef __MINGW32__

Для Linux :

#ifdef __linux__

Для інших компіляторів Windows перевірте цей потік і це для кількох інших компіляторів та архітектур.


2
Чи __APPLE__відрізняє OSX від iOS?
gman

14
__APPLE__встановлюється як для OS X, так і для iOS. Ви можете #include <TargetConditionals.h>всередину #ifdef __APPLE__, яка потім дає вам TARGET_OS_IPHONE #define.
Тед Мільчарек

2
__MINGW64__також доступний, коли використовується mingw64
scones

2
Оскільки __MINGW64__посилається, думаю, що _MSC_VERдля Windows / MSVC варто згадати (що також можна використовувати для перевірки версії MSVC).
ideaman42

Вибачте, але ця відповідь є абсолютно невірною для всіх облікових записів і навіть не відповідає на питання.
rubenvb

59

Дивіться: http://predef.sourceforge.net/index.php

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


5
Станом на версію 1.55, Predef тепер включений до бібліотек Boost C ++ .
rvalue

Я знаю, що правила були різними, коли ви публікували це, але мені доведеться попросити вас відредагувати цю публікацію, щоб включити більш релевантні дані. Зараз посилання на дні лише на відповіді сильно не рекомендується, і я хотів би запропонувати вам можливість зберегти цю публікацію до її видалення.
Мік Маккаллум

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

EDIT: Хоча вищезазначене може працювати для основ, не забудьте перевірити, який макрос ви хочете перевірити, переглянувши довідкові сторінки Boost.Predef . Або просто використовувати Boost.Predef безпосередньо.


4
використовуйте __linux __ замість цього, Linux не визначається під час компіляції з GCC з відключеними розширеннями GNU (тобто -std = c ++ 0x)
Ербурет говорить, що відновить Моніку

1
@Erbureth Виправлено, але дійсно слід використовувати predef.sourceforge.net/index.php, як у відповіді з найбільшою оцінкою.
rubenvb

@rubenvb: справді. І в ньому ще занадто мало голосів, я думаю :) ... Я стільки разів звертався до їх сайту.
0xC0000022L

Для послідовності (можливо, трохи педантичної): перші #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

Враховуючи, що це стимул, це рішення працюватиме на різних платформах / ОС та різних компіляторах.
Тревор Бойд Сміт

3
"Я не можу рекомендувати використовувати бібліотеки Boost досить сильно ...." - Я тричі оцінював Boost. Він не може пройти оцінку ... Більшість звітів про помилки пощастило, якщо їх визнали. Відсутність визнання вказує на більш глибокі проблеми в інженерному процесі. Я вважаю, що макроси препроцесора та вбудовані стандартні бібліотеки C ++ є більш безпечним вибором.
jww
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.