diff --git a/src/plugins/projectexplorer/gcctoolchain.cpp b/src/plugins/projectexplorer/gcctoolchain.cpp index 95aca43ab13e87e0703b48ee1401f44ae98b7f57..8e5e8675f88f8c9623d2c5f5764ddcd0e4b0b53c 100644 --- a/src/plugins/projectexplorer/gcctoolchain.cpp +++ b/src/plugins/projectexplorer/gcctoolchain.cpp @@ -273,6 +273,12 @@ static QList<ProjectExplorer::Abi> guessGccAbi(const QString &path, const QStrin return guessGccAbi(machine); } +static QString gccVersion(const QString &path, const QStringList &env) +{ + QStringList arguments(QLatin1String("-dumpversion")); + return QString::fromLocal8Bit(runGcc(path, arguments, env)).trimmed(); +} + // -------------------------------------------------------------------------- // GccToolChain // -------------------------------------------------------------------------- @@ -322,6 +328,13 @@ Abi GccToolChain::targetAbi() const return m_targetAbi; } +QString GccToolChain::version() const +{ + if (m_version.isEmpty()) + m_version = detectVersion(); + return m_version; +} + void GccToolChain::setTargetAbi(const Abi &abi) { if (abi == m_targetAbi) @@ -389,10 +402,30 @@ QString GccToolChain::debuggerCommand() const QString GccToolChain::mkspec() const { Abi abi = targetAbi(); - if (abi.os() == Abi::MacOS) + if (abi.os() == Abi::MacOS) { + QString v = version(); + // prefer versioned g++ on mac. This is required to enable building for older Mac OS versions + if (v.startsWith(QLatin1String("4.0"))) + return QLatin1String("macx-g++40"); + if (v.startsWith(QLatin1String("4.2"))) + return QLatin1String("macx-g++42"); return QLatin1String("macx-g++"); - if (abi.os() == Abi::LinuxOS) + } + + Abi gccAbi = Abi::abisOfBinary(m_compilerPath); + if (gccAbi.architecture() != abi.architecture() + || gccAbi.os() != abi.os() + || gccAbi.osFlavor() != abi.osFlavor()) { + // Note: This can fail:-( + return QString(); // this is a cross-compiler, leave the mkspec alone! + } + if (abi.os() == Abi::LinuxOS) { + if (abi.osFlavor() != Abi::GenericLinuxFlavor) + return QString(); // most likely not a desktop, so leave the mkspec alone. + if (abi.wordWidth() == gccAbi.wordWidth()) + return QLatin1String("linux-g++"); // no need to explicitly set the word width return QLatin1String("linux-g++-") + QString::number(m_targetAbi.wordWidth()); + } if (abi.os() == Abi::BsdOS && abi.osFlavor() == Abi::FreeBsdFlavor) return QLatin1String("freebsd-g++"); return QString(); @@ -507,6 +540,13 @@ QList<Abi> GccToolChain::detectSupportedAbis() const return guessGccAbi(m_compilerPath, env.toStringList()); } +QString GccToolChain::detectVersion() const +{ + Utils::Environment env = Utils::Environment::systemEnvironment(); + addToEnvironment(env); + return gccVersion(m_compilerPath, env.toStringList()); +} + // -------------------------------------------------------------------------- // GccToolChainFactory // -------------------------------------------------------------------------- @@ -734,11 +774,12 @@ QString ClangToolChain::makeCommand() const QString ClangToolChain::mkspec() const { - if (targetAbi().os() == Abi::MacOS) + Abi abi = targetAbi(); + if (abi.os() == Abi::MacOS) return QLatin1String("unsupported/macx-clang"); - else if (targetAbi().os() == Abi::LinuxOS) + else if (abi.os() == Abi::LinuxOS) return QLatin1String("unsupported/linux-clang"); - return QLatin1String("unsupported/win32-clang"); // Note: Not part of Qt yet! + return QString(); // Note: Not supported by Qt yet, so default to the mkspec the Qt was build with } IOutputParser *ClangToolChain::outputParser() const diff --git a/src/plugins/projectexplorer/gcctoolchain.h b/src/plugins/projectexplorer/gcctoolchain.h index 15425cab1843e8e8903b2d69810f1c89fb4344a4..7f596907ef0b3fca19eb66959aeba67cba49e5fd 100644 --- a/src/plugins/projectexplorer/gcctoolchain.h +++ b/src/plugins/projectexplorer/gcctoolchain.h @@ -56,6 +56,7 @@ class PROJECTEXPLORER_EXPORT GccToolChain : public ToolChain public: QString typeName() const; Abi targetAbi() const; + QString version() const; QList<Abi> supportedAbis() const; void setTargetAbi(const Abi &); @@ -91,6 +92,7 @@ protected: void updateId(); virtual QList<Abi> detectSupportedAbis() const; + virtual QString detectVersion() const; mutable QByteArray m_predefinedMacros; @@ -105,6 +107,7 @@ private: Abi m_targetAbi; mutable QList<Abi> m_supportedAbis; mutable QList<HeaderPath> m_headerPathes; + mutable QString m_version; friend class Internal::GccToolChainFactory; friend class ToolChainFactory; diff --git a/src/plugins/qt4projectmanager/qmakestep.cpp b/src/plugins/qt4projectmanager/qmakestep.cpp index 8be1872dfced13f16bf25b1b833d5686811b482d..a4cb600a164d21eed7b624eef68e9f282dcdf196 100644 --- a/src/plugins/qt4projectmanager/qmakestep.cpp +++ b/src/plugins/qt4projectmanager/qmakestep.cpp @@ -146,8 +146,9 @@ QString QMakeStep::allArguments(bool shorted) } } } - if (!userProvidedMkspec) - arguments << "-spec" << mkspec(); + QString specArg = mkspec(); + if (!userProvidedMkspec && !specArg.isEmpty()) + arguments << "-spec" << specArg; // Find out what flags we pass on to qmake arguments << bc->configCommandLineArguments(); @@ -454,12 +455,17 @@ QString QMakeStep::mkspec() } } + QtSupport::BaseQtVersion *version = bc->qtVersion(); + // We do not know which abi the Qt version has, so let's stick with the defaults + if (version && version->qtAbis().count() == 1 && version->qtAbis().first().isNull()) + return QString(); + const QString tcSpec = bc->toolChain() ? bc->toolChain()->mkspec() : QString(); - if (!bc->qtVersion()) + if (!version) return tcSpec; - if (!tcSpec.isEmpty() && bc->qtVersion()->hasMkspec(tcSpec)) + if (!tcSpec.isEmpty() && version->hasMkspec(tcSpec)) return tcSpec; - return bc->qtVersion()->mkspec(); + return version->mkspec(); } QVariantMap QMakeStep::toMap() const diff --git a/src/plugins/qt4projectmanager/qt-desktop/desktopqtversion.cpp b/src/plugins/qt4projectmanager/qt-desktop/desktopqtversion.cpp index 65d5ca9c6a9cfe9711bf0fce1a7ab625c409c04a..28ce0ee07b2d96ff69b4d8e871e43685f965bc04 100644 --- a/src/plugins/qt4projectmanager/qt-desktop/desktopqtversion.cpp +++ b/src/plugins/qt4projectmanager/qt-desktop/desktopqtversion.cpp @@ -44,15 +44,13 @@ using namespace Qt4ProjectManager; using namespace Qt4ProjectManager::Internal; DesktopQtVersion::DesktopQtVersion() - : BaseQtVersion(), - m_qtAbisUpToDate(false) + : BaseQtVersion() { } DesktopQtVersion::DesktopQtVersion(const QString &path, bool isAutodetected, const QString &autodetectionSource) - : BaseQtVersion(path, isAutodetected, autodetectionSource), - m_qtAbisUpToDate(false) + : BaseQtVersion(path, isAutodetected, autodetectionSource) { } @@ -72,38 +70,19 @@ QString DesktopQtVersion::type() const return QtSupport::Constants::DESKTOPQT; } -bool DesktopQtVersion::isValid() const -{ - if (!BaseQtVersion::isValid()) - return false; - if (qtAbis().isEmpty()) - return false; - return true; -} - -QString DesktopQtVersion::invalidReason() const -{ - QString tmp = BaseQtVersion::invalidReason(); - if (tmp.isEmpty() && qtAbis().isEmpty()) - return QCoreApplication::translate("QtVersion", "Failed to detect the ABI(s) used by the Qt version."); - return tmp; -} - QString DesktopQtVersion::warningReason() const { + if (qtAbis().count() == 1 && qtAbis().first().isNull()) + return QCoreApplication::translate("QtVersion", "ABI detection failed: Make sure to use a matching tool chain when building."); if (qtVersion() >= QtSupport::QtVersionNumber(4, 7, 0) && qmlviewerCommand().isEmpty()) return QCoreApplication::translate("QtVersion", "No qmlviewer installed."); return QString(); } -QList<ProjectExplorer::Abi> DesktopQtVersion::qtAbis() const +QList<ProjectExplorer::Abi> DesktopQtVersion::detectQtAbis() const { - if (!m_qtAbisUpToDate) { - m_qtAbisUpToDate = true; - ensureMkSpecParsed(); - m_qtAbis = qtAbisFromLibrary(qtCorePath(versionInfo(), qtVersionString())); - } - return m_qtAbis; + ensureMkSpecParsed(); + return qtAbisFromLibrary(qtCorePath(versionInfo(), qtVersionString())); } bool DesktopQtVersion::supportsTargetId(const QString &id) const diff --git a/src/plugins/qt4projectmanager/qt-desktop/desktopqtversion.h b/src/plugins/qt4projectmanager/qt-desktop/desktopqtversion.h index 44b61807d19e0aebef0e5d73d8a1874da5059780..cae498450ec2da1b11547a816445c44f30f7d1c5 100644 --- a/src/plugins/qt4projectmanager/qt-desktop/desktopqtversion.h +++ b/src/plugins/qt4projectmanager/qt-desktop/desktopqtversion.h @@ -49,20 +49,14 @@ public: QString type() const; - bool isValid() const; - QString invalidReason() const; QString warningReason() const; - QList<ProjectExplorer::Abi> qtAbis() const; + QList<ProjectExplorer::Abi> detectQtAbis() const; bool supportsTargetId(const QString &id) const; QSet<QString> supportedTargetIds() const; QString description() const; - -private: - mutable bool m_qtAbisUpToDate; - mutable QList<ProjectExplorer::Abi> m_qtAbis; }; } diff --git a/src/plugins/qt4projectmanager/qt-desktop/simulatorqtversion.cpp b/src/plugins/qt4projectmanager/qt-desktop/simulatorqtversion.cpp index 947d25f5cf4a3f49f022294f13ac8bc8cc283bca..1ec1c61d8e5529faed9bf3d6d6d907358620eb30 100644 --- a/src/plugins/qt4projectmanager/qt-desktop/simulatorqtversion.cpp +++ b/src/plugins/qt4projectmanager/qt-desktop/simulatorqtversion.cpp @@ -44,15 +44,13 @@ using namespace Qt4ProjectManager; using namespace Qt4ProjectManager::Internal; SimulatorQtVersion::SimulatorQtVersion() - : QtSupport::BaseQtVersion(), - m_qtAbisUpToDate(false) + : QtSupport::BaseQtVersion() { } SimulatorQtVersion::SimulatorQtVersion(const QString &path, bool isAutodetected, const QString &autodetectionSource) - : QtSupport::BaseQtVersion(path, isAutodetected, autodetectionSource), - m_qtAbisUpToDate(false) + : QtSupport::BaseQtVersion(path, isAutodetected, autodetectionSource) { } @@ -72,38 +70,19 @@ QString SimulatorQtVersion::type() const return QtSupport::Constants::SIMULATORQT; } -bool SimulatorQtVersion::isValid() const -{ - if (!BaseQtVersion::isValid()) - return false; - if (qtAbis().isEmpty()) - return false; - return true; -} - -QString SimulatorQtVersion::invalidReason() const -{ - QString tmp = BaseQtVersion::invalidReason(); - if (tmp.isEmpty() && qtAbis().isEmpty()) - return QCoreApplication::translate("QtVersion", "Failed to detect the ABI(s) used by the Qt version."); - return tmp; -} - QString SimulatorQtVersion::warningReason() const { + if (qtAbis().count() == 1 && qtAbis().first().isNull()) + return QCoreApplication::translate("QtVersion", "ABI detection failed: Make sure to use a matching tool chain when building."); if (qtVersion() >= QtSupport::QtVersionNumber(4, 7, 0) && qmlviewerCommand().isEmpty()) return QCoreApplication::translate("QtVersion", "No qmlviewer installed."); return QString(); } -QList<ProjectExplorer::Abi> SimulatorQtVersion::qtAbis() const +QList<ProjectExplorer::Abi> SimulatorQtVersion::detectQtAbis() const { - if (!m_qtAbisUpToDate) { - m_qtAbisUpToDate = true; - ensureMkSpecParsed(); - m_qtAbis = qtAbisFromLibrary(qtCorePath(versionInfo(), qtVersionString())); - } - return m_qtAbis; + ensureMkSpecParsed(); + return qtAbisFromLibrary(qtCorePath(versionInfo(), qtVersionString())); } bool SimulatorQtVersion::supportsTargetId(const QString &id) const @@ -120,4 +99,3 @@ QString SimulatorQtVersion::description() const { return QCoreApplication::translate("QtVersion", "Qt Simulator", "Qt Version is meant for Qt Simulator"); } - diff --git a/src/plugins/qt4projectmanager/qt-desktop/simulatorqtversion.h b/src/plugins/qt4projectmanager/qt-desktop/simulatorqtversion.h index 14e1e79bb92c3623a4af3297e3c9dcb96e3d664d..835b400746ac74eb2c6926431f1cf642bb04acd9 100644 --- a/src/plugins/qt4projectmanager/qt-desktop/simulatorqtversion.h +++ b/src/plugins/qt4projectmanager/qt-desktop/simulatorqtversion.h @@ -49,20 +49,14 @@ public: QString type() const; - bool isValid() const; - QString invalidReason() const; QString warningReason() const; - QList<ProjectExplorer::Abi> qtAbis() const; + QList<ProjectExplorer::Abi> detectQtAbis() const; bool supportsTargetId(const QString &id) const; QSet<QString> supportedTargetIds() const; QString description() const; - -private: - mutable bool m_qtAbisUpToDate; - mutable QList<ProjectExplorer::Abi> m_qtAbis; }; } diff --git a/src/plugins/qt4projectmanager/qt-s60/symbianqtversion.cpp b/src/plugins/qt4projectmanager/qt-s60/symbianqtversion.cpp index 6dc705b60b586f7abc40e649e3b6577f7d61c99f..57031f8b605f17b6eb4a7dda7d2607e69cccca79 100644 --- a/src/plugins/qt4projectmanager/qt-s60/symbianqtversion.cpp +++ b/src/plugins/qt4projectmanager/qt-s60/symbianqtversion.cpp @@ -163,7 +163,7 @@ QVariantMap SymbianQtVersion::toMap() const return result; } -QList<ProjectExplorer::Abi> SymbianQtVersion::qtAbis() const +QList<ProjectExplorer::Abi> SymbianQtVersion::detectQtAbis() const { return QList<ProjectExplorer::Abi>() << ProjectExplorer::Abi(ProjectExplorer::Abi::ArmArchitecture, ProjectExplorer::Abi::SymbianOS, diff --git a/src/plugins/qt4projectmanager/qt-s60/symbianqtversion.h b/src/plugins/qt4projectmanager/qt-s60/symbianqtversion.h index cfb26622cc323c2f4e013cc5bc862a1416f866be..460690451aa193bfbcf5a1f0cbf5cd8d7876999f 100644 --- a/src/plugins/qt4projectmanager/qt-s60/symbianqtversion.h +++ b/src/plugins/qt4projectmanager/qt-s60/symbianqtversion.h @@ -46,7 +46,7 @@ public: SymbianQtVersion *clone() const; ~SymbianQtVersion(); - virtual bool equals(BaseQtVersion *other); + bool equals(BaseQtVersion *other); QString type() const; @@ -59,7 +59,7 @@ public: void fromMap(const QVariantMap &map); QVariantMap toMap() const; - QList<ProjectExplorer::Abi> qtAbis() const; + QList<ProjectExplorer::Abi> detectQtAbis() const; bool supportsTargetId(const QString &id) const; QSet<QString> supportedTargetIds() const; diff --git a/src/plugins/qt4projectmanager/winceqtversion.cpp b/src/plugins/qt4projectmanager/winceqtversion.cpp index fc91ed52d06997637fba7ba05d7b531e62223e86..0b80869299ac3cdb8350b2a96115a289d76d24f5 100644 --- a/src/plugins/qt4projectmanager/winceqtversion.cpp +++ b/src/plugins/qt4projectmanager/winceqtversion.cpp @@ -65,7 +65,7 @@ QString WinCeQtVersion::type() const return QtSupport::Constants::WINCEQT; } -QList<ProjectExplorer::Abi> WinCeQtVersion::qtAbis() const +QList<ProjectExplorer::Abi> WinCeQtVersion::detectQtAbis() const { return QList<ProjectExplorer::Abi>() << ProjectExplorer::Abi(ProjectExplorer::Abi::ArmArchitecture, diff --git a/src/plugins/qt4projectmanager/winceqtversion.h b/src/plugins/qt4projectmanager/winceqtversion.h index b57e01fd50dbb6c1355604772c51f4f7dd9d1f17..7bff4a8063c01a5ea31c676a0871cea733d739e3 100644 --- a/src/plugins/qt4projectmanager/winceqtversion.h +++ b/src/plugins/qt4projectmanager/winceqtversion.h @@ -48,7 +48,7 @@ public: QString type() const; - QList<ProjectExplorer::Abi> qtAbis() const; + QList<ProjectExplorer::Abi> detectQtAbis() const; bool supportsTargetId(const QString &id) const; QSet<QString> supportedTargetIds() const; diff --git a/src/plugins/qtsupport/baseqtversion.cpp b/src/plugins/qtsupport/baseqtversion.cpp index 5a41c5deeb13a0bc675710b53e335cd4d318fcca..1cfab3b19984cad9305429653976202a397316b4 100644 --- a/src/plugins/qtsupport/baseqtversion.cpp +++ b/src/plugins/qtsupport/baseqtversion.cpp @@ -299,7 +299,7 @@ bool BaseQtVersion::isValid() const return !qmakeCommand().isEmpty() && !m_notInstalled && m_versionInfo.contains("QT_INSTALL_BINS") - && (!m_mkspecFullPath.isEmpty() || !m_mkspecUpToDate) + && !m_mkspecFullPath.isEmpty() && m_qmakeIsExecutable; } @@ -342,6 +342,15 @@ bool BaseQtVersion::toolChainAvailable(const QString &id) const return false; } +QList<ProjectExplorer::Abi> BaseQtVersion::qtAbis() const +{ + if (m_qtAbis.isEmpty()) + m_qtAbis = detectQtAbis(); + if (m_qtAbis.isEmpty()) + m_qtAbis.append(ProjectExplorer::Abi()); // add empty ABI by default: This is compatible with all TCs. + return m_qtAbis; +} + bool BaseQtVersion::equals(BaseQtVersion *other) { if (type() != other->type()) @@ -1199,11 +1208,5 @@ QString BaseQtVersion::qtCorePath(const QHash<QString,QString> &versionInfo, con QList<ProjectExplorer::Abi> BaseQtVersion::qtAbisFromLibrary(const QString &coreLibrary) { - QList<ProjectExplorer::Abi> qtAbis = ProjectExplorer::Abi::abisOfBinary(coreLibrary); - if (qtAbis.isEmpty() && !coreLibrary.isEmpty()) { - qWarning("Warning: Could not find ABI for '%s'" - "Qt Creator does not know about the system includes, " - "nor the system defines.", qPrintable(coreLibrary)); - } - return qtAbis; + return ProjectExplorer::Abi::abisOfBinary(coreLibrary); } diff --git a/src/plugins/qtsupport/baseqtversion.h b/src/plugins/qtsupport/baseqtversion.h index afbb7aacbbee442fe2e5fd4130ebad3d21313738..f525d5d62c3d3208eeed1f5c27b0b9ddd3e2fd12 100644 --- a/src/plugins/qtsupport/baseqtversion.h +++ b/src/plugins/qtsupport/baseqtversion.h @@ -125,7 +125,8 @@ public: virtual bool supportsTargetId(const QString &id) const = 0; virtual QSet<QString> supportedTargetIds() const = 0; - virtual QList<ProjectExplorer::Abi> qtAbis() const = 0; + QList<ProjectExplorer::Abi> qtAbis() const; + virtual QList<ProjectExplorer::Abi> detectQtAbis() const = 0; // Returns the PREFIX, BINPREFIX, DOCPREFIX and similar information virtual QHash<QString,QString> versionInfo() const; @@ -268,6 +269,7 @@ private: mutable QString m_qmlviewerCommand; mutable bool m_qmakeIsExecutable; + mutable QList<ProjectExplorer::Abi> m_qtAbis; }; } diff --git a/src/plugins/remotelinux/maemoqtversion.cpp b/src/plugins/remotelinux/maemoqtversion.cpp index 167bc2cedec51f9599f86c9f656da2f9bca6503d..8f61abd941fa93b0fae07131a3572f38ff105611 100644 --- a/src/plugins/remotelinux/maemoqtversion.cpp +++ b/src/plugins/remotelinux/maemoqtversion.cpp @@ -110,7 +110,7 @@ QString MaemoQtVersion::systemRoot() const return m_systemRoot; } -QList<ProjectExplorer::Abi> MaemoQtVersion::qtAbis() const +QList<ProjectExplorer::Abi> MaemoQtVersion::detectQtAbis() const { QList<ProjectExplorer::Abi> result; if (!m_isvalidVersion) diff --git a/src/plugins/remotelinux/maemoqtversion.h b/src/plugins/remotelinux/maemoqtversion.h index 7c64453eeb9a5aed2b3d3633bc35730b16ca45e3..6fcbccf0b9dcc8d40007cc30cbabb263bec470ec 100644 --- a/src/plugins/remotelinux/maemoqtversion.h +++ b/src/plugins/remotelinux/maemoqtversion.h @@ -50,7 +50,7 @@ public: QString type() const; bool isValid() const; QString systemRoot() const; - QList<ProjectExplorer::Abi> qtAbis() const; + QList<ProjectExplorer::Abi> detectQtAbis() const; void addToEnvironment(Utils::Environment &env) const; bool supportsTargetId(const QString &id) const;