From f163cdc9fe2c33b4f3b9a0bcb984cad0e053e2b5 Mon Sep 17 00:00:00 2001 From: James McDonnell Date: Fri, 16 Dec 2016 12:48:53 -0500 Subject: [PATCH] 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 Reviewed-by: Tobias Hunger --- src/plugins/qnx/qnxconfiguration.cpp | 25 ++--------- src/plugins/qnx/qnxconfiguration.h | 2 +- src/plugins/qnx/qnxtoolchain.cpp | 65 ++++++++++++++++++++++------ src/plugins/qnx/qnxtoolchain.h | 2 + src/plugins/qnx/qnxutils.cpp | 31 +++++++++++++ src/plugins/qnx/qnxutils.h | 13 ++++++ 6 files changed, 102 insertions(+), 36 deletions(-) diff --git a/src/plugins/qnx/qnxconfiguration.cpp b/src/plugins/qnx/qnxconfiguration.cpp index 66c455b0e6d..295b942c4f5 100644 --- a/src/plugins/qnx/qnxconfiguration.cpp +++ b/src/plugins/qnx/qnxconfiguration.cpp @@ -267,7 +267,6 @@ QVariant QnxConfiguration::createDebugger(const Target &target) QnxToolChain *QnxConfiguration::createToolChain(const Target &target) { QnxToolChain *toolChain = new QnxToolChain(ToolChain::AutoDetection); - toolChain->resetToolChain(qccCompilerPath()); toolChain->setLanguage(ProjectExplorer::Constants::CXX_LANGUAGE_ID); toolChain->setTargetAbi(target.m_abi); toolChain->setDisplayName( @@ -277,6 +276,7 @@ QnxToolChain *QnxConfiguration::createToolChain(const Target &target) .arg(displayName()) .arg(target.shortDescription())); toolChain->setSdpPath(sdpPath().toString()); + toolChain->resetToolChain(qccCompilerPath()); ToolChainManager::registerToolChain(toolChain); return toolChain; } @@ -414,26 +414,9 @@ const QnxConfiguration::Target *QnxConfiguration::findTargetByDebuggerPath( void QnxConfiguration::updateTargets() { m_targets.clear(); - - QDir targetsDir(m_qnxTarget.toString()); - QStringList targetNames = targetsDir.entryList(QDir::Dirs | QDir::NoDotAndDotDot); - foreach (const QString &targetName, targetNames) { - FileName targetPath = FileName(m_qnxTarget).appendPath(targetName); - FileName libc = FileName(targetPath).appendPath("lib/libc.so"); - if (libc.exists()) { - QList 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"; - } - } - } - + QList targets = QnxUtils::findTargets(m_qnxTarget); + for (const auto &target : targets) + m_targets.append(Target(target.m_abi, target.m_path)); } void QnxConfiguration::assignDebuggersToTargets() diff --git a/src/plugins/qnx/qnxconfiguration.h b/src/plugins/qnx/qnxconfiguration.h index bfb5c6d4069..613167a68c0 100644 --- a/src/plugins/qnx/qnxconfiguration.h +++ b/src/plugins/qnx/qnxconfiguration.h @@ -103,7 +103,7 @@ private: class Target { public: - Target(const ProjectExplorer::Abi &abi, Utils::FileName &path) + Target(const ProjectExplorer::Abi &abi, const Utils::FileName &path) : m_abi(abi), m_path(path) { } diff --git a/src/plugins/qnx/qnxtoolchain.cpp b/src/plugins/qnx/qnxtoolchain.cpp index 511bb9aaeda..3c0d89208c4 100644 --- a/src/plugins/qnx/qnxtoolchain.cpp +++ b/src/plugins/qnx/qnxtoolchain.cpp @@ -30,7 +30,7 @@ #include "qnxutils.h" #include - +#include #include #include @@ -43,15 +43,32 @@ namespace Internal { static const char CompilerSdpPath[] = "Qnx.QnxToolChain.NDKPath"; -static const QList qccSupportedAbis() +static QList detectTargetAbis(const FileName &sdpPath) { - QList abis; - abis << Abi(Abi::ArmArchitecture, Abi::LinuxOS, Abi::GenericLinuxFlavor, Abi::ElfFormat, 32); - 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); + QList result; + FileName qnxTarget; - return abis; + if (!sdpPath.fileName().isEmpty()) { + QList 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 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 &qnxEnv) @@ -133,10 +150,9 @@ void QnxToolChain::setSdpPath(const QString &sdpPath) toolChainUpdated(); } -// qcc doesn't support a "-dumpmachine" option to get supported abis 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 @@ -227,8 +243,9 @@ QnxToolChainConfigWidget::QnxToolChainConfigWidget(QnxToolChain *tc) m_sdpPath->setPath(tc->sdpPath()); m_sdpPath->setEnabled(!tc->isAutoDetected()); - m_abiWidget->setAbis(qccSupportedAbis(), tc->targetAbi()); - m_abiWidget->setEnabled(!tc->isAutoDetected()); + QList abiList = detectTargetAbis(m_sdpPath->fileName()); + m_abiWidget->setAbis(abiList, tc->targetAbi()); + m_abiWidget->setEnabled(!tc->isAutoDetected() && !abiList.isEmpty()); m_mainLayout->addRow(tr("&Compiler path:"), m_compilerCommand); //: SDP refers to 'Software Development Platform'. @@ -236,7 +253,8 @@ QnxToolChainConfigWidget::QnxToolChainConfigWidget(QnxToolChain *tc) m_mainLayout->addRow(tr("&ABI:"), m_abiWidget); 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); } @@ -248,10 +266,10 @@ void QnxToolChainConfigWidget::applyImpl() QnxToolChain *tc = static_cast(toolChain()); Q_ASSERT(tc); QString displayName = tc->displayName(); - tc->resetToolChain(m_compilerCommand->fileName()); tc->setDisplayName(displayName); // reset display name tc->setSdpPath(m_sdpPath->fileName().toString()); tc->setTargetAbi(m_abiWidget->currentAbi()); + tc->resetToolChain(m_compilerCommand->fileName()); } void QnxToolChainConfigWidget::discardImpl() @@ -276,5 +294,24 @@ bool QnxToolChainConfigWidget::isDirtyImpl() const || m_abiWidget->currentAbi() != tc->targetAbi(); } +void QnxToolChainConfigWidget::handleSdpPathChange() +{ + Abi currentAbi = m_abiWidget->currentAbi(); + bool customAbi = m_abiWidget->isCustomAbi(); + QList 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 Qnx diff --git a/src/plugins/qnx/qnxtoolchain.h b/src/plugins/qnx/qnxtoolchain.h index c2acccb60b1..e20c9f66ead 100644 --- a/src/plugins/qnx/qnxtoolchain.h +++ b/src/plugins/qnx/qnxtoolchain.h @@ -99,6 +99,8 @@ private: bool isDirtyImpl() const override; void makeReadOnlyImpl() override { } + void handleSdpPathChange(); + Utils::PathChooser *m_compilerCommand; Utils::PathChooser *m_sdpPath; ProjectExplorer::AbiWidget *m_abiWidget; diff --git a/src/plugins/qnx/qnxutils.cpp b/src/plugins/qnx/qnxutils.cpp index e77ad7c9f86..b1d67ba4d6f 100644 --- a/src/plugins/qnx/qnxutils.cpp +++ b/src/plugins/qnx/qnxutils.cpp @@ -26,11 +26,14 @@ #include "qnxutils.h" #include "qnxqtversion.h" +#include #include #include #include +#include #include +#include #include #include #include @@ -227,3 +230,31 @@ QList QnxUtils::qnxEnvironment(const QString &sdpPath) { return qnxEnvironmentFromEnvFile(envFilePath(sdpPath)); } + +QList QnxUtils::findTargets(const Utils::FileName &basePath) +{ + using namespace Utils; + QList 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; +} diff --git a/src/plugins/qnx/qnxutils.h b/src/plugins/qnx/qnxutils.h index bc6fa411f80..4a51692ad2f 100644 --- a/src/plugins/qnx/qnxutils.h +++ b/src/plugins/qnx/qnxutils.h @@ -27,6 +27,7 @@ #include "qnxconstants.h" +#include #include #include #include @@ -53,6 +54,17 @@ public: && !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 { public: @@ -64,6 +76,7 @@ public: static QString defaultTargetVersion(const QString &sdpPath); static QList installedConfigs(const QString &configPath = QString()); static QList qnxEnvironment(const QString &sdpPath); + static QList findTargets(const Utils::FileName &basePath); }; } // namespace Internal