forked from qt-creator/qt-creator
Switch QNX tool chains from hard-coded to detected ABIs
Move the target detection code from the QnxConfiguration class into a separate function that can be used by the QnxConfiguration code and the QnxToolChain code. Move some resetToolChain calls after setSdpPath calls. QNX ABI detection depends on the SDP path. Change-Id: I7417a5a1064a77edfb113d9d0010f1e061b81ca6 Reviewed-by: hjk <hjk@qt.io> Reviewed-by: Tobias Hunger <tobias.hunger@qt.io>
This commit is contained in:
@@ -267,7 +267,6 @@ QVariant QnxConfiguration::createDebugger(const Target &target)
|
|||||||
QnxToolChain *QnxConfiguration::createToolChain(const Target &target)
|
QnxToolChain *QnxConfiguration::createToolChain(const Target &target)
|
||||||
{
|
{
|
||||||
QnxToolChain *toolChain = new QnxToolChain(ToolChain::AutoDetection);
|
QnxToolChain *toolChain = new QnxToolChain(ToolChain::AutoDetection);
|
||||||
toolChain->resetToolChain(qccCompilerPath());
|
|
||||||
toolChain->setLanguage(ProjectExplorer::Constants::CXX_LANGUAGE_ID);
|
toolChain->setLanguage(ProjectExplorer::Constants::CXX_LANGUAGE_ID);
|
||||||
toolChain->setTargetAbi(target.m_abi);
|
toolChain->setTargetAbi(target.m_abi);
|
||||||
toolChain->setDisplayName(
|
toolChain->setDisplayName(
|
||||||
@@ -277,6 +276,7 @@ QnxToolChain *QnxConfiguration::createToolChain(const Target &target)
|
|||||||
.arg(displayName())
|
.arg(displayName())
|
||||||
.arg(target.shortDescription()));
|
.arg(target.shortDescription()));
|
||||||
toolChain->setSdpPath(sdpPath().toString());
|
toolChain->setSdpPath(sdpPath().toString());
|
||||||
|
toolChain->resetToolChain(qccCompilerPath());
|
||||||
ToolChainManager::registerToolChain(toolChain);
|
ToolChainManager::registerToolChain(toolChain);
|
||||||
return toolChain;
|
return toolChain;
|
||||||
}
|
}
|
||||||
@@ -414,26 +414,9 @@ const QnxConfiguration::Target *QnxConfiguration::findTargetByDebuggerPath(
|
|||||||
void QnxConfiguration::updateTargets()
|
void QnxConfiguration::updateTargets()
|
||||||
{
|
{
|
||||||
m_targets.clear();
|
m_targets.clear();
|
||||||
|
QList<QnxTarget> targets = QnxUtils::findTargets(m_qnxTarget);
|
||||||
QDir targetsDir(m_qnxTarget.toString());
|
for (const auto &target : targets)
|
||||||
QStringList targetNames = targetsDir.entryList(QDir::Dirs | QDir::NoDotAndDotDot);
|
m_targets.append(Target(target.m_abi, target.m_path));
|
||||||
foreach (const QString &targetName, targetNames) {
|
|
||||||
FileName targetPath = FileName(m_qnxTarget).appendPath(targetName);
|
|
||||||
FileName libc = FileName(targetPath).appendPath("lib/libc.so");
|
|
||||||
if (libc.exists()) {
|
|
||||||
QList<Abi> abis = Abi::abisOfBinary(libc);
|
|
||||||
if (abis.count() > 0) {
|
|
||||||
if (abis.count() > 1)
|
|
||||||
qWarning() << libc << "has more than one ABI ... processing all";
|
|
||||||
|
|
||||||
foreach (const Abi &abi, abis)
|
|
||||||
m_targets.append(Target(abi, targetPath));
|
|
||||||
} else {
|
|
||||||
qWarning() << libc << "has no ABIs ... discarded";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void QnxConfiguration::assignDebuggersToTargets()
|
void QnxConfiguration::assignDebuggersToTargets()
|
||||||
|
@@ -103,7 +103,7 @@ private:
|
|||||||
class Target
|
class Target
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Target(const ProjectExplorer::Abi &abi, Utils::FileName &path)
|
Target(const ProjectExplorer::Abi &abi, const Utils::FileName &path)
|
||||||
: m_abi(abi), m_path(path)
|
: m_abi(abi), m_path(path)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@@ -30,7 +30,7 @@
|
|||||||
#include "qnxutils.h"
|
#include "qnxutils.h"
|
||||||
|
|
||||||
#include <projectexplorer/projectexplorerconstants.h>
|
#include <projectexplorer/projectexplorerconstants.h>
|
||||||
|
#include <utils/algorithm.h>
|
||||||
#include <utils/pathchooser.h>
|
#include <utils/pathchooser.h>
|
||||||
|
|
||||||
#include <QFormLayout>
|
#include <QFormLayout>
|
||||||
@@ -43,15 +43,32 @@ namespace Internal {
|
|||||||
|
|
||||||
static const char CompilerSdpPath[] = "Qnx.QnxToolChain.NDKPath";
|
static const char CompilerSdpPath[] = "Qnx.QnxToolChain.NDKPath";
|
||||||
|
|
||||||
static const QList<Abi> qccSupportedAbis()
|
static QList<Abi> detectTargetAbis(const FileName &sdpPath)
|
||||||
{
|
{
|
||||||
QList<Abi> abis;
|
QList<Abi> result;
|
||||||
abis << Abi(Abi::ArmArchitecture, Abi::LinuxOS, Abi::GenericLinuxFlavor, Abi::ElfFormat, 32);
|
FileName qnxTarget;
|
||||||
abis << Abi(Abi::ArmArchitecture, Abi::LinuxOS, Abi::GenericLinuxFlavor, Abi::ElfFormat, 64);
|
|
||||||
abis << Abi(Abi::X86Architecture, Abi::LinuxOS, Abi::GenericLinuxFlavor, Abi::ElfFormat, 32);
|
|
||||||
abis << Abi(Abi::X86Architecture, Abi::LinuxOS, Abi::GenericLinuxFlavor, Abi::ElfFormat, 64);
|
|
||||||
|
|
||||||
return abis;
|
if (!sdpPath.fileName().isEmpty()) {
|
||||||
|
QList<Utils::EnvironmentItem> environment = QnxUtils::qnxEnvironment(sdpPath.toString());
|
||||||
|
foreach (const Utils::EnvironmentItem &item, environment) {
|
||||||
|
if (item.name == QLatin1Literal("QNX_TARGET"))
|
||||||
|
qnxTarget = FileName::fromString(item.value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (qnxTarget.isEmpty())
|
||||||
|
return result;
|
||||||
|
|
||||||
|
QList<QnxTarget> targets = QnxUtils::findTargets(qnxTarget);
|
||||||
|
for (const auto &target : targets) {
|
||||||
|
if (!result.contains(target.m_abi))
|
||||||
|
result.append(target.m_abi);
|
||||||
|
}
|
||||||
|
|
||||||
|
Utils::sort(result,
|
||||||
|
[](const Abi &arg1, const Abi &arg2) { return arg1.toString() < arg2.toString(); });
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void setQnxEnvironment(Environment &env, const QList<EnvironmentItem> &qnxEnv)
|
static void setQnxEnvironment(Environment &env, const QList<EnvironmentItem> &qnxEnv)
|
||||||
@@ -133,10 +150,9 @@ void QnxToolChain::setSdpPath(const QString &sdpPath)
|
|||||||
toolChainUpdated();
|
toolChainUpdated();
|
||||||
}
|
}
|
||||||
|
|
||||||
// qcc doesn't support a "-dumpmachine" option to get supported abis
|
|
||||||
GccToolChain::DetectedAbisResult QnxToolChain::detectSupportedAbis() const
|
GccToolChain::DetectedAbisResult QnxToolChain::detectSupportedAbis() const
|
||||||
{
|
{
|
||||||
return qccSupportedAbis();
|
return detectTargetAbis(FileName::fromString(m_sdpPath));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Qcc is a multi-compiler driver, and most of the gcc options can be accomplished by using the -Wp, and -Wc
|
// Qcc is a multi-compiler driver, and most of the gcc options can be accomplished by using the -Wp, and -Wc
|
||||||
@@ -227,8 +243,9 @@ QnxToolChainConfigWidget::QnxToolChainConfigWidget(QnxToolChain *tc)
|
|||||||
m_sdpPath->setPath(tc->sdpPath());
|
m_sdpPath->setPath(tc->sdpPath());
|
||||||
m_sdpPath->setEnabled(!tc->isAutoDetected());
|
m_sdpPath->setEnabled(!tc->isAutoDetected());
|
||||||
|
|
||||||
m_abiWidget->setAbis(qccSupportedAbis(), tc->targetAbi());
|
QList<Abi> abiList = detectTargetAbis(m_sdpPath->fileName());
|
||||||
m_abiWidget->setEnabled(!tc->isAutoDetected());
|
m_abiWidget->setAbis(abiList, tc->targetAbi());
|
||||||
|
m_abiWidget->setEnabled(!tc->isAutoDetected() && !abiList.isEmpty());
|
||||||
|
|
||||||
m_mainLayout->addRow(tr("&Compiler path:"), m_compilerCommand);
|
m_mainLayout->addRow(tr("&Compiler path:"), m_compilerCommand);
|
||||||
//: SDP refers to 'Software Development Platform'.
|
//: SDP refers to 'Software Development Platform'.
|
||||||
@@ -236,7 +253,8 @@ QnxToolChainConfigWidget::QnxToolChainConfigWidget(QnxToolChain *tc)
|
|||||||
m_mainLayout->addRow(tr("&ABI:"), m_abiWidget);
|
m_mainLayout->addRow(tr("&ABI:"), m_abiWidget);
|
||||||
|
|
||||||
connect(m_compilerCommand, &PathChooser::rawPathChanged, this, &ToolChainConfigWidget::dirty);
|
connect(m_compilerCommand, &PathChooser::rawPathChanged, this, &ToolChainConfigWidget::dirty);
|
||||||
connect(m_sdpPath, &PathChooser::rawPathChanged, this, &ToolChainConfigWidget::dirty);
|
connect(m_sdpPath, &PathChooser::rawPathChanged,
|
||||||
|
this, &QnxToolChainConfigWidget::handleSdpPathChange);
|
||||||
connect(m_abiWidget, &AbiWidget::abiChanged, this, &ToolChainConfigWidget::dirty);
|
connect(m_abiWidget, &AbiWidget::abiChanged, this, &ToolChainConfigWidget::dirty);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -248,10 +266,10 @@ void QnxToolChainConfigWidget::applyImpl()
|
|||||||
QnxToolChain *tc = static_cast<QnxToolChain *>(toolChain());
|
QnxToolChain *tc = static_cast<QnxToolChain *>(toolChain());
|
||||||
Q_ASSERT(tc);
|
Q_ASSERT(tc);
|
||||||
QString displayName = tc->displayName();
|
QString displayName = tc->displayName();
|
||||||
tc->resetToolChain(m_compilerCommand->fileName());
|
|
||||||
tc->setDisplayName(displayName); // reset display name
|
tc->setDisplayName(displayName); // reset display name
|
||||||
tc->setSdpPath(m_sdpPath->fileName().toString());
|
tc->setSdpPath(m_sdpPath->fileName().toString());
|
||||||
tc->setTargetAbi(m_abiWidget->currentAbi());
|
tc->setTargetAbi(m_abiWidget->currentAbi());
|
||||||
|
tc->resetToolChain(m_compilerCommand->fileName());
|
||||||
}
|
}
|
||||||
|
|
||||||
void QnxToolChainConfigWidget::discardImpl()
|
void QnxToolChainConfigWidget::discardImpl()
|
||||||
@@ -276,5 +294,24 @@ bool QnxToolChainConfigWidget::isDirtyImpl() const
|
|||||||
|| m_abiWidget->currentAbi() != tc->targetAbi();
|
|| m_abiWidget->currentAbi() != tc->targetAbi();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void QnxToolChainConfigWidget::handleSdpPathChange()
|
||||||
|
{
|
||||||
|
Abi currentAbi = m_abiWidget->currentAbi();
|
||||||
|
bool customAbi = m_abiWidget->isCustomAbi();
|
||||||
|
QList<Abi> abiList = detectTargetAbis(m_sdpPath->fileName());
|
||||||
|
|
||||||
|
m_abiWidget->setEnabled(!abiList.isEmpty());
|
||||||
|
|
||||||
|
// Find a good ABI for the new compiler:
|
||||||
|
Abi newAbi;
|
||||||
|
if (customAbi)
|
||||||
|
newAbi = currentAbi;
|
||||||
|
else if (abiList.contains(currentAbi))
|
||||||
|
newAbi = currentAbi;
|
||||||
|
|
||||||
|
m_abiWidget->setAbis(abiList, newAbi);
|
||||||
|
emit dirty();
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Internal
|
} // namespace Internal
|
||||||
} // namespace Qnx
|
} // namespace Qnx
|
||||||
|
@@ -99,6 +99,8 @@ private:
|
|||||||
bool isDirtyImpl() const override;
|
bool isDirtyImpl() const override;
|
||||||
void makeReadOnlyImpl() override { }
|
void makeReadOnlyImpl() override { }
|
||||||
|
|
||||||
|
void handleSdpPathChange();
|
||||||
|
|
||||||
Utils::PathChooser *m_compilerCommand;
|
Utils::PathChooser *m_compilerCommand;
|
||||||
Utils::PathChooser *m_sdpPath;
|
Utils::PathChooser *m_sdpPath;
|
||||||
ProjectExplorer::AbiWidget *m_abiWidget;
|
ProjectExplorer::AbiWidget *m_abiWidget;
|
||||||
|
@@ -26,11 +26,14 @@
|
|||||||
#include "qnxutils.h"
|
#include "qnxutils.h"
|
||||||
#include "qnxqtversion.h"
|
#include "qnxqtversion.h"
|
||||||
|
|
||||||
|
#include <utils/fileutils.h>
|
||||||
#include <utils/hostosinfo.h>
|
#include <utils/hostosinfo.h>
|
||||||
#include <utils/synchronousprocess.h>
|
#include <utils/synchronousprocess.h>
|
||||||
#include <utils/temporaryfile.h>
|
#include <utils/temporaryfile.h>
|
||||||
|
|
||||||
|
#include <QDebug>
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
|
#include <QDirIterator>
|
||||||
#include <QDomDocument>
|
#include <QDomDocument>
|
||||||
#include <QProcess>
|
#include <QProcess>
|
||||||
#include <QStandardPaths>
|
#include <QStandardPaths>
|
||||||
@@ -227,3 +230,31 @@ QList<Utils::EnvironmentItem> QnxUtils::qnxEnvironment(const QString &sdpPath)
|
|||||||
{
|
{
|
||||||
return qnxEnvironmentFromEnvFile(envFilePath(sdpPath));
|
return qnxEnvironmentFromEnvFile(envFilePath(sdpPath));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QList<QnxTarget> QnxUtils::findTargets(const Utils::FileName &basePath)
|
||||||
|
{
|
||||||
|
using namespace Utils;
|
||||||
|
QList<QnxTarget> result;
|
||||||
|
|
||||||
|
QDirIterator iterator(basePath.toString());
|
||||||
|
while (iterator.hasNext()) {
|
||||||
|
iterator.next();
|
||||||
|
FileName libc = FileName::fromString(iterator.filePath()).appendPath("lib/libc.so");
|
||||||
|
if (libc.exists()) {
|
||||||
|
auto abis = Abi::abisOfBinary(libc);
|
||||||
|
if (abis.isEmpty()) {
|
||||||
|
qWarning() << libc << "has no ABIs ... discarded";
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (abis.count() > 1)
|
||||||
|
qWarning() << libc << "has more than one ABI ... processing all";
|
||||||
|
|
||||||
|
FileName path = FileName::fromString(iterator.filePath());
|
||||||
|
for (auto abi : abis)
|
||||||
|
result.append(QnxTarget(path, abi));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
@@ -27,6 +27,7 @@
|
|||||||
|
|
||||||
#include "qnxconstants.h"
|
#include "qnxconstants.h"
|
||||||
|
|
||||||
|
#include <projectexplorer/abi.h>
|
||||||
#include <utils/environment.h>
|
#include <utils/environment.h>
|
||||||
#include <utils/qtcassert.h>
|
#include <utils/qtcassert.h>
|
||||||
#include <utils/fileutils.h>
|
#include <utils/fileutils.h>
|
||||||
@@ -53,6 +54,17 @@ public:
|
|||||||
&& !target.isEmpty() && !version.isEmpty() && !installationXmlFilePath.isEmpty(); }
|
&& !target.isEmpty() && !version.isEmpty() && !installationXmlFilePath.isEmpty(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class QnxTarget
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
QnxTarget(const Utils::FileName &path, const ProjectExplorer::Abi &abi) :
|
||||||
|
m_path(path), m_abi(abi)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
Utils::FileName m_path;
|
||||||
|
ProjectExplorer::Abi m_abi;
|
||||||
|
};
|
||||||
|
|
||||||
class QnxUtils
|
class QnxUtils
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -64,6 +76,7 @@ public:
|
|||||||
static QString defaultTargetVersion(const QString &sdpPath);
|
static QString defaultTargetVersion(const QString &sdpPath);
|
||||||
static QList<ConfigInstallInformation> installedConfigs(const QString &configPath = QString());
|
static QList<ConfigInstallInformation> installedConfigs(const QString &configPath = QString());
|
||||||
static QList<Utils::EnvironmentItem> qnxEnvironment(const QString &sdpPath);
|
static QList<Utils::EnvironmentItem> qnxEnvironment(const QString &sdpPath);
|
||||||
|
static QList<QnxTarget> findTargets(const Utils::FileName &basePath);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Internal
|
} // namespace Internal
|
||||||
|
Reference in New Issue
Block a user