Какой препроцессор перекрестной платформы определяет? (__WIN32__ или __WIN32 или WIN32)?

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

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

Ответ 1

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

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

Макросы для gcc

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

#ifdef __GNUC__
// do my gcc specific stuff
#else
// ... handle this for other compilers
#endif

Ответ 2

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

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

Вы можете обнаружить ОС 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__ для обнаружения версий компилятора.

Ответ 3

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

Ответ 4

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

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

Наиболее популярным является (насколько Google говорит правду) _WIN32.

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


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

Вам не нужно "ничего". Это просто для многоплатформенной совместимости. Часто версия кода для всех 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, _WIN32_ и т.д. Поэтому, компилируя его в Windows, скорее всего, вы не нужно сделать что-то еще, кроме компиляции.

Ответ 5

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

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