Определение архитектуры процессора во время компиляции
Какой самый надежный способ узнать архитектуру процессора при компиляции кода C или C++? Насколько я могу судить, разные компиляторы имеют собственный набор нестандартных определений препроцессора (_M_X86
в MSVS, __i386__
, __arm__
в GCC и т. д.).
Есть ли стандартный способ определения архитектуры, для которой я создаю? Если нет, то есть ли источник для исчерпывающего списка таких определений для различных компиляторов, таких как заголовок со всеми образцами #ifdef
s?
8 ответов
Вот некоторая информация о предопределенных макросах архитектуры и других типах предопределенных макросов.
Этот вопрос спрашивает, где они определены в исходном коде GCC.
Наслаждайтесь, я был оригинальным автором этого.
extern "C" {
char *getBuild() { //Get current architecture, detectx nearly every architecture. Coded by Freak
#if defined(__x86_64__) || defined(_M_X64)
return "x86_64";
#elif defined(i386) || defined(__i386__) || defined(__i386) || defined(_M_IX86)
return "x86_32";
#elif defined(__ARM_ARCH_2__)
return "ARM2";
#elif defined(__ARM_ARCH_3__) || defined(__ARM_ARCH_3M__)
return "ARM3";
#elif defined(__ARM_ARCH_4T__) || defined(__TARGET_ARM_4T)
return "ARM4T";
#elif defined(__ARM_ARCH_5_) || defined(__ARM_ARCH_5E_)
return "ARM5"
#elif defined(__ARM_ARCH_6T2_) || defined(__ARM_ARCH_6T2_)
return "ARM6T2";
#elif defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) || defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6Z__) || defined(__ARM_ARCH_6ZK__)
return "ARM6";
#elif defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7S__)
return "ARM7";
#elif defined(__aarch64__)
return "ARM64";
#elif defined(mips) || defined(__mips__) || defined(__mips)
return "MIPS";
#elif defined(__sh__)
return "SUPERH";
#elif defined(__powerpc) || defined(__powerpc__) || defined(__powerpc64__) || defined(__POWERPC__) || defined(__ppc__) || defined(__ppc64__) || defined(__PPC__) || defined(__PPC64__) || defined(_ARCH_PPC) || defined(_ARCH_PPC64)
return "POWERPC";
#elif defined(__sparc__) || defined(__sparc)
return "SPARC";
#elif defined(__m68k__)
return "M68K";
#else
return "UNKNOWN";
#endif
}
}
Там нет никакого стандарта между компиляторами, но каждый компилятор имеет тенденцию быть достаточно последовательным. Вы можете создать заголовок для себя, что-то вроде этого:
#if MSVC
#ifdef _M_X86
#define ARCH_X86
#endif
#endif
#if GCC
#ifdef __i386__
#define ARCH_X86
#endif
#endif
Нет большого смысла в исчерпывающем списке, потому что есть тысячи компиляторов, но только 3-4 широко используются (Microsoft C++, GCC, Intel CC, может быть, TenDRA?). Просто решите, какие компиляторы будет поддерживать ваше приложение, перечислите их #defines и обновите ваш заголовок по мере необходимости.
Если вы хотите сбросить все доступные функции на конкретной платформе, вы можете запустить GCC следующим образом:
gcc -march=native -dM -E - </dev/null
Было бы свалки Маркоса, как #define __SSE3__ 1
, #define __AES__ 1
, так далее.
Если вы хотите кросс-компиляторное решение, просто используйте Boost.Predef
который содержит
BOOST_ARCH_
для архитектуры системы / процессора компилируется каждый.BOOST_COMP_
для компилятора один использует.BOOST_LANG_
для языковых стандартов составляются против.BOOST_LIB_C_
и BOOST_LIB_STD_ для используемой стандартной библиотеки C и C++.BOOST_OS_
для операционной системы, которую мы компилируем.BOOST_PLAT_
для платформ поверх операционной системы или компиляторов.BOOST_ENDIAN_
для порядка байтов ОС и архитектуры.BOOST_HW_
для аппаратных особенностей.BOOST_HW_SIMD
для обнаружения SIMD (одной команды, нескольких данных).
Например
#if defined(BOOST_ARCH_X86)
#if BOOST_ARCH_X86_64
std::cout << "x86_64 " << BOOST_ARCH_X86_64 << " \n";
#elif BOOST_ARCH_X86_32
std::cout << "x86 " << BOOST_ARCH_X86_32 << " \n";
#endif
#elif defined(BOOST_ARCH_ARM)
#if _M_ARM
std::cout << "ARM " << _M_ARM << " \n";
#elif _M_ARM64
std::cout << "ARM64 " << _M_ARM64 << " \n";
#endif
#endif
Вы можете узнать больше о том, как использовать его здесь
Там нет ничего стандартного. Брайан Хук задокументировал их в своем "Portable Open Source Harness" и даже пытается превратить их во что-то связное и удобное для использования (с другой стороны). Смотрите заголовок posh.h на этом сайте:
Обратите внимание, что приведенная выше ссылка может потребовать от вас ввести некоторые поддельные ИД / пароль из-за атаки DOS некоторое время назад.
Есть список
#define
S здесь. Был предыдущий ответ с высокой оценкой голосов, который включал эту ссылку, но он был удален модом, предположительно из-за правила SO «ответы должны иметь код». Итак, вот случайная выборка. Перейдите по ссылке, чтобы увидеть полный список.
AMD64
Если вам необходимо детальное определение функций ЦП, лучшим подходом является поставка также программы CPUID, которая выводит в стандартный вывод или в некоторый файл "cpu_config.h" набор функций, поддерживаемых ЦП. Затем вы интегрируете эту программу в процесс сборки.