Какой кроссплатформенный препроцессор определяет?(__WIN32__ или __WIN32 или WIN32)? - PullRequest
37 голосов
/ 07 июня 2010

Я часто вижу __WIN32, WIN32 или __WIN32__.Я предполагаю, что это зависит от используемого препроцессора (либо от Visual Studio, либо от gcc и т. Д.).

Должен ли я теперь проверять сначала OS, а затем используемый компилятор?Мы используем здесь G ++ 4.4.x, Visual Studio 2008 и Xcode (который, я полагаю, снова gcc) и банкомат, который мы используем __WIN32__, __APPLE__ и __LINUX__.

Ответы [ 5 ]

38 голосов
/ 07 октября 2014

Эта статья отвечает на ваш вопрос:

Статья довольно длинная и включает таблицы, которые трудно воспроизвести, но вот суть:

Вы можете обнаружить ОС в стиле Unix с помощью:

#if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__)))
    /* UNIX-style OS. ------------------------------------------- */

#endif

Как только вы узнаете, что это Unix, вы можете узнать, является ли это POSIX и версией POSIX с:

#include <unistd.h>
#if defined(_POSIX_VERSION)
    /* POSIX compliant */
#endif

Вы можете проверить системы BSD с:

#if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__))
#include <sys/param.h>
#if defined(BSD)
    /* BSD (DragonFly BSD, FreeBSD, OpenBSD, NetBSD). ----------- */

#endif
#endif

и Linux с:

#if defined(__linux__)
    /* Linux  */
#endif

и операционные системы Apple с

#if defined(__APPLE__) && defined(__MACH__)
    /* Apple OSX and iOS (Darwin) */
#include <TargetConditionals.h>
#if TARGET_IPHONE_SIMULATOR == 1
    /* iOS in Xcode simulator */
#elif TARGET_OS_IPHONE == 1
    /* iOS on iPhone, iPad, etc. */    
#elif TARGET_OS_MAC == 1
    /* OS X */
#endif
#endif

Windows с Cygwin

#if defined(__CYGWIN__) && !defined(_WIN32)
    /* Cygwin POSIX under Microsoft Windows. */
#endif

И не POSIX Windows с:

#if defined(_WIN64)
    /* Microsoft Windows (64-bit) */
#elif defined(_WIN32)
    /* Microsoft Windows (32-bit) */
#endif

В полной статье перечислены следующие символы и показано, какие системы определяют их и когда: _AIX, __APPLE__, __CYGWIN32__, __CYGWIN__, __DragonFly__, __FreeBSD__, __gnu_linux, hpux, __hpux, linux, __linux, __linux__, __MACH__, __MINGW32__, __MINGW64__, __NetBSD__, __OpenBSD__, _POSIX_IPV6, _POSIX_MAPPED_FILES, _POSIX_SEMAPHORES, _POSIX_THREADS, _POSIX_VERSION, sun, __sun, __SunOS, __sun__, __SVR4, __svr4__, TARGET_IPHONE_SIMULATOR, TARGET_OS_EMBEDDED, TARGET_OS_IPHONE, TARGET_OS_MAC, UNIX, unix, __unix, __unix__, WIN32, _WIN32, __WIN32, __WIN32__, WIN64, _WIN64, __WIN64, __WIN64__, WINNT, __WINNT, __WINNT__.

A связанная статья ( archive.org ссылка ) посвящена обнаружению компиляторов и версий компиляторов. Здесь перечислены следующие символы: __clang__, __GNUC__, __GNUG__, __HP_aCC, __HP_cc, __IBMCPP__, __IBMC__, __ICC, __INTEL_COMPILER, _MSC_VER, __PGI, __SUNPRO_C, __SUNPRO_CC для обнаружения компиляторов и __clang_major__, __clang_minor__, __clang_patchlevel__, __clang_version__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__, __GNUC__, __GNUG__, __HP_aCC, __HP_cc, __IBMCPP__, __IBMC__, __ICC, __INTEL_COMPILER, __INTEL_COMPILER_BUILD_DATE, _MSC_BUILD, _MSC_FULL_VER, _MSC_VER, __PGIC_MINOR__, __PGIC_PATCHLEVEL__, __PGIC__, __SUNPRO_C, __SUNPRO_CC, __VERSION__, __xlC_ver__, __xlC__, __xlc__ для определения версий компилятора.

