diff --git a/config.tests/arch/arch.cpp b/config.tests/arch/arch.cpp index ed772f70a0..da0fe1c1b7 100644 --- a/config.tests/arch/arch.cpp +++ b/config.tests/arch/arch.cpp @@ -76,7 +76,169 @@ const char msg[] = "==Qt=magic=Qt== Architecture:" #endif ; +extern const char msg2[]; +const char msg2[] = "==Qt=magic=Qt== Sub-architecture:" + // This is the list of features found in GCC or MSVC + // We don't use all of them, but this is ready for future expansion + +// -- x86 -- +#ifdef __3dNOW__ +// 3dNow!, introduced with the AMD K6-2, discontinued after 2010 +" 3dnow" +#endif +#ifdef __3dNOW_A__ +// Athlon +" 3dnow-a" +#endif +#ifdef __ABM__ +// Advanced Bit Manipulation, AMD Barcelona (family 10h) +" abm" +#endif +#ifdef __AES__ +// AES New Instructions, Intel Core-i7 second generation ("Sandy Bridge") +" aes" +#endif +#ifdef __AVX__ +// Advanced Vector Extensions, Intel Core-i7 second generation ("Sandy Bridge") +" avx" +#endif +#ifdef __AVX2__ +// AVX 2, Intel codename "Haswell" +" avx2" +#endif +#ifdef __BMI__ +// Bit Manipulation Instructions 1, Intel codename "Haswell", AMD "Bulldozer 2" +" bmi" +#endif +#ifdef __BMI2__ +// Bit Manipulation Instructions 2, Intel codename "Haswell" +" bmi2" +#endif +#ifdef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_16 +// cmpxchg16b instruction, Intel Pentium 4 64-bit ("Nocona"), AMD Barcelona (family 10h) +// Notably, this instruction is missing on earlier AMD Athlon 64 +" cx16" +#endif +#ifdef __F16C__ +// 16-bit floating point conversion, Intel codename "Ivy Bridge" +" f16c" +#endif +#ifdef __FMA__ +// Fused Multiply-Add with 3 arguments, Intel codename "Haswell", AMD "Bulldozer 2" +// a.k.a. "FMA3" +" fma" +#endif +#ifdef __FMA4__ +// Fused Multiply-Add with 4 arguments, AMD "Bulldozer" +" fma4" +#endif +#ifdef __FSGSBASE__ +// rdfsgsbase, wrfsgsbase, Intel codename "Ivy Bridge" +" fsgsbase" +#endif +#ifdef __LWP__ +// LWP instructions, AMD "Bulldozer" +" lwp" +#endif +#ifdef __LZCNT__ +// Leading-Zero bit count, Intel codename "Haswell" +" lzcnt" +#endif +#ifdef __MMX__ +// Multimedia Extensions, Pentium MMX, AMD K6-2 +" mmx" +#endif +#ifdef __MOVBE__ +// Move Big Endian, Intel Atom & "Haswell" +" movbe" +#endif +#ifdef __NO_SAHF__ +// missing SAHF instruction in 64-bit, up to Intel Pentium 4 64-bit ("Nocona"), AMD Athlon FX +// Note: the macro is not defined, so this will never show up +" no-sahf" +#endif +#ifdef __PCLMUL__ +// (Packed) Carry-less multiplication, Intel Core-i7 second generation ("Sandy Bridge") +" pclmul" +#endif +#ifdef __POPCNT__ +// Population Count (count of set bits), Intel Core-i7 second generation ("Sandy Bridge") +" popcnt" +#endif +#ifdef __RDRND__ +// Random number generator, Intel codename "Ivy Bridge" +" rdrnd" +#endif +#if defined(__SSE__) || (defined(_M_IX86_FP) && _M_IX86_FP >= 1) || defined(_M_X64) +// Streaming SIMD Extensions, Intel Pentium III, AMD Athlon +" sse" +#endif +#if defined(__SSE2__) || (defined(_M_IX86_FP) && _M_IX86_FP >= 2) || defined(_M_X64) +// SSE2, Intel Pentium-M, Intel Pentium 4, AMD Opteron and Athlon 64 +" sse2" +#endif +#ifdef __SSE3__ +// SSE3, Intel Pentium 4 "Prescott", AMD Athlon 64 rev E +" sse3" +#endif +#ifdef __SSSE3__ +// Supplemental SSE3, Intel Core 2, AMD "Bulldozer" +" ssse3" +#endif +#ifdef __SSE4A__ +// SSE4a, AMD Barcelona +" sse4a" +#endif +#ifdef __SSE4_1__ +// SSE 4.1, Intel Core-i7 ("Nehalem"), AMD "Bulldozer" +" sse4.1" +#endif +#ifdef __SSE4_2__ +// SSE 4.2, Intel Core-i7 ("Nehalem"), AMD "Bulldozer" +" sse4.2" +// Since no processor supports SSE4.2 without 4.1 and since no Intel processor +// supports SSE4a, define "sse4" to indicate SSE4" +" sse4" +#endif +#ifdef __TBM__ +// TBM, AMD "Bulldozer" +" tbm" +#endif +#ifdef __XOP__ +// XOP, AMD "Bulldozer" +" xop" +#endif + +// -- ARM -- +#ifdef __ARM_NEON__ +" neon" +#endif +#ifdef __IWMMXT__ +" iwmmxt" +#endif + +// -- SPARC -- +#ifdef __VIS__ +" vis" +# if __VIS__ >= 0x200 +" vis2" +# endif +# if __VIS__ >= 0x300 +" vis3" +# endif +#endif + +// -- MIPS -- +// Wikipedia says there are extensions, but GCC installs no headers + +// -- POWER, PowerPC -- +#ifdef __ALTIVEC__ +" altivec" +#endif + ""; + int main() { puts(msg); + puts(msg2); } diff --git a/config.tests/unix/arch.test b/config.tests/unix/arch.test index 2a6e12de56..939b49cea0 100755 --- a/config.tests/unix/arch.test +++ b/config.tests/unix/arch.test @@ -5,6 +5,7 @@ VERBOSE=$2 SRCDIR=$3 OUTDIR=$4 RESULTFILE=$5 +VARPREFIX=$6 # debuggery [ "$VERBOSE" = "yes" ] && echo "Determining architecture... ($*)" @@ -28,14 +29,15 @@ else exit 2 fi -ARCH=`strings - $binary 2>/dev/null | awk -F: '/==Qt=magic=Qt==/ { print $2 }'` || -{ +if strings - $binary 2>/dev/null | \ + awk -F: '/==Qt=magic=Qt== Architecture/ { print "'$VARPREFIX'_ARCH=\"" $2 "\"" } + /==Qt=magic=Qt== Sub-architecture/ { print "'$VARPREFIX'_CPUFEATURES=\"" $2 "\"" }' > "$RESULTFILE" +then + [ "$VERBOSE" = "yes" ] && echo " Found architecture in binary" && \ + cat "$RESULTFILE" +else [ "$VERBOSE" = "yes" ] && echo "Unable to determine architecture!" exit 2 -} +fi $MAKE distclean >/dev/null 2>&1 - -[ "$VERBOSE" = "yes" ] && echo " Found '$ARCH' in binary" - -echo "$ARCH" > $5 diff --git a/configure b/configure index 52413f12fe..c8f615888c 100755 --- a/configure +++ b/configure @@ -708,8 +708,10 @@ CFG_PKGCONFIG=auto # Target architecture CFG_ARCH= +CFG_CPUFEATURES= # Host architecture, same as CFG_ARCH when not cross-compiling CFG_HOST_ARCH= +CFG_HOST_CPUFEATURES= # Set when the -arch or -host-arch arguments are used OPT_OBSOLETE_HOST_ARG=no @@ -3668,9 +3670,9 @@ fi # Use config.tests/arch/arch.pro to has the compiler tell us what the target architecture is OUTFILE=$outpath/arch.result -"$unixtests/arch.test" "$XQMAKESPEC" $OPT_VERBOSE "$relpath" "$outpath" "$OUTFILE" +"$unixtests/arch.test" "$XQMAKESPEC" $OPT_VERBOSE "$relpath" "$outpath" "$OUTFILE" "CFG" if [ $? -eq 0 ]; then - CFG_ARCH=`cat "$OUTFILE"` + eval `cat "$OUTFILE"` else echo echo "Could not determine the target architecture!" @@ -3681,9 +3683,9 @@ rm -f "$OUTFILE" 2>/dev/null if [ "$QMAKESPEC" != "$XQMAKESPEC" ]; then # Do the same test again, using the host compiler - SYSROOT_FLAG= "$unixtests/arch.test" "$QMAKESPEC" $OPT_VERBOSE "$relpath" "$outpath" "$OUTFILE" + SYSROOT_FLAG= "$unixtests/arch.test" "$QMAKESPEC" $OPT_VERBOSE "$relpath" "$outpath" "$OUTFILE" "CFG_HOST" if [ $? -eq 0 ]; then - CFG_HOST_ARCH=`cat "$OUTFILE"` + eval `cat "$OUTFILE"` else echo echo "Could not determine the host architecture!" @@ -3694,6 +3696,7 @@ if [ "$QMAKESPEC" != "$XQMAKESPEC" ]; then else # not cross compiling, host == target CFG_HOST_ARCH="$CFG_ARCH" + CFG_HOST_CPUFEATURES="$CFG_CPUFEATURES" fi unset OUTFILE @@ -5719,6 +5722,8 @@ cat >>"$QTCONFIG.tmp" < > qmakespecs; + QVector qmakespecs; if (dictionary.contains("XQMAKESPEC")) - qmakespecs << qMakePair(QString("XQMAKESPEC"), QString("QT_ARCH")); - qmakespecs << qMakePair(QString("QMAKESPEC"), QString("QT_HOST_ARCH")); + qmakespecs << ArchData("target", "XQMAKESPEC", "QT_ARCH", "QT_CPU_FEATURES"); + qmakespecs << ArchData("host", "QMAKESPEC", "QT_HOST_ARCH", "QT_HOST_CPU_FEATURES"); for (int i = 0; i < qmakespecs.count(); ++i) { - const QPair &pair = qmakespecs.at(i); - QString qmakespec = dictionary.value(pair.first); - QString key = pair.second; + const ArchData &data = qmakespecs.at(i); + QString qmakespec = dictionary.value(data.qmakespec); + QString key = data.key; + QString subarchKey = data.subarchKey; // run qmake QString command = @@ -2584,10 +2596,11 @@ void Configure::detectArch() QByteArray exeContents = exe.readAll(); exe.close(); - static const char magic[] = "==Qt=magic=Qt== Architecture:"; - int magicPos = exeContents.indexOf(magic); + static const char archMagic[] = "==Qt=magic=Qt== Architecture:"; + int magicPos = exeContents.indexOf(archMagic); if (magicPos == -1) { - cout << "Internal error, could not find the architecture of the executable" << endl; + cout << "Internal error, could not find the architecture of the " + << data.type << " executable" << endl; dictionary["DONE"] = "error"; return; } @@ -2595,10 +2608,24 @@ void Configure::detectArch() // the conversion from QByteArray will stop at the ending NUL anyway QString arch = QString::fromLatin1(exeContents.constData() + magicPos - + sizeof(magic) - 1); + + sizeof(archMagic) - 1); dictionary[key] = arch; + static const char subarchMagic[] = "==Qt=magic=Qt== Sub-architecture:"; + magicPos = exeContents.indexOf(subarchMagic); + if (magicPos == -1) { + cout << "Internal error, could not find the sub-architecture of the " + << data.type << " executable" << endl; + dictionary["DONE"] = "error"; + return; + } + + QString subarch = QString::fromLatin1(exeContents.constData() + magicPos + + sizeof(subarchMagic) - 1); + dictionary[subarchKey] = subarch; + //cout << "Detected arch '" << qPrintable(arch) << "'\n"; + //cout << "Detected sub-arch '" << qPrintable(subarch) << "'\n"; // clean up Environment::execute(command + " distclean"); @@ -2606,8 +2633,10 @@ void Configure::detectArch() if (!dictionary.contains("QT_HOST_ARCH")) dictionary["QT_HOST_ARCH"] = "unknown"; - if (!dictionary.contains("QT_ARCH")) + if (!dictionary.contains("QT_ARCH")) { dictionary["QT_ARCH"] = dictionary["QT_HOST_ARCH"]; + dictionary["QT_CPU_FEATURES"] = dictionary["QT_HOST_CPU_FEATURES"]; + } QDir::setCurrent(oldpwd); } @@ -2650,6 +2679,8 @@ void Configure::generateQConfigPri() configStream << endl; configStream << "QT_ARCH = " << dictionary["QT_ARCH"] << endl; configStream << "QT_HOST_ARCH = " << dictionary["QT_HOST_ARCH"] << endl; + configStream << "QT_CPU_FEATURES = " << dictionary["QT_CPU_FEATURES"] << endl; + configStream << "QT_HOST_CPU_FEATURES = " << dictionary["QT_HOST_CPU_FEATURES"] << endl; if (dictionary["QT_EDITION"].contains("OPENSOURCE")) configStream << "QT_EDITION = " << QLatin1String("OpenSource") << endl; else @@ -3037,8 +3068,10 @@ void Configure::displayConfig() sout << "QMAKESPEC..................." << dictionary[ "XQMAKESPEC" ] << " (" << dictionary["QMAKESPEC_FROM"] << ")" << endl; else sout << "QMAKESPEC..................." << dictionary[ "QMAKESPEC" ] << " (" << dictionary["QMAKESPEC_FROM"] << ")" << endl; - sout << "Architecture................" << dictionary["QT_ARCH"] << endl; - sout << "Host Architecture..........." << dictionary["QT_HOST_ARCH"] << endl; + sout << "Architecture................" << dictionary["QT_ARCH"] + << ", features:" << dictionary["QT_CPU_FEATURES"] << endl; + sout << "Host Architecture..........." << dictionary["QT_HOST_ARCH"] + << ", features:" << dictionary["QT_HOST_CPU_FEATURES"] << endl; sout << "Maketool...................." << dictionary[ "MAKE" ] << endl; sout << "Debug symbols..............." << (dictionary[ "BUILD" ] == "debug" ? "yes" : "no") << endl; sout << "Link Time Code Generation..." << dictionary[ "LTCG" ] << endl;