Rilevamento del tempo di compilazione dell'architettura della CPU
-
02-07-2019 - |
Domanda
Qual è il modo più affidabile per scoprire l'architettura della CPU durante la compilazione del codice C o C ++? Per quanto posso dire, diversi compilatori hanno il proprio set di definizioni di preprocessore non standard ( _M_X86
in MSVS, __i386__
, __arm__
in GCC , ecc.)
Esiste un modo standard per rilevare l'architettura per la quale sto costruendo? In caso contrario, esiste una fonte per un elenco completo di tali definizioni per vari compilatori, come un'intestazione con tutte le piastre di caldaia #ifdef
s?
Soluzione
Ecco alcune informazioni su Macro di architettura predefinite e altri tipi di pre macro definite.
Questa domanda chiede dove sono definiti nel codice sorgente GCC.
Altri suggerimenti
Non esiste uno standard inter-compilatore, ma ogni compilatore tende ad essere abbastanza coerente. Puoi creare un'intestazione per te che è qualcosa del genere:
#if MSVC
#ifdef _M_X86
#define ARCH_X86
#endif
#endif
#if GCC
#ifdef __i386__
#define ARCH_X86
#endif
#endif
Non ha molto senso un elenco completo, perché ci sono migliaia di compilatori ma solo 3-4 in uso diffuso (Microsoft C ++, GCC, Intel CC, forse TenDRA?). Decidi semplicemente quali compilatori saranno supportati dalla tua applicazione, elenca le loro #define e aggiorna l'intestazione secondo necessità.
Se desideri scaricare tutte le funzionalità disponibili su una particolare piattaforma, puoi eseguire GCC come:
gcc -march=native -dM -E - </dev/null
Dump di macro come #define __SSE3__ 1
, #define __AES__ 1
, ecc.
Se desideri una soluzione di cross-compilatore, utilizza Boost.Predef
che contiene
-
BOOST_ARCH_
per l'architettura di sistema / CPU per cui si sta compilando. -
BOOST_COMP_
per il compilatore in uso. -
BOOST_LANG_
per gli standard linguistici si sta compilando. -
BOOST_LIB_C_
e BOOST_LIB_STD_ per la libreria standard C e C ++ in uso. -
BOOST_OS_
per il sistema operativo che stiamo compilando. -
BOOST_PLAT_
per piattaforme su sistema operativo o compilatori. -
BOOST_ENDIAN_
per endianness della combinazione di sistema operativo e architettura. -
BOOST_HW_
per funzionalità specifiche dell'hardware. -
BOOST_HW_SIMD
per rilevamento SIMD (Single Instruction Multiple Data).
Ad esempio
#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
Puoi scoprire di più su come usarlo qui
Non c'è nulla di standard. Brian Hook ha documentato alcuni di questi nel suo "cablaggio open source portatile", e persino cerca di trasformarli in qualcosa di coerente e utilizzabile (ymmv a riguardo). Vedi l'intestazione posh.h su questo sito:
Nota, il link sopra potrebbe richiedere di inserire un userid / password fasulli a causa di un attacco DOS qualche tempo fa.
Se hai bisogno di un rilevamento approfondito delle funzionalità della CPU, l'approccio migliore è spedire anche un programma CPUID che trasmetta a stdout o alcuni "cpu_config.h". archiviare il set di funzionalità supportate dalla CPU. Quindi integri quel programma con il tuo processo di generazione.