ABI: Improve tool chain selection for Qt projects

* Set a null-ABI for toolchains where detection of ABI failed: This
  allows the user to select any tool chain.

* Warn if ABI detection fails by showing a message in the Qt version
  setup dialog

* Do not override the mkspec if the Qt version has a null ABI only:
  We (have to) trust the user to know what he is doing in that case.

* GCC: Add version information to GCC tool chain and use it to select
  the mkspec on Mac.

* GCC: Do not override mkspec if we do a cross-compile
  (and actually detect that).

* GCC: Leave out -32 or -64 from mkspec if the compiler binaries ABI
  matches the target ABI.

* Linux-generic is compatible with all other linuxes (both ways)
  The targets themselves do additional filtering and will remove
  anything that does not work for them anyway.

Task-number: QTCREATORBUG-5756
Task-number: QTCREATORBUG-5960
Change-Id: Ib3c0ac91f3aa8e2a823e3e9891a02bdccb97af14
Reviewed-on: http://codereview.qt-project.org/4281
Reviewed-by: Qt Sanity Bot <qt_sanity_bot@ovi.com>
Reviewed-by: Daniel Teske <daniel.teske@nokia.com>
This commit is contained in:
Tobias Hunger
2011-09-06 15:19:05 +00:00
parent bfd9fcbb3c
commit aaf260c04b
15 changed files with 97 additions and 97 deletions

View File

@@ -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

View File

@@ -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;

View File

@@ -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

View File

@@ -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

View File

@@ -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;
};
}

View File

@@ -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");
}

View File

@@ -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;
};
}

View File

@@ -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,

View File

@@ -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;

View File

@@ -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,

View File

@@ -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;

View File

@@ -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);
}

View File

@@ -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;
};
}

View File

@@ -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)

View File

@@ -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;