14 голосов
/ 07 июня 2010

Это зависит от того, что вы пытаетесь сделать. Вы можете проверить компилятор, если ваша программа хочет использовать некоторые специфические функции (например, из цепочки инструментов gcc). Вы можете проверить операционную систему (_WINDOWS, __unix__), если хотите использовать некоторые специфичные для ОС функции (независимо от компилятора - например, CreateProcess в Windows и fork в unix).

Макросы для Visual C

Макросы для gcc

Вы должны проверить документацию каждого компилятора, чтобы иметь возможность обнаруживать различия при компиляции. Я помню, что у цепочки инструментов gnu (gcc) есть некоторые функции в библиотеке C ( libc ), которых нет в других цепочках инструментов (например, в Visual C). Таким образом, если вы хотите использовать эти функции вне товаров, вы должны обнаружить, что используете GCC, поэтому код, который вы должны использовать, будет следующим:

#ifdef __GNUC__
// do my gcc specific stuff
#else
// ... handle this for other compilers
#endif
3 голосов
/ 07 июня 2010

Не понимаю, почему ты должен. Возможно, вам не придется указывать определение вручную в командной строке вашего компилятора, но это все. Для записи, определение Visual Studio _WIN32 (с одним подчеркиванием), а не __WIN32. Если это не определено, то это не определено, и это не будет иметь значения.

2 голосов
/ 07 июня 2010

Я перестроил свой ответ ... Черт, редактирую берсерк: P:

Вам не нужно использовать частичное. И, вероятно, для MacOSX, Linux и других Unix-подобных приложений вам вообще не нужно их использовать.

Самый популярный (насколько Google говорит правду) - _WIN32.

Вы никогда определяете это "вручную" в вашем исходном коде. Это определяется одним из следующих способов:
как флаг препроцессора / компилятора командной строки (например, g++ -D _WIN32)
или это предопределено самим компилятором (большинство компиляторов Windows предопределяют _WIN32, а иногда и другие, такие как WIN32 или &#95;WIN32&#95;. - Тогда вам вообще не нужно беспокоиться об его определении, компилятор делает все работа.


И мой старый ответ:

Вам не нужно ничего делать. Это просто для мультиплатформенности. Часто версия кода для всех Unix-подобных (включая Linux, MacOSX, BSD, Solaris ...) и других платформ POSIX будет полностью одинаковой, и для Windows должны быть внесены некоторые изменения. Таким образом, люди пишут свой код, как правило, для Unix-лайков и помещают некоторые части, предназначенные только для Windows (например, инструкции DirectX, пути к файлам, подобные Windows), между #ifdef _WIN32 и #endif.

Если у вас есть детали, например. Только для системы X-Window или только для MacOS вы делаете нечто подобное с #ifdef X_WINDOW или #ifdef MACOS. Затем вам нужно установить правильное определение препроцессора во время компиляции (с gcc, использующим флаг -D, например, gcc -D _WIN32).

Если вы не пишете код, зависящий от платформы, вам не нужно заботиться о таких #ifdef, #else, #endif блоках. И большинство компиляторов / препроцессоров Windows AFAIK имеют предопределенные символы, такие как _WIN32 (наиболее популярные, насколько Google говорит правду), WIN32, &#95;WIN32&#95; и т. Д. Так что компилировать их в Windows, скорее всего, нет. нужно сделать что-то еще, кроме простой компиляции.

0 голосов
/ 07 июня 2010

Вздох - не полагайтесь на компилятор - укажите, для какой платформы вы строите свой Makefile.Проще говоря, все, что начинается с _, зависит от реализации и не является переносимым.

Я однажды попробовал ваш метод в очень большом проекте, и между перерывами между Sun-C ++ и GCC мы просто решили использовать контроль Makefile, а не пытаться определить, что собираются компиляторысделать.

...