forked from qt-creator/qt-creator
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:
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user