forked from qt-creator/qt-creator
Qnx: Re-work item store
This reduces the number of updates from the env* files and overall simplifies the architecture. I actually believe that it would be better if the whole configuration settings page would not exist but be part of the device settings page. Change-Id: I4184b74fc2c9695356752903c861f3758a6d7c73 Reviewed-by: Christian Stenger <christian.stenger@qt.io> Reviewed-by: <github-actions-qt-creator@cristianadam.eu>
This commit is contained in:
@@ -4,8 +4,6 @@ add_qtc_plugin(Qnx
|
|||||||
SOURCES
|
SOURCES
|
||||||
qnx.qrc
|
qnx.qrc
|
||||||
qnxanalyzesupport.cpp qnxanalyzesupport.h
|
qnxanalyzesupport.cpp qnxanalyzesupport.h
|
||||||
qnxconfiguration.cpp qnxconfiguration.h
|
|
||||||
qnxconfigurationmanager.cpp qnxconfigurationmanager.h
|
|
||||||
qnxconstants.h
|
qnxconstants.h
|
||||||
qnxdebugsupport.cpp qnxdebugsupport.h
|
qnxdebugsupport.cpp qnxdebugsupport.h
|
||||||
qnxdeployqtlibrariesdialog.cpp qnxdeployqtlibrariesdialog.h
|
qnxdeployqtlibrariesdialog.cpp qnxdeployqtlibrariesdialog.h
|
||||||
|
@@ -20,8 +20,6 @@ QtcPlugin {
|
|||||||
"qnxtoolchain.h",
|
"qnxtoolchain.h",
|
||||||
"qnx.qrc",
|
"qnx.qrc",
|
||||||
"qnxconstants.h",
|
"qnxconstants.h",
|
||||||
"qnxconfiguration.cpp",
|
|
||||||
"qnxconfiguration.h",
|
|
||||||
"qnxanalyzesupport.cpp",
|
"qnxanalyzesupport.cpp",
|
||||||
"qnxanalyzesupport.h",
|
"qnxanalyzesupport.h",
|
||||||
"qnxdebugsupport.cpp",
|
"qnxdebugsupport.cpp",
|
||||||
@@ -30,8 +28,6 @@ QtcPlugin {
|
|||||||
"qnxdevice.h",
|
"qnxdevice.h",
|
||||||
"qnxdevicetester.cpp",
|
"qnxdevicetester.cpp",
|
||||||
"qnxdevicetester.h",
|
"qnxdevicetester.h",
|
||||||
"qnxconfigurationmanager.cpp",
|
|
||||||
"qnxconfigurationmanager.h",
|
|
||||||
"qnxsettingspage.cpp",
|
"qnxsettingspage.cpp",
|
||||||
"qnxsettingspage.h",
|
"qnxsettingspage.h",
|
||||||
"qnxtr.h",
|
"qnxtr.h",
|
||||||
|
@@ -1,466 +0,0 @@
|
|||||||
// Copyright (C) 2016 BlackBerry Limited. All rights reserved.
|
|
||||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
|
||||||
|
|
||||||
#include "qnxconfiguration.h"
|
|
||||||
|
|
||||||
#include "qnxqtversion.h"
|
|
||||||
#include "qnxutils.h"
|
|
||||||
#include "qnxtoolchain.h"
|
|
||||||
#include "qnxtr.h"
|
|
||||||
|
|
||||||
#include <coreplugin/icore.h>
|
|
||||||
|
|
||||||
#include <debugger/debuggeritem.h>
|
|
||||||
#include <debugger/debuggeritemmanager.h>
|
|
||||||
#include <debugger/debuggerkitinformation.h>
|
|
||||||
|
|
||||||
#include <projectexplorer/toolchainmanager.h>
|
|
||||||
#include <projectexplorer/toolchain.h>
|
|
||||||
#include <projectexplorer/kit.h>
|
|
||||||
#include <projectexplorer/kitmanager.h>
|
|
||||||
|
|
||||||
#include <qtsupport/baseqtversion.h>
|
|
||||||
#include <qtsupport/qtversionmanager.h>
|
|
||||||
#include <qtsupport/qtkitinformation.h>
|
|
||||||
|
|
||||||
#include <qmakeprojectmanager/qmakeprojectmanagerconstants.h>
|
|
||||||
|
|
||||||
#include <utils/algorithm.h>
|
|
||||||
|
|
||||||
#include <QDebug>
|
|
||||||
#include <QDomDocument>
|
|
||||||
#include <QMessageBox>
|
|
||||||
|
|
||||||
using namespace ProjectExplorer;
|
|
||||||
using namespace QtSupport;
|
|
||||||
using namespace Utils;
|
|
||||||
using namespace Debugger;
|
|
||||||
|
|
||||||
namespace Qnx::Internal {
|
|
||||||
|
|
||||||
const QLatin1String QNXEnvFileKey("EnvFile");
|
|
||||||
const QLatin1String QNXVersionKey("QNXVersion");
|
|
||||||
// For backward compatibility
|
|
||||||
const QLatin1String SdpEnvFileKey("NDKEnvFile");
|
|
||||||
|
|
||||||
const QLatin1String QNXConfiguration("QNX_CONFIGURATION");
|
|
||||||
const QLatin1String QNXTarget("QNX_TARGET");
|
|
||||||
const QLatin1String QNXHost("QNX_HOST");
|
|
||||||
|
|
||||||
QnxConfiguration::QnxConfiguration() = default;
|
|
||||||
|
|
||||||
QnxConfiguration::QnxConfiguration(const FilePath &sdpEnvFile)
|
|
||||||
{
|
|
||||||
setDefaultConfiguration(sdpEnvFile);
|
|
||||||
readInformation();
|
|
||||||
}
|
|
||||||
|
|
||||||
QnxConfiguration::QnxConfiguration(const QVariantMap &data)
|
|
||||||
{
|
|
||||||
QString envFilePath = data.value(QNXEnvFileKey).toString();
|
|
||||||
if (envFilePath.isEmpty())
|
|
||||||
envFilePath = data.value(SdpEnvFileKey).toString();
|
|
||||||
|
|
||||||
m_version = QnxVersionNumber(data.value(QNXVersionKey).toString());
|
|
||||||
|
|
||||||
setDefaultConfiguration(FilePath::fromString(envFilePath));
|
|
||||||
readInformation();
|
|
||||||
}
|
|
||||||
|
|
||||||
FilePath QnxConfiguration::envFile() const
|
|
||||||
{
|
|
||||||
return m_envFile;
|
|
||||||
}
|
|
||||||
|
|
||||||
FilePath QnxConfiguration::qnxTarget() const
|
|
||||||
{
|
|
||||||
return m_qnxTarget;
|
|
||||||
}
|
|
||||||
|
|
||||||
FilePath QnxConfiguration::qnxHost() const
|
|
||||||
{
|
|
||||||
return m_qnxHost;
|
|
||||||
}
|
|
||||||
|
|
||||||
FilePath QnxConfiguration::qccCompilerPath() const
|
|
||||||
{
|
|
||||||
return m_qccCompiler;
|
|
||||||
}
|
|
||||||
|
|
||||||
EnvironmentItems QnxConfiguration::qnxEnv() const
|
|
||||||
{
|
|
||||||
return m_qnxEnv;
|
|
||||||
}
|
|
||||||
|
|
||||||
QnxVersionNumber QnxConfiguration::version() const
|
|
||||||
{
|
|
||||||
return m_version;
|
|
||||||
}
|
|
||||||
|
|
||||||
QVariantMap QnxConfiguration::toMap() const
|
|
||||||
{
|
|
||||||
QVariantMap data;
|
|
||||||
data.insert(QLatin1String(QNXEnvFileKey), m_envFile.toString());
|
|
||||||
data.insert(QLatin1String(QNXVersionKey), m_version.toString());
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool QnxConfiguration::isValid() const
|
|
||||||
{
|
|
||||||
return !m_qccCompiler.isEmpty() && !m_targets.isEmpty();
|
|
||||||
}
|
|
||||||
|
|
||||||
QString QnxConfiguration::displayName() const
|
|
||||||
{
|
|
||||||
return m_configName;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool QnxConfiguration::activate()
|
|
||||||
{
|
|
||||||
if (isActive())
|
|
||||||
return true;
|
|
||||||
|
|
||||||
if (!isValid()) {
|
|
||||||
QMessageBox::warning(Core::ICore::dialogParent(), Tr::tr("Cannot Set Up QNX Configuration"),
|
|
||||||
validationErrorMessage(), QMessageBox::Ok);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const Target &target : std::as_const(m_targets))
|
|
||||||
createTools(target);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void QnxConfiguration::deactivate()
|
|
||||||
{
|
|
||||||
if (!isActive())
|
|
||||||
return;
|
|
||||||
|
|
||||||
const Toolchains toolChainsToRemove =
|
|
||||||
ToolChainManager::toolchains(Utils::equal(&ToolChain::compilerCommand, qccCompilerPath()));
|
|
||||||
|
|
||||||
QList<DebuggerItem> debuggersToRemove;
|
|
||||||
const QList<DebuggerItem> debuggerItems = DebuggerItemManager::debuggers();
|
|
||||||
for (const DebuggerItem &debuggerItem : debuggerItems) {
|
|
||||||
if (findTargetByDebuggerPath(debuggerItem.command()))
|
|
||||||
debuggersToRemove.append(debuggerItem);
|
|
||||||
}
|
|
||||||
|
|
||||||
const QList<Kit *> kits = KitManager::kits();
|
|
||||||
for (Kit *kit : kits) {
|
|
||||||
if (kit->isAutoDetected()
|
|
||||||
&& DeviceTypeKitAspect::deviceTypeId(kit) == Constants::QNX_QNX_OS_TYPE
|
|
||||||
&& toolChainsToRemove.contains(ToolChainKitAspect::cxxToolChain(kit))) {
|
|
||||||
KitManager::deregisterKit(kit);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (ToolChain *tc : toolChainsToRemove)
|
|
||||||
ToolChainManager::deregisterToolChain(tc);
|
|
||||||
|
|
||||||
for (const DebuggerItem &debuggerItem : std::as_const(debuggersToRemove))
|
|
||||||
DebuggerItemManager::deregisterDebugger(debuggerItem.id());
|
|
||||||
}
|
|
||||||
|
|
||||||
bool QnxConfiguration::isActive() const
|
|
||||||
{
|
|
||||||
const bool hasToolChain = ToolChainManager::toolChain(Utils::equal(&ToolChain::compilerCommand,
|
|
||||||
qccCompilerPath()));
|
|
||||||
const bool hasDebugger = Utils::contains(DebuggerItemManager::debuggers(), [this](const DebuggerItem &di) {
|
|
||||||
return findTargetByDebuggerPath(di.command());
|
|
||||||
});
|
|
||||||
|
|
||||||
return hasToolChain && hasDebugger;
|
|
||||||
}
|
|
||||||
|
|
||||||
FilePath QnxConfiguration::sdpPath() const
|
|
||||||
{
|
|
||||||
return envFile().parentDir();
|
|
||||||
}
|
|
||||||
|
|
||||||
QnxQtVersion *QnxConfiguration::qnxQtVersion(const Target &target) const
|
|
||||||
{
|
|
||||||
const QtVersions versions = QtVersionManager::versions(
|
|
||||||
Utils::equal(&QtVersion::type, QString::fromLatin1(Constants::QNX_QNX_QT)));
|
|
||||||
for (QtVersion *version : versions) {
|
|
||||||
auto qnxQt = dynamic_cast<QnxQtVersion *>(version);
|
|
||||||
if (qnxQt && qnxQt->sdpPath() == sdpPath()) {
|
|
||||||
const Abis abis = version->qtAbis();
|
|
||||||
for (const Abi &qtAbi : abis) {
|
|
||||||
if ((qtAbi == target.m_abi) && (qnxQt->cpuDir() == target.cpuDir()))
|
|
||||||
return qnxQt;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
QList<ToolChain *> QnxConfiguration::autoDetect(const QList<ToolChain *> &alreadyKnown)
|
|
||||||
{
|
|
||||||
QList<ToolChain *> result;
|
|
||||||
|
|
||||||
for (const Target &target : std::as_const(m_targets))
|
|
||||||
result += findToolChain(alreadyKnown, target.m_abi);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
void QnxConfiguration::createTools(const Target &target)
|
|
||||||
{
|
|
||||||
QnxToolChainMap toolchainMap = createToolChain(target);
|
|
||||||
QVariant debuggerId = createDebugger(target);
|
|
||||||
createKit(target, toolchainMap, debuggerId);
|
|
||||||
}
|
|
||||||
|
|
||||||
QVariant QnxConfiguration::createDebugger(const Target &target)
|
|
||||||
{
|
|
||||||
Environment sysEnv = m_qnxHost.deviceEnvironment();
|
|
||||||
sysEnv.modify(qnxEnvironmentItems());
|
|
||||||
|
|
||||||
Debugger::DebuggerItem debugger;
|
|
||||||
debugger.setCommand(target.m_debuggerPath);
|
|
||||||
debugger.reinitializeFromFile(nullptr, &sysEnv);
|
|
||||||
debugger.setUnexpandedDisplayName(Tr::tr("Debugger for %1 (%2)")
|
|
||||||
.arg(displayName())
|
|
||||||
.arg(target.shortDescription()));
|
|
||||||
return Debugger::DebuggerItemManager::registerDebugger(debugger);
|
|
||||||
}
|
|
||||||
|
|
||||||
QnxConfiguration::QnxToolChainMap QnxConfiguration::createToolChain(const Target &target)
|
|
||||||
{
|
|
||||||
QnxToolChainMap toolChainMap;
|
|
||||||
|
|
||||||
for (auto language : { ProjectExplorer::Constants::C_LANGUAGE_ID,
|
|
||||||
ProjectExplorer::Constants::CXX_LANGUAGE_ID}) {
|
|
||||||
auto toolChain = new QnxToolChain;
|
|
||||||
toolChain->setDetection(ToolChain::AutoDetection);
|
|
||||||
toolChain->setLanguage(language);
|
|
||||||
toolChain->setTargetAbi(target.m_abi);
|
|
||||||
toolChain->setDisplayName(Tr::tr("QCC for %1 (%2)")
|
|
||||||
.arg(displayName())
|
|
||||||
.arg(target.shortDescription()));
|
|
||||||
toolChain->setSdpPath(sdpPath());
|
|
||||||
toolChain->setCpuDir(target.cpuDir());
|
|
||||||
toolChain->resetToolChain(qccCompilerPath());
|
|
||||||
ToolChainManager::registerToolChain(toolChain);
|
|
||||||
|
|
||||||
toolChainMap.insert({language, toolChain});
|
|
||||||
}
|
|
||||||
|
|
||||||
return toolChainMap;
|
|
||||||
}
|
|
||||||
|
|
||||||
QList<ToolChain *> QnxConfiguration::findToolChain(const QList<ToolChain *> &alreadyKnown,
|
|
||||||
const Abi &abi)
|
|
||||||
{
|
|
||||||
return Utils::filtered(alreadyKnown, [this, abi](ToolChain *tc) {
|
|
||||||
return tc->typeId() == Constants::QNX_TOOLCHAIN_ID
|
|
||||||
&& tc->targetAbi() == abi
|
|
||||||
&& tc->compilerCommand() == m_qccCompiler;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
void QnxConfiguration::createKit(const Target &target, const QnxToolChainMap &toolChainMap,
|
|
||||||
const QVariant &debugger)
|
|
||||||
{
|
|
||||||
QnxQtVersion *qnxQt = qnxQtVersion(target); // nullptr is ok.
|
|
||||||
|
|
||||||
const auto init = [&](Kit *k) {
|
|
||||||
QtKitAspect::setQtVersion(k, qnxQt);
|
|
||||||
ToolChainKitAspect::setToolChain(k, toolChainMap.at(ProjectExplorer::Constants::C_LANGUAGE_ID));
|
|
||||||
ToolChainKitAspect::setToolChain(k, toolChainMap.at(ProjectExplorer::Constants::CXX_LANGUAGE_ID));
|
|
||||||
|
|
||||||
if (debugger.isValid())
|
|
||||||
DebuggerKitAspect::setDebugger(k, debugger);
|
|
||||||
|
|
||||||
DeviceTypeKitAspect::setDeviceTypeId(k, Constants::QNX_QNX_OS_TYPE);
|
|
||||||
// TODO: Add sysroot?
|
|
||||||
|
|
||||||
k->setUnexpandedDisplayName(Tr::tr("Kit for %1 (%2)")
|
|
||||||
.arg(displayName())
|
|
||||||
.arg(target.shortDescription()));
|
|
||||||
|
|
||||||
k->setAutoDetected(false);
|
|
||||||
k->setAutoDetectionSource(envFile().toString());
|
|
||||||
k->setMutable(DeviceKitAspect::id(), true);
|
|
||||||
|
|
||||||
k->setSticky(ToolChainKitAspect::id(), true);
|
|
||||||
k->setSticky(DeviceTypeKitAspect::id(), true);
|
|
||||||
k->setSticky(SysRootKitAspect::id(), true);
|
|
||||||
k->setSticky(DebuggerKitAspect::id(), true);
|
|
||||||
k->setSticky(QmakeProjectManager::Constants::KIT_INFORMATION_ID, true);
|
|
||||||
|
|
||||||
EnvironmentKitAspect::setEnvironmentChanges(k, qnxEnvironmentItems());
|
|
||||||
};
|
|
||||||
|
|
||||||
// add kit with device and qt version not sticky
|
|
||||||
KitManager::registerKit(init);
|
|
||||||
}
|
|
||||||
|
|
||||||
QString QnxConfiguration::validationErrorMessage() const
|
|
||||||
{
|
|
||||||
if (isValid())
|
|
||||||
return {};
|
|
||||||
|
|
||||||
QStringList errorStrings
|
|
||||||
= {Tr::tr("The following errors occurred while activating the QNX configuration:")};
|
|
||||||
if (m_qccCompiler.isEmpty())
|
|
||||||
errorStrings << Tr::tr("- No GCC compiler found.");
|
|
||||||
if (m_targets.isEmpty())
|
|
||||||
errorStrings << Tr::tr("- No targets found.");
|
|
||||||
return errorStrings.join('\n');
|
|
||||||
}
|
|
||||||
|
|
||||||
void QnxConfiguration::setVersion(const QnxVersionNumber &version)
|
|
||||||
{
|
|
||||||
m_version = version;
|
|
||||||
}
|
|
||||||
|
|
||||||
void QnxConfiguration::readInformation()
|
|
||||||
{
|
|
||||||
const FilePath configPath = m_qnxConfiguration / "qconfig";
|
|
||||||
if (!configPath.isDir())
|
|
||||||
return;
|
|
||||||
|
|
||||||
configPath.iterateDirectory([this, configPath](const FilePath &sdpFile) {
|
|
||||||
QFile xmlFile(sdpFile.toFSPathString());
|
|
||||||
if (!xmlFile.open(QIODevice::ReadOnly))
|
|
||||||
return IterationPolicy::Continue;
|
|
||||||
|
|
||||||
QDomDocument doc;
|
|
||||||
if (!doc.setContent(&xmlFile)) // Skip error message
|
|
||||||
return IterationPolicy::Continue;
|
|
||||||
|
|
||||||
QDomElement docElt = doc.documentElement();
|
|
||||||
if (docElt.tagName() != QLatin1String("qnxSystemDefinition"))
|
|
||||||
return IterationPolicy::Continue;
|
|
||||||
|
|
||||||
QDomElement childElt = docElt.firstChildElement(QLatin1String("installation"));
|
|
||||||
// The file contains only one installation node
|
|
||||||
if (childElt.isNull()) // The file contains only one base node
|
|
||||||
return IterationPolicy::Continue;
|
|
||||||
|
|
||||||
FilePath host = configPath.withNewPath(
|
|
||||||
childElt.firstChildElement(QLatin1String("host")).text()).canonicalPath();
|
|
||||||
if (m_qnxHost != host)
|
|
||||||
return IterationPolicy::Continue;
|
|
||||||
|
|
||||||
FilePath target = configPath.withNewPath(
|
|
||||||
childElt.firstChildElement(QLatin1String("target")).text()).canonicalPath();
|
|
||||||
if (m_qnxTarget != target)
|
|
||||||
return IterationPolicy::Continue;
|
|
||||||
|
|
||||||
m_configName = childElt.firstChildElement(QLatin1String("name")).text();
|
|
||||||
QString version = childElt.firstChildElement(QLatin1String("version")).text();
|
|
||||||
setVersion(QnxVersionNumber(version));
|
|
||||||
return IterationPolicy::Stop;
|
|
||||||
}, {{"*.xml"}, QDir::Files});
|
|
||||||
}
|
|
||||||
|
|
||||||
void QnxConfiguration::setDefaultConfiguration(const FilePath &envScript)
|
|
||||||
{
|
|
||||||
QTC_ASSERT(!envScript.isEmpty(), return);
|
|
||||||
m_envFile = envScript;
|
|
||||||
m_qnxEnv = QnxUtils::qnxEnvironmentFromEnvFile(m_envFile);
|
|
||||||
for (const EnvironmentItem &item : std::as_const(m_qnxEnv)) {
|
|
||||||
if (item.name == QNXConfiguration)
|
|
||||||
m_qnxConfiguration = envScript.withNewPath(item.value).canonicalPath();
|
|
||||||
else if (item.name == QNXTarget)
|
|
||||||
m_qnxTarget = envScript.withNewPath(item.value).canonicalPath();
|
|
||||||
else if (item.name == QNXHost)
|
|
||||||
m_qnxHost = envScript.withNewPath(item.value).canonicalPath();
|
|
||||||
}
|
|
||||||
|
|
||||||
const FilePath qccPath = m_qnxHost.pathAppended("usr/bin/qcc").withExecutableSuffix();
|
|
||||||
if (qccPath.exists())
|
|
||||||
m_qccCompiler = qccPath;
|
|
||||||
|
|
||||||
// Some fall back in case the qconfig dir with .xml files is not found later
|
|
||||||
if (m_configName.isEmpty())
|
|
||||||
m_configName = QString("%1 - %2").arg(m_qnxHost.fileName(), m_qnxTarget.fileName());
|
|
||||||
|
|
||||||
updateTargets();
|
|
||||||
assignDebuggersToTargets();
|
|
||||||
|
|
||||||
// Remove debuggerless targets.
|
|
||||||
Utils::erase(m_targets, [](const Target &target) {
|
|
||||||
if (target.m_debuggerPath.isEmpty())
|
|
||||||
qWarning() << "No debugger found for" << target.m_path << "... discarded";
|
|
||||||
return target.m_debuggerPath.isEmpty();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
EnvironmentItems QnxConfiguration::qnxEnvironmentItems() const
|
|
||||||
{
|
|
||||||
Utils::EnvironmentItems envList;
|
|
||||||
envList.push_back(EnvironmentItem(QNXConfiguration, m_qnxConfiguration.path()));
|
|
||||||
envList.push_back(EnvironmentItem(QNXTarget, m_qnxTarget.path()));
|
|
||||||
envList.push_back(EnvironmentItem(QNXHost, m_qnxHost.path()));
|
|
||||||
|
|
||||||
return envList;
|
|
||||||
}
|
|
||||||
|
|
||||||
const QnxConfiguration::Target *QnxConfiguration::findTargetByDebuggerPath(
|
|
||||||
const FilePath &path) const
|
|
||||||
{
|
|
||||||
const auto it = std::find_if(m_targets.begin(), m_targets.end(),
|
|
||||||
[path](const Target &target) { return target.m_debuggerPath == path; });
|
|
||||||
return it == m_targets.end() ? nullptr : &(*it);
|
|
||||||
}
|
|
||||||
|
|
||||||
void QnxConfiguration::updateTargets()
|
|
||||||
{
|
|
||||||
m_targets.clear();
|
|
||||||
const QList<QnxTarget> targets = QnxUtils::findTargets(m_qnxTarget);
|
|
||||||
for (const QnxTarget &target : targets)
|
|
||||||
m_targets.append(Target(target.m_abi, target.m_path));
|
|
||||||
}
|
|
||||||
|
|
||||||
void QnxConfiguration::assignDebuggersToTargets()
|
|
||||||
{
|
|
||||||
const FilePath hostUsrBinDir = m_qnxHost.pathAppended("usr/bin");
|
|
||||||
QString pattern = "nto*-gdb";
|
|
||||||
if (m_qnxHost.osType() == Utils::OsTypeWindows)
|
|
||||||
pattern += ".exe";
|
|
||||||
|
|
||||||
const FilePaths debuggerNames = hostUsrBinDir.dirEntries({{pattern}, QDir::Files});
|
|
||||||
Environment sysEnv = m_qnxHost.deviceEnvironment();
|
|
||||||
sysEnv.modify(qnxEnvironmentItems());
|
|
||||||
|
|
||||||
for (const FilePath &debuggerPath : debuggerNames) {
|
|
||||||
DebuggerItem item;
|
|
||||||
item.setCommand(debuggerPath);
|
|
||||||
item.reinitializeFromFile(nullptr, &sysEnv);
|
|
||||||
bool found = false;
|
|
||||||
for (const Abi &abi : item.abis()) {
|
|
||||||
for (Target &target : m_targets) {
|
|
||||||
if (target.m_abi.isCompatibleWith(abi)) {
|
|
||||||
found = true;
|
|
||||||
|
|
||||||
if (target.m_debuggerPath.isEmpty()) {
|
|
||||||
target.m_debuggerPath = debuggerPath;
|
|
||||||
} else {
|
|
||||||
qWarning() << debuggerPath << "has the same ABI as" << target.m_debuggerPath
|
|
||||||
<< "... discarded";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!found)
|
|
||||||
qWarning() << "No target found for" << debuggerPath.toUserOutput() << "... discarded";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
QString QnxConfiguration::Target::shortDescription() const
|
|
||||||
{
|
|
||||||
return QnxUtils::cpuDirShortDescription(cpuDir());
|
|
||||||
}
|
|
||||||
|
|
||||||
QString QnxConfiguration::Target::cpuDir() const
|
|
||||||
{
|
|
||||||
return m_path.fileName();
|
|
||||||
}
|
|
||||||
|
|
||||||
} // Qnx::Internal
|
|
@@ -1,114 +0,0 @@
|
|||||||
// Copyright (C) 2016 BlackBerry Limited. All rights reserved.
|
|
||||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "qnxconstants.h"
|
|
||||||
#include "qnxversionnumber.h"
|
|
||||||
|
|
||||||
#include <utils/fileutils.h>
|
|
||||||
#include <utils/environment.h>
|
|
||||||
|
|
||||||
#include <projectexplorer/abi.h>
|
|
||||||
|
|
||||||
#include <debugger/debuggeritemmanager.h>
|
|
||||||
|
|
||||||
#include <QVariant>
|
|
||||||
|
|
||||||
namespace ProjectExplorer
|
|
||||||
{
|
|
||||||
class Kit;
|
|
||||||
class ToolChain;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace Qnx::Internal {
|
|
||||||
|
|
||||||
class QnxToolChain;
|
|
||||||
class QnxQtVersion;
|
|
||||||
|
|
||||||
class QnxConfiguration
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
QnxConfiguration();
|
|
||||||
QnxConfiguration(const Utils::FilePath &sdpEnvFile);
|
|
||||||
QnxConfiguration(const QVariantMap &data);
|
|
||||||
|
|
||||||
Utils::FilePath envFile() const;
|
|
||||||
Utils::FilePath qnxTarget() const;
|
|
||||||
Utils::FilePath qnxHost() const;
|
|
||||||
Utils::FilePath qccCompilerPath() const;
|
|
||||||
Utils::EnvironmentItems qnxEnv() const;
|
|
||||||
QnxVersionNumber version() const;
|
|
||||||
QVariantMap toMap() const;
|
|
||||||
|
|
||||||
bool isValid() const;
|
|
||||||
|
|
||||||
QString displayName() const;
|
|
||||||
bool activate();
|
|
||||||
void deactivate();
|
|
||||||
bool isActive() const;
|
|
||||||
Utils::FilePath sdpPath() const;
|
|
||||||
|
|
||||||
QList<ProjectExplorer::ToolChain *> autoDetect(
|
|
||||||
const QList<ProjectExplorer::ToolChain *> &alreadyKnown);
|
|
||||||
|
|
||||||
private:
|
|
||||||
QList<ProjectExplorer::ToolChain *> findToolChain(
|
|
||||||
const QList<ProjectExplorer::ToolChain *> &alreadyKnown,
|
|
||||||
const ProjectExplorer::Abi &abi);
|
|
||||||
|
|
||||||
QString validationErrorMessage() const;
|
|
||||||
|
|
||||||
void setVersion(const QnxVersionNumber& version);
|
|
||||||
|
|
||||||
void readInformation();
|
|
||||||
|
|
||||||
void setDefaultConfiguration(const Utils::FilePath &envScript);
|
|
||||||
|
|
||||||
Utils::EnvironmentItems qnxEnvironmentItems() const;
|
|
||||||
|
|
||||||
QString m_configName;
|
|
||||||
|
|
||||||
Utils::FilePath m_envFile;
|
|
||||||
Utils::FilePath m_qnxConfiguration;
|
|
||||||
Utils::FilePath m_qnxTarget;
|
|
||||||
Utils::FilePath m_qnxHost;
|
|
||||||
Utils::FilePath m_qccCompiler;
|
|
||||||
Utils::EnvironmentItems m_qnxEnv;
|
|
||||||
QnxVersionNumber m_version;
|
|
||||||
|
|
||||||
class Target
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
Target(const ProjectExplorer::Abi &abi, const Utils::FilePath &path)
|
|
||||||
: m_abi(abi), m_path(path)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
QString shortDescription() const;
|
|
||||||
QString cpuDir() const;
|
|
||||||
|
|
||||||
ProjectExplorer::Abi m_abi;
|
|
||||||
Utils::FilePath m_path;
|
|
||||||
Utils::FilePath m_debuggerPath;
|
|
||||||
};
|
|
||||||
|
|
||||||
QList<Target> m_targets;
|
|
||||||
|
|
||||||
QnxQtVersion *qnxQtVersion(const Target &target) const;
|
|
||||||
|
|
||||||
void createTools(const Target &target);
|
|
||||||
QVariant createDebugger(const Target &target);
|
|
||||||
|
|
||||||
using QnxToolChainMap = std::map<const char*, QnxToolChain*>;
|
|
||||||
|
|
||||||
QnxToolChainMap createToolChain(const Target &target);
|
|
||||||
void createKit(const Target &target, const QnxToolChainMap &toolChain, const QVariant &debugger);
|
|
||||||
|
|
||||||
const Target *findTargetByDebuggerPath(const Utils::FilePath &path) const;
|
|
||||||
|
|
||||||
void updateTargets();
|
|
||||||
void assignDebuggersToTargets();
|
|
||||||
};
|
|
||||||
|
|
||||||
} // Qnx::Internal
|
|
@@ -1,124 +0,0 @@
|
|||||||
// Copyright (C) 2016 BlackBerry Limited. All rights reserved.
|
|
||||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
|
||||||
|
|
||||||
#include "qnxconfigurationmanager.h"
|
|
||||||
|
|
||||||
#include "qnxconfiguration.h"
|
|
||||||
|
|
||||||
#include <coreplugin/icore.h>
|
|
||||||
|
|
||||||
#include <utils/persistentsettings.h>
|
|
||||||
#include <utils/qtcassert.h>
|
|
||||||
|
|
||||||
using namespace Utils;
|
|
||||||
|
|
||||||
namespace Qnx::Internal {
|
|
||||||
|
|
||||||
const QLatin1String QNXConfigDataKey("QNXConfiguration.");
|
|
||||||
const QLatin1String QNXConfigCountKey("QNXConfiguration.Count");
|
|
||||||
const QLatin1String QNXConfigsFileVersionKey("Version");
|
|
||||||
|
|
||||||
static FilePath qnxConfigSettingsFileName()
|
|
||||||
{
|
|
||||||
return Core::ICore::userResourcePath("qnx/qnxconfigurations.xml");
|
|
||||||
}
|
|
||||||
|
|
||||||
static QnxConfigurationManager *m_instance = nullptr;
|
|
||||||
|
|
||||||
QnxConfigurationManager::QnxConfigurationManager()
|
|
||||||
{
|
|
||||||
m_instance = this;
|
|
||||||
m_writer = new PersistentSettingsWriter(qnxConfigSettingsFileName(), "QnxConfigurations");
|
|
||||||
connect(Core::ICore::instance(), &Core::ICore::saveSettingsRequested,
|
|
||||||
this, &QnxConfigurationManager::saveConfigs);
|
|
||||||
}
|
|
||||||
|
|
||||||
QnxConfigurationManager *QnxConfigurationManager::instance()
|
|
||||||
{
|
|
||||||
return m_instance;
|
|
||||||
}
|
|
||||||
|
|
||||||
QnxConfigurationManager::~QnxConfigurationManager()
|
|
||||||
{
|
|
||||||
m_instance = nullptr;
|
|
||||||
qDeleteAll(m_configurations);
|
|
||||||
delete m_writer;
|
|
||||||
}
|
|
||||||
|
|
||||||
QList<QnxConfiguration *> QnxConfigurationManager::configurations() const
|
|
||||||
{
|
|
||||||
return m_configurations;
|
|
||||||
}
|
|
||||||
|
|
||||||
void QnxConfigurationManager::removeConfiguration(QnxConfiguration *config)
|
|
||||||
{
|
|
||||||
if (m_configurations.removeAll(config)) {
|
|
||||||
delete config;
|
|
||||||
emit configurationsListUpdated();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool QnxConfigurationManager::addConfiguration(QnxConfiguration *config)
|
|
||||||
{
|
|
||||||
if (!config || !config->isValid())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
for (QnxConfiguration *c : std::as_const(m_configurations)) {
|
|
||||||
if (c->envFile() == config->envFile())
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_configurations.append(config);
|
|
||||||
emit configurationsListUpdated();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
QnxConfiguration *QnxConfigurationManager::configurationFromEnvFile(const FilePath &envFile) const
|
|
||||||
{
|
|
||||||
for (QnxConfiguration *c : m_configurations) {
|
|
||||||
if (c->envFile() == envFile)
|
|
||||||
return c;
|
|
||||||
}
|
|
||||||
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void QnxConfigurationManager::saveConfigs()
|
|
||||||
{
|
|
||||||
QTC_ASSERT(m_writer, return);
|
|
||||||
QVariantMap data;
|
|
||||||
data.insert(QLatin1String(QNXConfigsFileVersionKey), 1);
|
|
||||||
int count = 0;
|
|
||||||
for (QnxConfiguration *config : std::as_const(m_configurations)) {
|
|
||||||
QVariantMap tmp = config->toMap();
|
|
||||||
if (tmp.isEmpty())
|
|
||||||
continue;
|
|
||||||
|
|
||||||
data.insert(QNXConfigDataKey + QString::number(count), tmp);
|
|
||||||
++count;
|
|
||||||
}
|
|
||||||
|
|
||||||
data.insert(QLatin1String(QNXConfigCountKey), count);
|
|
||||||
m_writer->save(data, Core::ICore::dialogParent());
|
|
||||||
}
|
|
||||||
|
|
||||||
void QnxConfigurationManager::restoreConfigurations()
|
|
||||||
{
|
|
||||||
PersistentSettingsReader reader;
|
|
||||||
if (!reader.load(qnxConfigSettingsFileName()))
|
|
||||||
return;
|
|
||||||
|
|
||||||
QVariantMap data = reader.restoreValues();
|
|
||||||
int count = data.value(QNXConfigCountKey, 0).toInt();
|
|
||||||
for (int i = 0; i < count; ++i) {
|
|
||||||
const QString key = QNXConfigDataKey + QString::number(i);
|
|
||||||
if (!data.contains(key))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
const QVariantMap dMap = data.value(key).toMap();
|
|
||||||
auto configuration = new QnxConfiguration(dMap);
|
|
||||||
addConfiguration(configuration);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} // Qnx::Internal
|
|
@@ -1,41 +0,0 @@
|
|||||||
// Copyright (C) 2016 BlackBerry Limited. All rights reserved.
|
|
||||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <utils/fileutils.h>
|
|
||||||
|
|
||||||
namespace Utils { class PersistentSettingsWriter; }
|
|
||||||
|
|
||||||
namespace Qnx::Internal {
|
|
||||||
|
|
||||||
class QnxConfiguration;
|
|
||||||
class QnxPlugin;
|
|
||||||
|
|
||||||
class QnxConfigurationManager: public QObject
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
public:
|
|
||||||
QnxConfigurationManager();
|
|
||||||
~QnxConfigurationManager() override;
|
|
||||||
|
|
||||||
void restoreConfigurations();
|
|
||||||
|
|
||||||
static QnxConfigurationManager *instance();
|
|
||||||
QList<QnxConfiguration*> configurations() const;
|
|
||||||
void removeConfiguration(QnxConfiguration *config);
|
|
||||||
bool addConfiguration(QnxConfiguration *config);
|
|
||||||
QnxConfiguration* configurationFromEnvFile(const Utils::FilePath &envFile) const;
|
|
||||||
|
|
||||||
protected slots:
|
|
||||||
void saveConfigs();
|
|
||||||
|
|
||||||
signals:
|
|
||||||
void configurationsListUpdated();
|
|
||||||
|
|
||||||
private:
|
|
||||||
QList<QnxConfiguration*> m_configurations;
|
|
||||||
Utils::PersistentSettingsWriter *m_writer;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // Qnx::Internal
|
|
@@ -2,7 +2,6 @@
|
|||||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
||||||
|
|
||||||
#include "qnxanalyzesupport.h"
|
#include "qnxanalyzesupport.h"
|
||||||
#include "qnxconfigurationmanager.h"
|
|
||||||
#include "qnxconstants.h"
|
#include "qnxconstants.h"
|
||||||
#include "qnxdebugsupport.h"
|
#include "qnxdebugsupport.h"
|
||||||
#include "qnxdevice.h"
|
#include "qnxdevice.h"
|
||||||
@@ -80,7 +79,7 @@ public:
|
|||||||
QAction *m_debugSeparator = nullptr;
|
QAction *m_debugSeparator = nullptr;
|
||||||
QAction m_attachToQnxApplication{Tr::tr("Attach to remote QNX application..."), nullptr};
|
QAction m_attachToQnxApplication{Tr::tr("Attach to remote QNX application..."), nullptr};
|
||||||
|
|
||||||
QnxConfigurationManager configurationManager;
|
QnxSettingsPage settingsPage;
|
||||||
QnxQtVersionFactory qtVersionFactory;
|
QnxQtVersionFactory qtVersionFactory;
|
||||||
QnxDeviceFactory deviceFactory;
|
QnxDeviceFactory deviceFactory;
|
||||||
QnxDeployConfigurationFactory deployConfigFactory;
|
QnxDeployConfigurationFactory deployConfigFactory;
|
||||||
@@ -88,7 +87,6 @@ public:
|
|||||||
Constants::QNX_DIRECT_UPLOAD_STEP_ID};
|
Constants::QNX_DIRECT_UPLOAD_STEP_ID};
|
||||||
QnxDeployStepFactory makeInstallStepFactory{RemoteLinux::Constants::MakeInstallStepId};
|
QnxDeployStepFactory makeInstallStepFactory{RemoteLinux::Constants::MakeInstallStepId};
|
||||||
QnxRunConfigurationFactory runConfigFactory;
|
QnxRunConfigurationFactory runConfigFactory;
|
||||||
QnxSettingsPage settingsPage;
|
|
||||||
QnxToolChainFactory toolChainFactory;
|
QnxToolChainFactory toolChainFactory;
|
||||||
SimpleTargetRunnerFactory runWorkerFactory{{runConfigFactory.runConfigurationId()}};
|
SimpleTargetRunnerFactory runWorkerFactory{{runConfigFactory.runConfigurationId()}};
|
||||||
QnxDebugWorkerFactory debugWorkerFactory;
|
QnxDebugWorkerFactory debugWorkerFactory;
|
||||||
@@ -112,10 +110,6 @@ private:
|
|||||||
|
|
||||||
void QnxPlugin::extensionsInitialized()
|
void QnxPlugin::extensionsInitialized()
|
||||||
{
|
{
|
||||||
// Can't do yet as not all devices are around.
|
|
||||||
connect(DeviceManager::instance(), &DeviceManager::devicesLoaded,
|
|
||||||
&d->configurationManager, &QnxConfigurationManager::restoreConfigurations);
|
|
||||||
|
|
||||||
// Attach support
|
// Attach support
|
||||||
connect(&d->m_attachToQnxApplication, &QAction::triggered, this, &showAttachToProcessDialog);
|
connect(&d->m_attachToQnxApplication, &QAction::triggered, this, &showAttachToProcessDialog);
|
||||||
|
|
||||||
|
@@ -3,29 +3,481 @@
|
|||||||
|
|
||||||
#include "qnxsettingspage.h"
|
#include "qnxsettingspage.h"
|
||||||
|
|
||||||
#include "qnxconfiguration.h"
|
#include "qnxqtversion.h"
|
||||||
#include "qnxconfigurationmanager.h"
|
#include "qnxtoolchain.h"
|
||||||
#include "qnxtr.h"
|
#include "qnxtr.h"
|
||||||
|
#include "qnxutils.h"
|
||||||
|
#include "qnxversionnumber.h"
|
||||||
|
|
||||||
#include <coreplugin/icore.h>
|
#include <coreplugin/icore.h>
|
||||||
|
|
||||||
|
#include <debugger/debuggeritem.h>
|
||||||
|
#include <debugger/debuggeritemmanager.h>
|
||||||
|
#include <debugger/debuggerkitinformation.h>
|
||||||
|
|
||||||
|
#include <projectexplorer/devicesupport/devicemanager.h>
|
||||||
#include <projectexplorer/projectexplorerconstants.h>
|
#include <projectexplorer/projectexplorerconstants.h>
|
||||||
|
#include <projectexplorer/toolchainmanager.h>
|
||||||
|
#include <projectexplorer/toolchain.h>
|
||||||
|
#include <projectexplorer/kit.h>
|
||||||
|
#include <projectexplorer/kitmanager.h>
|
||||||
|
|
||||||
|
#include <qtsupport/baseqtversion.h>
|
||||||
#include <qtsupport/qtversionmanager.h>
|
#include <qtsupport/qtversionmanager.h>
|
||||||
|
#include <qtsupport/qtkitinformation.h>
|
||||||
|
|
||||||
|
#include <qmakeprojectmanager/qmakeprojectmanagerconstants.h>
|
||||||
|
|
||||||
|
#include <utils/algorithm.h>
|
||||||
#include <utils/layoutbuilder.h>
|
#include <utils/layoutbuilder.h>
|
||||||
|
#include <utils/persistentsettings.h>
|
||||||
|
#include <utils/qtcassert.h>
|
||||||
|
|
||||||
#include <QCheckBox>
|
#include <QCheckBox>
|
||||||
#include <QComboBox>
|
#include <QComboBox>
|
||||||
|
#include <QDebug>
|
||||||
|
#include <QDomDocument>
|
||||||
#include <QGroupBox>
|
#include <QGroupBox>
|
||||||
#include <QLabel>
|
#include <QLabel>
|
||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
#include <QPushButton>
|
#include <QPushButton>
|
||||||
|
|
||||||
|
using namespace ProjectExplorer;
|
||||||
|
using namespace QtSupport;
|
||||||
using namespace Utils;
|
using namespace Utils;
|
||||||
|
using namespace Debugger;
|
||||||
|
|
||||||
namespace Qnx::Internal {
|
namespace Qnx::Internal {
|
||||||
|
|
||||||
|
const QLatin1String QNXEnvFileKey("EnvFile");
|
||||||
|
const QLatin1String QNXVersionKey("QNXVersion");
|
||||||
|
// For backward compatibility
|
||||||
|
const QLatin1String SdpEnvFileKey("NDKEnvFile");
|
||||||
|
|
||||||
|
const QLatin1String QNXConfiguration("QNX_CONFIGURATION");
|
||||||
|
const QLatin1String QNXTarget("QNX_TARGET");
|
||||||
|
const QLatin1String QNXHost("QNX_HOST");
|
||||||
|
|
||||||
|
const QLatin1String QNXConfigDataKey("QNXConfiguration.");
|
||||||
|
const QLatin1String QNXConfigCountKey("QNXConfiguration.Count");
|
||||||
|
const QLatin1String QNXConfigsFileVersionKey("Version");
|
||||||
|
|
||||||
|
static FilePath qnxConfigSettingsFileName()
|
||||||
|
{
|
||||||
|
return Core::ICore::userResourcePath("qnx/qnxconfigurations.xml");
|
||||||
|
}
|
||||||
|
|
||||||
|
class QnxConfiguration
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
QnxConfiguration() = default;
|
||||||
|
explicit QnxConfiguration(const FilePath &envFile) { m_envFile = envFile; }
|
||||||
|
|
||||||
|
void fromMap(const QVariantMap &data)
|
||||||
|
{
|
||||||
|
QString envFilePath = data.value(QNXEnvFileKey).toString();
|
||||||
|
if (envFilePath.isEmpty())
|
||||||
|
envFilePath = data.value(SdpEnvFileKey).toString();
|
||||||
|
|
||||||
|
m_version = QnxVersionNumber(data.value(QNXVersionKey).toString());
|
||||||
|
m_envFile = FilePath::fromString(envFilePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariantMap toMap() const
|
||||||
|
{
|
||||||
|
QVariantMap data;
|
||||||
|
data.insert(QLatin1String(QNXEnvFileKey), m_envFile.toString());
|
||||||
|
data.insert(QLatin1String(QNXVersionKey), m_version.toString());
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isValid() const
|
||||||
|
{
|
||||||
|
return !m_qccCompiler.isEmpty() && !m_targets.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isActive() const
|
||||||
|
{
|
||||||
|
const bool hasToolChain = ToolChainManager::toolChain(Utils::equal(&ToolChain::compilerCommand,
|
||||||
|
m_qccCompiler));
|
||||||
|
const bool hasDebugger = Utils::contains(DebuggerItemManager::debuggers(), [this](const DebuggerItem &di) {
|
||||||
|
return findTargetByDebuggerPath(di.command());
|
||||||
|
});
|
||||||
|
return hasToolChain && hasDebugger;
|
||||||
|
}
|
||||||
|
|
||||||
|
void activate();
|
||||||
|
void deactivate();
|
||||||
|
|
||||||
|
void ensureContents() const;
|
||||||
|
void mutableEnsureContents();
|
||||||
|
|
||||||
|
EnvironmentItems qnxEnvironmentItems() const;
|
||||||
|
|
||||||
|
QnxQtVersion *qnxQtVersion(const QnxTarget &target) const;
|
||||||
|
|
||||||
|
void createKit(const QnxTarget &target);
|
||||||
|
QVariant createDebugger(const QnxTarget &target);
|
||||||
|
Toolchains createToolChains(const QnxTarget &target);
|
||||||
|
|
||||||
|
const QnxTarget *findTargetByDebuggerPath(const Utils::FilePath &path) const;
|
||||||
|
|
||||||
|
bool m_hasContents = false;
|
||||||
|
QString m_configName;
|
||||||
|
|
||||||
|
FilePath m_envFile;
|
||||||
|
FilePath m_qnxConfiguration;
|
||||||
|
FilePath m_qnxTarget;
|
||||||
|
FilePath m_qnxHost;
|
||||||
|
FilePath m_qccCompiler;
|
||||||
|
EnvironmentItems m_qnxEnv;
|
||||||
|
QnxVersionNumber m_version;
|
||||||
|
|
||||||
|
QList<QnxTarget> m_targets;
|
||||||
|
};
|
||||||
|
|
||||||
|
void QnxConfiguration::activate()
|
||||||
|
{
|
||||||
|
ensureContents();
|
||||||
|
|
||||||
|
if (!isValid()) {
|
||||||
|
QStringList errorStrings
|
||||||
|
= {Tr::tr("The following errors occurred while activating the QNX configuration:")};
|
||||||
|
if (m_qccCompiler.isEmpty())
|
||||||
|
errorStrings << Tr::tr("- No GCC compiler found.");
|
||||||
|
if (m_targets.isEmpty())
|
||||||
|
errorStrings << Tr::tr("- No targets found.");
|
||||||
|
const QString msg = errorStrings.join('\n');
|
||||||
|
|
||||||
|
QMessageBox::warning(Core::ICore::dialogParent(), Tr::tr("Cannot Set Up QNX Configuration"),
|
||||||
|
msg, QMessageBox::Ok);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const QnxTarget &target : std::as_const(m_targets))
|
||||||
|
createKit(target);
|
||||||
|
}
|
||||||
|
|
||||||
|
void QnxConfiguration::deactivate()
|
||||||
|
{
|
||||||
|
QTC_ASSERT(isActive(), return);
|
||||||
|
|
||||||
|
const Toolchains toolChainsToRemove =
|
||||||
|
ToolChainManager::toolchains(Utils::equal(&ToolChain::compilerCommand, m_qccCompiler));
|
||||||
|
|
||||||
|
QList<DebuggerItem> debuggersToRemove;
|
||||||
|
const QList<DebuggerItem> debuggerItems = DebuggerItemManager::debuggers();
|
||||||
|
for (const DebuggerItem &debuggerItem : debuggerItems) {
|
||||||
|
if (findTargetByDebuggerPath(debuggerItem.command()))
|
||||||
|
debuggersToRemove.append(debuggerItem);
|
||||||
|
}
|
||||||
|
|
||||||
|
const QList<Kit *> kits = KitManager::kits();
|
||||||
|
for (Kit *kit : kits) {
|
||||||
|
if (kit->isAutoDetected()
|
||||||
|
&& DeviceTypeKitAspect::deviceTypeId(kit) == Constants::QNX_QNX_OS_TYPE
|
||||||
|
&& toolChainsToRemove.contains(ToolChainKitAspect::cxxToolChain(kit))) {
|
||||||
|
KitManager::deregisterKit(kit);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (ToolChain *tc : toolChainsToRemove)
|
||||||
|
ToolChainManager::deregisterToolChain(tc);
|
||||||
|
|
||||||
|
for (const DebuggerItem &debuggerItem : std::as_const(debuggersToRemove))
|
||||||
|
DebuggerItemManager::deregisterDebugger(debuggerItem.id());
|
||||||
|
}
|
||||||
|
|
||||||
|
QnxQtVersion *QnxConfiguration::qnxQtVersion(const QnxTarget &target) const
|
||||||
|
{
|
||||||
|
const QtVersions versions = QtVersionManager::versions(
|
||||||
|
Utils::equal(&QtVersion::type, QString::fromLatin1(Constants::QNX_QNX_QT)));
|
||||||
|
for (QtVersion *version : versions) {
|
||||||
|
auto qnxQt = dynamic_cast<QnxQtVersion *>(version);
|
||||||
|
if (qnxQt && qnxQt->sdpPath() == m_envFile.parentDir()) {
|
||||||
|
const Abis abis = version->qtAbis();
|
||||||
|
for (const Abi &qtAbi : abis) {
|
||||||
|
if (qtAbi == target.m_abi && qnxQt->cpuDir() == target.cpuDir())
|
||||||
|
return qnxQt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant QnxConfiguration::createDebugger(const QnxTarget &target)
|
||||||
|
{
|
||||||
|
Environment sysEnv = m_qnxHost.deviceEnvironment();
|
||||||
|
sysEnv.modify(qnxEnvironmentItems());
|
||||||
|
|
||||||
|
Debugger::DebuggerItem debugger;
|
||||||
|
debugger.setCommand(target.m_debuggerPath);
|
||||||
|
debugger.reinitializeFromFile(nullptr, &sysEnv);
|
||||||
|
debugger.setUnexpandedDisplayName(Tr::tr("Debugger for %1 (%2)")
|
||||||
|
.arg(m_configName)
|
||||||
|
.arg(target.shortDescription()));
|
||||||
|
return Debugger::DebuggerItemManager::registerDebugger(debugger);
|
||||||
|
}
|
||||||
|
|
||||||
|
Toolchains QnxConfiguration::createToolChains(const QnxTarget &target)
|
||||||
|
{
|
||||||
|
Toolchains toolChains;
|
||||||
|
|
||||||
|
for (const Id language : {ProjectExplorer::Constants::C_LANGUAGE_ID,
|
||||||
|
ProjectExplorer::Constants::CXX_LANGUAGE_ID}) {
|
||||||
|
auto toolChain = new QnxToolChain;
|
||||||
|
toolChain->setDetection(ToolChain::AutoDetection);
|
||||||
|
toolChain->setLanguage(language);
|
||||||
|
toolChain->setTargetAbi(target.m_abi);
|
||||||
|
toolChain->setDisplayName(Tr::tr("QCC for %1 (%2)")
|
||||||
|
.arg(m_configName)
|
||||||
|
.arg(target.shortDescription()));
|
||||||
|
toolChain->setSdpPath(m_envFile.parentDir());
|
||||||
|
toolChain->setCpuDir(target.cpuDir());
|
||||||
|
toolChain->resetToolChain(m_qccCompiler);
|
||||||
|
ToolChainManager::registerToolChain(toolChain);
|
||||||
|
|
||||||
|
toolChains.append(toolChain);
|
||||||
|
}
|
||||||
|
|
||||||
|
return toolChains;
|
||||||
|
}
|
||||||
|
|
||||||
|
void QnxConfiguration::createKit(const QnxTarget &target)
|
||||||
|
{
|
||||||
|
Toolchains toolChains = createToolChains(target);
|
||||||
|
QVariant debugger = createDebugger(target);
|
||||||
|
|
||||||
|
QnxQtVersion *qnxQt = qnxQtVersion(target); // nullptr is ok.
|
||||||
|
|
||||||
|
const auto init = [&](Kit *k) {
|
||||||
|
QtKitAspect::setQtVersion(k, qnxQt);
|
||||||
|
ToolChainKitAspect::setToolChain(k, toolChains[0]);
|
||||||
|
ToolChainKitAspect::setToolChain(k, toolChains[1]);
|
||||||
|
|
||||||
|
if (debugger.isValid())
|
||||||
|
DebuggerKitAspect::setDebugger(k, debugger);
|
||||||
|
|
||||||
|
DeviceTypeKitAspect::setDeviceTypeId(k, Constants::QNX_QNX_OS_TYPE);
|
||||||
|
// TODO: Add sysroot?
|
||||||
|
|
||||||
|
k->setUnexpandedDisplayName(Tr::tr("Kit for %1 (%2)")
|
||||||
|
.arg(m_configName)
|
||||||
|
.arg(target.shortDescription()));
|
||||||
|
|
||||||
|
k->setAutoDetected(false);
|
||||||
|
k->setAutoDetectionSource(m_envFile.toString());
|
||||||
|
k->setMutable(DeviceKitAspect::id(), true);
|
||||||
|
|
||||||
|
k->setSticky(ToolChainKitAspect::id(), true);
|
||||||
|
k->setSticky(DeviceTypeKitAspect::id(), true);
|
||||||
|
k->setSticky(SysRootKitAspect::id(), true);
|
||||||
|
k->setSticky(DebuggerKitAspect::id(), true);
|
||||||
|
k->setSticky(QmakeProjectManager::Constants::KIT_INFORMATION_ID, true);
|
||||||
|
|
||||||
|
EnvironmentKitAspect::setEnvironmentChanges(k, qnxEnvironmentItems());
|
||||||
|
};
|
||||||
|
|
||||||
|
// add kit with device and qt version not sticky
|
||||||
|
KitManager::registerKit(init);
|
||||||
|
}
|
||||||
|
|
||||||
|
void QnxConfiguration::ensureContents() const
|
||||||
|
{
|
||||||
|
if (!m_hasContents)
|
||||||
|
const_cast<QnxConfiguration *>(this)->mutableEnsureContents();
|
||||||
|
}
|
||||||
|
|
||||||
|
void QnxConfiguration::mutableEnsureContents()
|
||||||
|
{
|
||||||
|
QTC_ASSERT(!m_envFile.isEmpty(), return);
|
||||||
|
m_hasContents = true;
|
||||||
|
|
||||||
|
m_qnxEnv = QnxUtils::qnxEnvironmentFromEnvFile(m_envFile);
|
||||||
|
for (const EnvironmentItem &item : std::as_const(m_qnxEnv)) {
|
||||||
|
if (item.name == QNXConfiguration)
|
||||||
|
m_qnxConfiguration = m_envFile.withNewPath(item.value).canonicalPath();
|
||||||
|
else if (item.name == QNXTarget)
|
||||||
|
m_qnxTarget = m_envFile.withNewPath(item.value).canonicalPath();
|
||||||
|
else if (item.name == QNXHost)
|
||||||
|
m_qnxHost = m_envFile.withNewPath(item.value).canonicalPath();
|
||||||
|
}
|
||||||
|
|
||||||
|
const FilePath qccPath = m_qnxHost.pathAppended("usr/bin/qcc").withExecutableSuffix();
|
||||||
|
if (qccPath.exists())
|
||||||
|
m_qccCompiler = qccPath;
|
||||||
|
|
||||||
|
// Some fallback in case the qconfig dir with .xml files is not found later.
|
||||||
|
if (m_configName.isEmpty())
|
||||||
|
m_configName = QString("%1 - %2").arg(m_qnxHost.fileName(), m_qnxTarget.fileName());
|
||||||
|
|
||||||
|
m_targets = QnxUtils::findTargets(m_qnxTarget);
|
||||||
|
|
||||||
|
// Assign debuggers.
|
||||||
|
const FilePath hostUsrBinDir = m_qnxHost.pathAppended("usr/bin");
|
||||||
|
QString pattern = "nto*-gdb";
|
||||||
|
if (m_qnxHost.osType() == Utils::OsTypeWindows)
|
||||||
|
pattern += ".exe";
|
||||||
|
|
||||||
|
const FilePaths debuggerNames = hostUsrBinDir.dirEntries({{pattern}, QDir::Files});
|
||||||
|
Environment sysEnv = m_qnxHost.deviceEnvironment();
|
||||||
|
sysEnv.modify(qnxEnvironmentItems());
|
||||||
|
|
||||||
|
for (const FilePath &debuggerPath : debuggerNames) {
|
||||||
|
DebuggerItem item;
|
||||||
|
item.setCommand(debuggerPath);
|
||||||
|
item.reinitializeFromFile(nullptr, &sysEnv);
|
||||||
|
bool found = false;
|
||||||
|
for (const Abi &abi : item.abis()) {
|
||||||
|
for (QnxTarget &target : m_targets) {
|
||||||
|
if (target.m_abi.isCompatibleWith(abi)) {
|
||||||
|
found = true;
|
||||||
|
|
||||||
|
if (target.m_debuggerPath.isEmpty()) {
|
||||||
|
target.m_debuggerPath = debuggerPath;
|
||||||
|
} else {
|
||||||
|
qWarning() << debuggerPath << "has the same ABI as" << target.m_debuggerPath
|
||||||
|
<< "... discarded";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!found)
|
||||||
|
qWarning() << "No target found for" << debuggerPath.toUserOutput() << "... discarded";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove debuggerless targets.
|
||||||
|
Utils::erase(m_targets, [](const QnxTarget &target) {
|
||||||
|
if (target.m_debuggerPath.isEmpty())
|
||||||
|
qWarning() << "No debugger found for" << target.m_path << "... discarded";
|
||||||
|
return target.m_debuggerPath.isEmpty();
|
||||||
|
});
|
||||||
|
|
||||||
|
const FilePath configPath = m_qnxConfiguration / "qconfig";
|
||||||
|
if (!configPath.isDir())
|
||||||
|
return;
|
||||||
|
|
||||||
|
configPath.iterateDirectory([this, configPath](const FilePath &sdpFile) {
|
||||||
|
QFile xmlFile(sdpFile.toFSPathString());
|
||||||
|
if (!xmlFile.open(QIODevice::ReadOnly))
|
||||||
|
return IterationPolicy::Continue;
|
||||||
|
|
||||||
|
QDomDocument doc;
|
||||||
|
if (!doc.setContent(&xmlFile)) // Skip error message
|
||||||
|
return IterationPolicy::Continue;
|
||||||
|
|
||||||
|
QDomElement docElt = doc.documentElement();
|
||||||
|
if (docElt.tagName() != QLatin1String("qnxSystemDefinition"))
|
||||||
|
return IterationPolicy::Continue;
|
||||||
|
|
||||||
|
QDomElement childElt = docElt.firstChildElement(QLatin1String("installation"));
|
||||||
|
// The file contains only one installation node
|
||||||
|
if (childElt.isNull()) // The file contains only one base node
|
||||||
|
return IterationPolicy::Continue;
|
||||||
|
|
||||||
|
FilePath host = configPath.withNewPath(
|
||||||
|
childElt.firstChildElement(QLatin1String("host")).text()).canonicalPath();
|
||||||
|
if (m_qnxHost != host)
|
||||||
|
return IterationPolicy::Continue;
|
||||||
|
|
||||||
|
FilePath target = configPath.withNewPath(
|
||||||
|
childElt.firstChildElement(QLatin1String("target")).text()).canonicalPath();
|
||||||
|
if (m_qnxTarget != target)
|
||||||
|
return IterationPolicy::Continue;
|
||||||
|
|
||||||
|
m_configName = childElt.firstChildElement(QLatin1String("name")).text();
|
||||||
|
QString version = childElt.firstChildElement(QLatin1String("version")).text();
|
||||||
|
m_version = QnxVersionNumber(version);
|
||||||
|
return IterationPolicy::Stop;
|
||||||
|
}, {{"*.xml"}, QDir::Files});
|
||||||
|
}
|
||||||
|
|
||||||
|
EnvironmentItems QnxConfiguration::qnxEnvironmentItems() const
|
||||||
|
{
|
||||||
|
ensureContents();
|
||||||
|
return {
|
||||||
|
{QNXConfiguration, m_qnxConfiguration.path()},
|
||||||
|
{QNXTarget, m_qnxTarget.path()},
|
||||||
|
{QNXHost, m_qnxHost.path()}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const QnxTarget *QnxConfiguration::findTargetByDebuggerPath(
|
||||||
|
const FilePath &path) const
|
||||||
|
{
|
||||||
|
const auto it = std::find_if(m_targets.begin(), m_targets.end(),
|
||||||
|
[path](const QnxTarget &target) { return target.m_debuggerPath == path; });
|
||||||
|
return it == m_targets.end() ? nullptr : &(*it);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// QnxSettingsPagePrivate
|
||||||
|
|
||||||
|
class QnxSettingsPagePrivate : public QObject
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
QnxSettingsPagePrivate()
|
||||||
|
{
|
||||||
|
connect(Core::ICore::instance(), &Core::ICore::saveSettingsRequested,
|
||||||
|
this, &QnxSettingsPagePrivate::saveConfigs);
|
||||||
|
// Can't do yet as not all devices are around.
|
||||||
|
connect(DeviceManager::instance(), &DeviceManager::devicesLoaded,
|
||||||
|
this, &QnxSettingsPagePrivate::restoreConfigurations);
|
||||||
|
}
|
||||||
|
|
||||||
|
void saveConfigs()
|
||||||
|
{
|
||||||
|
QVariantMap data;
|
||||||
|
data.insert(QLatin1String(QNXConfigsFileVersionKey), 1);
|
||||||
|
int count = 0;
|
||||||
|
for (const QnxConfiguration &config : std::as_const(m_configurations)) {
|
||||||
|
QVariantMap tmp = config.toMap();
|
||||||
|
if (tmp.isEmpty())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
data.insert(QNXConfigDataKey + QString::number(count), tmp);
|
||||||
|
++count;
|
||||||
|
}
|
||||||
|
|
||||||
|
data.insert(QLatin1String(QNXConfigCountKey), count);
|
||||||
|
m_writer.save(data, Core::ICore::dialogParent());
|
||||||
|
}
|
||||||
|
|
||||||
|
void restoreConfigurations()
|
||||||
|
{
|
||||||
|
PersistentSettingsReader reader;
|
||||||
|
if (!reader.load(qnxConfigSettingsFileName()))
|
||||||
|
return;
|
||||||
|
|
||||||
|
QVariantMap data = reader.restoreValues();
|
||||||
|
int count = data.value(QNXConfigCountKey, 0).toInt();
|
||||||
|
for (int i = 0; i < count; ++i) {
|
||||||
|
const QString key = QNXConfigDataKey + QString::number(i);
|
||||||
|
if (!data.contains(key))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
QnxConfiguration config;
|
||||||
|
config.fromMap(data.value(key).toMap());
|
||||||
|
m_configurations[config.m_envFile] = config;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QnxConfiguration *configurationFromEnvFile(const FilePath &envFile)
|
||||||
|
{
|
||||||
|
auto it = m_configurations.find(envFile);
|
||||||
|
return it == m_configurations.end() ? nullptr : &*it;
|
||||||
|
}
|
||||||
|
|
||||||
|
QHash<FilePath, QnxConfiguration> m_configurations;
|
||||||
|
PersistentSettingsWriter m_writer{qnxConfigSettingsFileName(), "QnxConfigurations"};
|
||||||
|
};
|
||||||
|
|
||||||
|
static QnxSettingsPagePrivate *dd = nullptr;
|
||||||
|
|
||||||
|
|
||||||
|
// QnxSettingsWidget
|
||||||
|
|
||||||
class QnxSettingsWidget final : public Core::IOptionsPageWidget
|
class QnxSettingsWidget final : public Core::IOptionsPageWidget
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -42,10 +494,10 @@ public:
|
|||||||
public:
|
public:
|
||||||
bool operator ==(const ConfigState &cs) const
|
bool operator ==(const ConfigState &cs) const
|
||||||
{
|
{
|
||||||
return config == cs.config && state == cs.state;
|
return envFile == cs.envFile && state == cs.state;
|
||||||
}
|
}
|
||||||
|
|
||||||
QnxConfiguration *config;
|
FilePath envFile;
|
||||||
State state;
|
State state;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -57,7 +509,7 @@ public:
|
|||||||
void updateInformation();
|
void updateInformation();
|
||||||
void populateConfigsCombo();
|
void populateConfigsCombo();
|
||||||
|
|
||||||
void setConfigState(QnxConfiguration *config, State state);
|
void setConfigState(const FilePath &envFile, State state);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QComboBox *m_configsCombo = new QComboBox;
|
QComboBox *m_configsCombo = new QComboBox;
|
||||||
@@ -67,7 +519,6 @@ private:
|
|||||||
QLabel *m_configHost = new QLabel;
|
QLabel *m_configHost = new QLabel;
|
||||||
QLabel *m_configTarget = new QLabel;
|
QLabel *m_configTarget = new QLabel;
|
||||||
|
|
||||||
QnxConfigurationManager *m_qnxConfigManager = QnxConfigurationManager::instance();
|
|
||||||
QList<ConfigState> m_changedConfigs;
|
QList<ConfigState> m_changedConfigs;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -101,6 +552,7 @@ QnxSettingsWidget::QnxSettingsWidget()
|
|||||||
}.attachTo(this);
|
}.attachTo(this);
|
||||||
|
|
||||||
populateConfigsCombo();
|
populateConfigsCombo();
|
||||||
|
|
||||||
connect(addButton, &QAbstractButton::clicked,
|
connect(addButton, &QAbstractButton::clicked,
|
||||||
this, &QnxSettingsWidget::addConfiguration);
|
this, &QnxSettingsWidget::addConfiguration);
|
||||||
connect(removeButton, &QAbstractButton::clicked,
|
connect(removeButton, &QAbstractButton::clicked,
|
||||||
@@ -109,17 +561,14 @@ QnxSettingsWidget::QnxSettingsWidget()
|
|||||||
this, &QnxSettingsWidget::updateInformation);
|
this, &QnxSettingsWidget::updateInformation);
|
||||||
connect(m_generateKitsCheckBox, &QAbstractButton::toggled,
|
connect(m_generateKitsCheckBox, &QAbstractButton::toggled,
|
||||||
this, &QnxSettingsWidget::generateKits);
|
this, &QnxSettingsWidget::generateKits);
|
||||||
connect(m_qnxConfigManager, &QnxConfigurationManager::configurationsListUpdated,
|
connect(QtVersionManager::instance(), &QtVersionManager::qtVersionsChanged,
|
||||||
this, &QnxSettingsWidget::populateConfigsCombo);
|
|
||||||
connect(QtSupport::QtVersionManager::instance(),
|
|
||||||
&QtSupport::QtVersionManager::qtVersionsChanged,
|
|
||||||
this, &QnxSettingsWidget::updateInformation);
|
this, &QnxSettingsWidget::updateInformation);
|
||||||
}
|
}
|
||||||
|
|
||||||
void QnxSettingsWidget::addConfiguration()
|
void QnxSettingsWidget::addConfiguration()
|
||||||
{
|
{
|
||||||
QString filter;
|
QString filter;
|
||||||
if (Utils::HostOsInfo::isWindowsHost())
|
if (HostOsInfo::isWindowsHost())
|
||||||
filter = "*.bat file";
|
filter = "*.bat file";
|
||||||
else
|
else
|
||||||
filter = "*.sh file";
|
filter = "*.sh file";
|
||||||
@@ -129,82 +578,88 @@ void QnxSettingsWidget::addConfiguration()
|
|||||||
if (envFile.isEmpty())
|
if (envFile.isEmpty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
QnxConfiguration *config = new QnxConfiguration(envFile);
|
if (dd->m_configurations.contains(envFile)) {
|
||||||
if (m_qnxConfigManager->configurations().contains(config) || !config->isValid()) {
|
|
||||||
QMessageBox::warning(Core::ICore::dialogParent(),
|
QMessageBox::warning(Core::ICore::dialogParent(),
|
||||||
Tr::tr("Warning"),
|
Tr::tr("Warning"),
|
||||||
Tr::tr("Configuration already exists or is invalid."));
|
Tr::tr("Configuration already exists."));
|
||||||
delete config;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
setConfigState(config, Added);
|
// Temporary to be able to check
|
||||||
m_configsCombo->addItem(config->displayName(),
|
QnxConfiguration config(envFile);
|
||||||
QVariant::fromValue(static_cast<void*>(config)));
|
config.ensureContents();
|
||||||
|
if (!config.isValid()) {
|
||||||
|
QMessageBox::warning(Core::ICore::dialogParent(),
|
||||||
|
Tr::tr("Warning"),
|
||||||
|
Tr::tr("Configuration is not valid."));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
setConfigState(envFile, Added);
|
||||||
|
m_configsCombo->addItem(config.m_configName, QVariant::fromValue(envFile));
|
||||||
}
|
}
|
||||||
|
|
||||||
void QnxSettingsWidget::removeConfiguration()
|
void QnxSettingsWidget::removeConfiguration()
|
||||||
{
|
{
|
||||||
const int currentIndex = m_configsCombo->currentIndex();
|
const FilePath envFile = m_configsCombo->currentData().value<FilePath>();
|
||||||
auto config = static_cast<QnxConfiguration*>(
|
QTC_ASSERT(!envFile.isEmpty(), return);
|
||||||
m_configsCombo->itemData(currentIndex).value<void*>());
|
|
||||||
|
|
||||||
if (!config)
|
QnxConfiguration *config = dd->configurationFromEnvFile(envFile);
|
||||||
return;
|
QTC_ASSERT(config, return);
|
||||||
|
|
||||||
|
config->ensureContents();
|
||||||
|
|
||||||
QMessageBox::StandardButton button =
|
QMessageBox::StandardButton button =
|
||||||
QMessageBox::question(Core::ICore::dialogParent(),
|
QMessageBox::question(Core::ICore::dialogParent(),
|
||||||
Tr::tr("Remove QNX Configuration"),
|
Tr::tr("Remove QNX Configuration"),
|
||||||
Tr::tr("Are you sure you want to remove:\n %1?").arg(config->displayName()),
|
Tr::tr("Are you sure you want to remove:\n %1?")
|
||||||
|
.arg(config->m_configName),
|
||||||
QMessageBox::Yes | QMessageBox::No);
|
QMessageBox::Yes | QMessageBox::No);
|
||||||
|
|
||||||
if (button == QMessageBox::Yes) {
|
if (button == QMessageBox::Yes) {
|
||||||
setConfigState(config, Removed);
|
setConfigState(envFile, Removed);
|
||||||
m_configsCombo->removeItem(currentIndex);
|
m_configsCombo->removeItem(m_configsCombo->currentIndex());
|
||||||
|
updateInformation();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void QnxSettingsWidget::generateKits(bool checked)
|
void QnxSettingsWidget::generateKits(bool checked)
|
||||||
{
|
{
|
||||||
const int currentIndex = m_configsCombo->currentIndex();
|
const FilePath envFile = m_configsCombo->currentData().value<FilePath>();
|
||||||
auto config = static_cast<QnxConfiguration*>(
|
setConfigState(envFile, checked ? Activated : Deactivated);
|
||||||
m_configsCombo->itemData(currentIndex).value<void*>());
|
|
||||||
if (!config)
|
|
||||||
return;
|
|
||||||
|
|
||||||
setConfigState(config, checked ? Activated : Deactivated);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void QnxSettingsWidget::updateInformation()
|
void QnxSettingsWidget::updateInformation()
|
||||||
{
|
{
|
||||||
const int currentIndex = m_configsCombo->currentIndex();
|
const FilePath envFile = m_configsCombo->currentData().value<FilePath>();
|
||||||
|
|
||||||
auto config = static_cast<QnxConfiguration*>(
|
if (QnxConfiguration *config = dd->configurationFromEnvFile(envFile)) {
|
||||||
m_configsCombo->itemData(currentIndex).value<void*>());
|
config->ensureContents();
|
||||||
|
m_generateKitsCheckBox->setEnabled(config->isValid());
|
||||||
// update the checkbox
|
m_generateKitsCheckBox->setChecked(config->isActive());
|
||||||
m_generateKitsCheckBox->setEnabled(config ? config->isValid() : false);
|
m_configName->setText(config->m_configName);
|
||||||
m_generateKitsCheckBox->setChecked(config ? config->isActive() : false);
|
m_configVersion->setText(config->m_version.toString());
|
||||||
|
m_configHost->setText(config->m_qnxHost.toString());
|
||||||
// update information
|
m_configTarget->setText(config->m_qnxTarget.toString());
|
||||||
m_configName->setText(config ? config->displayName() : QString());
|
} else {
|
||||||
m_configVersion->setText(config ? config->version().toString() : QString());
|
m_generateKitsCheckBox->setEnabled(false);
|
||||||
m_configHost->setText(config ? config->qnxHost().toString() : QString());
|
m_generateKitsCheckBox->setChecked(false);
|
||||||
m_configTarget->setText(config ? config->qnxTarget().toString() : QString());
|
m_configName->setText({});
|
||||||
|
m_configVersion->setText({});
|
||||||
|
m_configHost->setText({});
|
||||||
|
m_configTarget->setText({});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void QnxSettingsWidget::populateConfigsCombo()
|
void QnxSettingsWidget::populateConfigsCombo()
|
||||||
{
|
{
|
||||||
m_configsCombo->clear();
|
m_configsCombo->clear();
|
||||||
const QList<QnxConfiguration *> configList = m_qnxConfigManager->configurations();
|
for (const QnxConfiguration &config : std::as_const(dd->m_configurations))
|
||||||
for (QnxConfiguration *config : configList) {
|
m_configsCombo->addItem(config.m_configName, QVariant::fromValue(config.m_envFile));
|
||||||
m_configsCombo->addItem(config->displayName(),
|
|
||||||
QVariant::fromValue(static_cast<void*>(config)));
|
|
||||||
}
|
|
||||||
updateInformation();
|
updateInformation();
|
||||||
}
|
}
|
||||||
|
|
||||||
void QnxSettingsWidget::setConfigState(QnxConfiguration *config, State state)
|
void QnxSettingsWidget::setConfigState(const FilePath &envFile, State state)
|
||||||
{
|
{
|
||||||
State stateToRemove = Activated;
|
State stateToRemove = Activated;
|
||||||
switch (state) {
|
switch (state) {
|
||||||
@@ -223,45 +678,79 @@ void QnxSettingsWidget::setConfigState(QnxConfiguration *config, State state)
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (const ConfigState &configState : std::as_const(m_changedConfigs)) {
|
for (const ConfigState &configState : std::as_const(m_changedConfigs)) {
|
||||||
if (configState.config == config && configState.state == stateToRemove)
|
if (configState.envFile == envFile && configState.state == stateToRemove)
|
||||||
m_changedConfigs.removeAll(configState);
|
m_changedConfigs.removeAll(configState);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_changedConfigs.append(ConfigState{config, state});
|
m_changedConfigs.append(ConfigState{envFile, state});
|
||||||
}
|
}
|
||||||
|
|
||||||
void QnxSettingsWidget::apply()
|
void QnxSettingsWidget::apply()
|
||||||
{
|
{
|
||||||
for (const ConfigState &configState : std::as_const(m_changedConfigs)) {
|
for (const ConfigState &configState : std::as_const(m_changedConfigs)) {
|
||||||
switch (configState.state) {
|
switch (configState.state) {
|
||||||
case Activated :
|
case Activated: {
|
||||||
configState.config->activate();
|
QnxConfiguration *config = dd->configurationFromEnvFile(configState.envFile);
|
||||||
|
QTC_ASSERT(config, break);
|
||||||
|
config->activate();
|
||||||
break;
|
break;
|
||||||
case Deactivated:
|
}
|
||||||
configState.config->deactivate();
|
case Deactivated: {
|
||||||
|
QnxConfiguration *config = dd->configurationFromEnvFile(configState.envFile);
|
||||||
|
QTC_ASSERT(config, break);
|
||||||
|
config->deactivate();
|
||||||
break;
|
break;
|
||||||
case Added:
|
}
|
||||||
m_qnxConfigManager->addConfiguration(configState.config);
|
case Added: {
|
||||||
|
QnxConfiguration config(configState.envFile);
|
||||||
|
config.ensureContents();
|
||||||
|
dd->m_configurations.insert(configState.envFile, config);
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case Removed:
|
case Removed:
|
||||||
configState.config->deactivate();
|
QnxConfiguration *config = dd->configurationFromEnvFile(configState.envFile);
|
||||||
m_qnxConfigManager->removeConfiguration(configState.config);
|
QTC_ASSERT(config, break);
|
||||||
|
config->deactivate();
|
||||||
|
dd->m_configurations.remove(configState.envFile);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
m_changedConfigs.clear();
|
m_changedConfigs.clear();
|
||||||
|
populateConfigsCombo();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// QnxSettingsPage
|
// QnxSettingsPage
|
||||||
|
|
||||||
|
QList<ToolChain *> QnxSettingsPage::autoDetect(const QList<ToolChain *> &alreadyKnown)
|
||||||
|
{
|
||||||
|
QList<ToolChain *> result;
|
||||||
|
for (const QnxConfiguration &config : std::as_const(dd->m_configurations)) {
|
||||||
|
config.ensureContents();
|
||||||
|
for (const QnxTarget &target : std::as_const(config.m_targets)) {
|
||||||
|
result += Utils::filtered(alreadyKnown, [config, target](ToolChain *tc) {
|
||||||
|
return tc->typeId() == Constants::QNX_TOOLCHAIN_ID
|
||||||
|
&& tc->targetAbi() == target.m_abi
|
||||||
|
&& tc->compilerCommand() == config.m_qccCompiler;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
QnxSettingsPage::QnxSettingsPage()
|
QnxSettingsPage::QnxSettingsPage()
|
||||||
{
|
{
|
||||||
setId("DD.Qnx Configuration");
|
setId("DD.Qnx Configuration");
|
||||||
setDisplayName(Tr::tr("QNX"));
|
setDisplayName(Tr::tr("QNX"));
|
||||||
setCategory(ProjectExplorer::Constants::DEVICE_SETTINGS_CATEGORY);
|
setCategory(ProjectExplorer::Constants::DEVICE_SETTINGS_CATEGORY);
|
||||||
setWidgetCreator([] { return new QnxSettingsWidget; });
|
setWidgetCreator([] { return new QnxSettingsWidget; });
|
||||||
|
|
||||||
|
dd = new QnxSettingsPagePrivate;
|
||||||
|
}
|
||||||
|
|
||||||
|
QnxSettingsPage::~QnxSettingsPage()
|
||||||
|
{
|
||||||
|
delete dd;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // Qnx::Internal
|
} // Qnx::Internal
|
||||||
|
@@ -5,12 +5,18 @@
|
|||||||
|
|
||||||
#include <coreplugin/dialogs/ioptionspage.h>
|
#include <coreplugin/dialogs/ioptionspage.h>
|
||||||
|
|
||||||
|
namespace ProjectExplorer { class ToolChain; }
|
||||||
|
|
||||||
namespace Qnx::Internal {
|
namespace Qnx::Internal {
|
||||||
|
|
||||||
class QnxSettingsPage final : public Core::IOptionsPage
|
class QnxSettingsPage final : public Core::IOptionsPage
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
QnxSettingsPage();
|
QnxSettingsPage();
|
||||||
|
~QnxSettingsPage();
|
||||||
|
|
||||||
|
static QList<ProjectExplorer::ToolChain *> autoDetect(
|
||||||
|
const QList<ProjectExplorer::ToolChain *> &alreadyKnown);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // Qnx::Internal
|
} // Qnx::Internal
|
||||||
|
@@ -3,9 +3,8 @@
|
|||||||
|
|
||||||
#include "qnxtoolchain.h"
|
#include "qnxtoolchain.h"
|
||||||
|
|
||||||
#include "qnxconfiguration.h"
|
|
||||||
#include "qnxconfigurationmanager.h"
|
|
||||||
#include "qnxconstants.h"
|
#include "qnxconstants.h"
|
||||||
|
#include "qnxsettingspage.h"
|
||||||
#include "qnxtr.h"
|
#include "qnxtr.h"
|
||||||
#include "qnxutils.h"
|
#include "qnxutils.h"
|
||||||
|
|
||||||
@@ -222,10 +221,7 @@ Toolchains QnxToolChainFactory::autoDetect(const ToolchainDetector &detector) co
|
|||||||
if (detector.device)
|
if (detector.device)
|
||||||
return {};
|
return {};
|
||||||
|
|
||||||
Toolchains tcs;
|
Toolchains tcs = QnxSettingsPage::autoDetect(detector.alreadyKnown);
|
||||||
const auto configurations = QnxConfigurationManager::instance()->configurations();
|
|
||||||
for (QnxConfiguration *configuration : configurations)
|
|
||||||
tcs += configuration->autoDetect(detector.alreadyKnown);
|
|
||||||
return tcs;
|
return tcs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -16,6 +16,15 @@ using namespace Utils;
|
|||||||
|
|
||||||
namespace Qnx::Internal {
|
namespace Qnx::Internal {
|
||||||
|
|
||||||
|
QnxTarget::QnxTarget(const Utils::FilePath &path, const ProjectExplorer::Abi &abi) :
|
||||||
|
m_path(path), m_abi(abi)
|
||||||
|
{}
|
||||||
|
|
||||||
|
QString QnxTarget::shortDescription() const
|
||||||
|
{
|
||||||
|
return QnxUtils::cpuDirShortDescription(cpuDir());
|
||||||
|
}
|
||||||
|
|
||||||
QString QnxUtils::cpuDirFromAbi(const Abi &abi)
|
QString QnxUtils::cpuDirFromAbi(const Abi &abi)
|
||||||
{
|
{
|
||||||
if (abi.os() != Abi::OS::QnxOS)
|
if (abi.os() != Abi::OS::QnxOS)
|
||||||
|
@@ -14,12 +14,14 @@ namespace Qnx::Internal {
|
|||||||
class QnxTarget
|
class QnxTarget
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
QnxTarget(const Utils::FilePath &path, const ProjectExplorer::Abi &abi) :
|
QnxTarget(const Utils::FilePath &path, const ProjectExplorer::Abi &abi);
|
||||||
m_path(path), m_abi(abi)
|
|
||||||
{
|
QString shortDescription() const;
|
||||||
}
|
QString cpuDir() const { return m_path.fileName(); }
|
||||||
|
|
||||||
Utils::FilePath m_path;
|
Utils::FilePath m_path;
|
||||||
ProjectExplorer::Abi m_abi;
|
ProjectExplorer::Abi m_abi;
|
||||||
|
Utils::FilePath m_debuggerPath;
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace QnxUtils {
|
namespace QnxUtils {
|
||||||
|
Reference in New Issue
Block a user