From 1533bfc5fcc4ec5865c1de606504b6aba8a5f6fe Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Tue, 27 Mar 2012 14:43:45 -0300 Subject: Improve the architecture-detection mechanism For the Unix part, this now obeys the -v option, printing the full command-line it used to compile, allowing testers to identify why something went wrong. Unfortunately, it requires a full compilation cycle, instead of just preprocessing. Just one more among the many on Unix, but maybe a noticeable slow-down on Windows. Change-Id: I654b70d99887e04c96731a5b91be9ad555e4d8fe Reviewed-by: Oswald Buddenhagen Reviewed-by: Girish Ramakrishnan --- config.tests/arch/arch.cpp | 52 +++++++++++++++++++--------------------- config.tests/arch/arch.pro | 11 ++++----- config.tests/unix/arch.test | 41 +++++++++++++++++++++++++++++++ configure | 24 ++++++++++++++++--- tools/configure/configureapp.cpp | 47 +++++++++++++++++++++++++++++------- 5 files changed, 130 insertions(+), 45 deletions(-) create mode 100755 config.tests/unix/arch.test diff --git a/config.tests/arch/arch.cpp b/config.tests/arch/arch.cpp index b1ec3d7111..ed772f70a0 100644 --- a/config.tests/arch/arch.cpp +++ b/config.tests/arch/arch.cpp @@ -1,6 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Copyright (C) 2012 Intel Corporation ** Contact: http://www.qt-project.org/ ** ** This file is part of the FOO module of the Qt Toolkit. @@ -39,46 +40,43 @@ ** ****************************************************************************/ -// NOTE: This file is not meant to be compiled, only preprocessed. #define QGLOBAL_H #include "../../src/corelib/global/qprocessordetection.h" -#undef alpha -#undef arm -#undef avr32 -#undef bfin -#undef i386 -#undef x86_64 -#undef ia64 -#undef mips -#undef power -#undef s390 -#undef sh -#undef sparc -#undef unknown +#include + +extern const char msg[]; +const char msg[] = "==Qt=magic=Qt== Architecture:" + #if defined(Q_PROCESSOR_ALPHA) -Architecture: alpha +"alpha" #elif defined(Q_PROCESSOR_ARM) -Architecture: arm +"arm" #elif defined(Q_PROCESSOR_AVR32) -Architecture: avr32 +"avr32" #elif defined(Q_PROCESSOR_BLACKFIN) -Architecture: bfin +"bfin" #elif defined(Q_PROCESSOR_X86_32) -Architecture: i386 +"i386" #elif defined(Q_PROCESSOR_X86_64) -Architecture: x86_64 +"x86_64" #elif defined(Q_PROCESSOR_IA64) -Architecture: ia64 +"ia64" #elif defined(Q_PROCESSOR_MIPS) -Architecture: mips +"mips" #elif defined(Q_PROCESSOR_POWER) -Architecture: power +"power" #elif defined(Q_PROCESSOR_S390) -Architecture: s390 +"s390" #elif defined(Q_PROCESSOR_SH) -Architecture: sh +"sh" #elif defined(Q_PROCESSOR_SPARC) -Architecture: sparc +"sparc" #else -Architecture: unknown +"unknown" #endif + ; + +int main() +{ + puts(msg); +} diff --git a/config.tests/arch/arch.pro b/config.tests/arch/arch.pro index ea85a52b97..c6801264b4 100644 --- a/config.tests/arch/arch.pro +++ b/config.tests/arch/arch.pro @@ -1,7 +1,4 @@ -CONFIG -= qt debug_and_release -# Detect target by preprocessing a file that uses Q_PROCESSOR_* macros from qprocessordetection.h -COMMAND = $$QMAKE_CXX $$QMAKE_CXXFLAGS -E $$PWD/arch.cpp -# system function converts newline in output into spaces -COMPILER_ARCH = $$system($$COMMAND) -# Message back to configure so that it can set QT_ARCH and QT_HOST_ARCH -message($$COMPILER_ARCH) +SOURCES = arch.cpp +CONFIG -= qt dylib release debug_and_release +CONFIG += debug console +mac:CONFIG -= app_bundle diff --git a/config.tests/unix/arch.test b/config.tests/unix/arch.test new file mode 100755 index 0000000000..2a6e12de56 --- /dev/null +++ b/config.tests/unix/arch.test @@ -0,0 +1,41 @@ +#!/bin/sh + +QMKSPEC=$1 +VERBOSE=$2 +SRCDIR=$3 +OUTDIR=$4 +RESULTFILE=$5 + +# debuggery +[ "$VERBOSE" = "yes" ] && echo "Determining architecture... ($*)" + +# build a test program but don't run it +test -d "$OUTDIR/config.tests/arch" || mkdir -p "$OUTDIR/config.tests/arch" +[ -f Makefile ] && $MAKE distclean >/dev/null 2>&1 +"$OUTDIR/bin/qmake" -nocache -spec "$QMKSPEC" "QT_BUILD_TREE=$OUTDIR" "LIBS+=$SYSROOT_FLAG" "QMAKE_CXXFLAGS+=$SYSROOT_FLAG" "$SRCDIR/config.tests/arch/arch.pro" -o "$OUTDIR/config.tests/arch/Makefile" >/dev/null 2>&1 || echo "qmake is broken" >&2 +cd "$OUTDIR/config.tests/arch" + + +ARCH="" +[ "$VERBOSE" = "yes" ] && $MAKE || $MAKE >/dev/null 2>&1 + +if [ -f ./arch.exe ]; then + binary=./arch.exe +elif [ -f ./arch ]; then + binary=./arch +else + [ "$VERBOSE" = "yes" ] && echo "Unable to determine architecture!" + exit 2 +fi + +ARCH=`strings - $binary 2>/dev/null | awk -F: '/==Qt=magic=Qt==/ { print $2 }'` || +{ + [ "$VERBOSE" = "yes" ] && echo "Unable to determine architecture!" + exit 2 +} + +$MAKE distclean >/dev/null 2>&1 + +[ "$VERBOSE" = "yes" ] && echo " Found '$ARCH' in binary" + +echo "$ARCH" > $5 diff --git a/configure b/configure index 7f9ea8a860..52413f12fe 100755 --- a/configure +++ b/configure @@ -3667,17 +3667,35 @@ fi #------------------------------------------------------------------------------- # Use config.tests/arch/arch.pro to has the compiler tell us what the target architecture is -CFG_ARCH=`OUTDIR="$outpath" "$outpath/bin/qmake" -spec "$XQMAKESPEC" -o /dev/null "$relpath/config.tests/arch/arch.pro" 2>&1 | sed -n -e 's,^Project MESSAGE:.*Architecture: \([a-zA-Z0-9_]*\).*,\1,p'` - +OUTFILE=$outpath/arch.result +"$unixtests/arch.test" "$XQMAKESPEC" $OPT_VERBOSE "$relpath" "$outpath" "$OUTFILE" +if [ $? -eq 0 ]; then + CFG_ARCH=`cat "$OUTFILE"` +else + echo + echo "Could not determine the target architecture!" + echo "Turn on verbose messaging (-v) to see the final report." +fi +rm -f "$OUTFILE" 2>/dev/null [ -z "$CFG_ARCH" ] && CFG_ARCH="unknown" + if [ "$QMAKESPEC" != "$XQMAKESPEC" ]; then # Do the same test again, using the host compiler - CFG_HOST_ARCH=`OUTDIR="$outpath" "$outpath/bin/qmake" -spec "$QMAKESPEC" -o /dev/null "$relpath/config.tests/arch/arch.pro" 2>&1 | sed -n -e 's,^Project MESSAGE:.*Architecture: \([a-zA-Z0-9_]*\).*,\1,p'` + SYSROOT_FLAG= "$unixtests/arch.test" "$QMAKESPEC" $OPT_VERBOSE "$relpath" "$outpath" "$OUTFILE" + if [ $? -eq 0 ]; then + CFG_HOST_ARCH=`cat "$OUTFILE"` + else + echo + echo "Could not determine the host architecture!" + echo "Turn on verbose messaging (-v) to see the final report." + fi + rm -f "$OUTFILE" 2>/dev/null [ -z "$CFG_HOST_ARCH" ] && CFG_HOST_ARCH="unknown" else # not cross compiling, host == target CFG_HOST_ARCH="$CFG_ARCH" fi +unset OUTFILE if [ "$OPT_VERBOSE" = "yes" ]; then echo "System architecture: '$CFG_ARCH'" diff --git a/tools/configure/configureapp.cpp b/tools/configure/configureapp.cpp index 050dd6b8e1..1059f0f83b 100644 --- a/tools/configure/configureapp.cpp +++ b/tools/configure/configureapp.cpp @@ -2561,16 +2561,47 @@ void Configure::detectArch() QString qmakespec = dictionary.value(pair.first); QString key = pair.second; + // run qmake QString command = - fixSeparators(QString("%1/bin/qmake.exe -spec %2 %3/config.tests/arch/arch.pro -o %4/Makefile.unused 2>&1") - .arg(buildPath, qmakespec, sourcePath, newpwd)); - QString output = Environment::execute(command); - if (output.isEmpty()) - continue; + fixSeparators(QString("%1/bin/qmake.exe -spec %2 %3/config.tests/arch/arch.pro 2>&1") + .arg(buildPath, qmakespec, sourcePath)); + Environment::execute(command); + + // compile + command = dictionary[ "MAKE" ]; + if (command.contains("nmake")) + command += " /NOLOGO"; + command += " -s"; + Environment::execute(command); + + // find the executable that was generated + QFile exe("arch.exe"); + if (!exe.open(QFile::ReadOnly)) { // no Text, this is binary + cout << "Could not find output file: " << qPrintable(exe.errorString()) << endl; + dictionary["DONE"] = "error"; + return; + } + QByteArray exeContents = exe.readAll(); + exe.close(); + + static const char magic[] = "==Qt=magic=Qt== Architecture:"; + int magicPos = exeContents.indexOf(magic); + if (magicPos == -1) { + cout << "Internal error, could not find the architecture of the executable" << endl; + dictionary["DONE"] = "error"; + return; + } + //cout << "Found magic at offset 0x" << hex << magicPos << endl; + + // the conversion from QByteArray will stop at the ending NUL anyway + QString arch = QString::fromLatin1(exeContents.constData() + magicPos + + sizeof(magic) - 1); + dictionary[key] = arch; + + //cout << "Detected arch '" << qPrintable(arch) << "'\n"; - QRegExp re("Project MESSAGE:.*Architecture: ([a-zA-Z0-9_]*)"); - if (re.indexIn(output) != -1) - dictionary[key] = re.cap(1); + // clean up + Environment::execute(command + " distclean"); } if (!dictionary.contains("QT_HOST_ARCH")) -- cgit v1.2.3