Détection de l'architecture de la CPU lors de la compilation
-
02-07-2019 - |
Question
Quel est le moyen le plus fiable de connaître l'architecture du processeur lors de la compilation de code C ou C ++? Autant que je sache, différents compilateurs ont leur propre ensemble de définitions de préprocesseur non standard ( _M_X86
dans MSVS, __ i386 __
, __ arm __
dans GCC , etc.).
Existe-t-il un moyen standard de détecter l'architecture pour laquelle je construis? Dans le cas contraire, existe-t-il une source pour une liste complète de ces définitions pour différents compilateurs, telle qu'un en-tête avec toutes les références #ifdef
s?
La solution
Voici des informations sur les Macros d'architecture prédéfinies et d'autres types de macros définies.
Cette question demande où ils sont définis dans le code source de GCC.
Autres conseils
Il n'y a pas de standard inter-compilateur, mais chaque compilateur a tendance à être assez cohérent. Vous pouvez créer un en-tête qui ressemble à ceci:
#if MSVC
#ifdef _M_X86
#define ARCH_X86
#endif
#endif
#if GCC
#ifdef __i386__
#define ARCH_X86
#endif
#endif
Il n’ya pas grand intérêt à une liste complète, car il existe des milliers de compilateurs mais seulement 3 ou 4 sont largement utilisés (Microsoft C ++, GCC, Intel CC, peut-être TenDRA?). Il vous suffit de choisir les compilateurs pris en charge par votre application, de répertorier leurs #défines et de mettre à jour votre en-tête si nécessaire.
Si vous souhaitez transférer toutes les fonctionnalités disponibles sur une plate-forme particulière, vous pouvez exécuter GCC comme suit:
gcc -march=native -dM -E - </dev/null
Cela produirait des macros telles que #define __SSE3__ 1
, #define __AES__ 1
, etc.
Si vous souhaitez une solution de compilation croisée, utilisez simplement Boost.Predef
qui contient
-
BOOST_ARCH _
pour l'architecture système / CPU pour laquelle vous compilez. -
BOOST_COMP _
pour le compilateur utilisé. -
BOOST_LANG _
pour les normes de langage sur lesquelles on compile. -
BOOST_LIB_C _
et BOOST_LIB_STD_ pour les bibliothèques standard C et C ++ utilisées. -
BOOST_OS _
pour le système d'exploitation pour lequel nous compilons. -
BOOST_PLAT _
pour les plates-formes situées en haut du système d'exploitation ou les compilateurs. -
BOOST_ENDIAN _
pour la finalité de la combinaison système d'exploitation et architecture. -
BOOST_HW _
pour les fonctionnalités spécifiques au matériel. -
BOOST_HW_SIMD
pour la détection SIMD (données multiples à instruction unique).
Par exemple
#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
Vous pouvez en savoir plus sur son utilisation ici
Il n'y a rien de standard. Brian Hook en a documenté plusieurs dans son "Portable Open Source Harness" et a même essayé de les transformer en quelque chose de cohérent et utilisable (ymmv à ce sujet). Voir l'en-tête posh.h sur ce site:
Remarque, le lien ci-dessus peut vous obliger à saisir un nom d'utilisateur / mot de passe factice en raison d'une attaque DOS il y a quelque temps.
Si vous avez besoin d'une détection fine des caractéristiques de la CPU, la meilleure approche consiste à expédier également un programme CPUID qui sort vers stdout ou un "cpu_config.h". classe l'ensemble des fonctionnalités supportées par la CPU. Ensuite, vous intégrez ce programme à votre processus de construction.