forked from qt-creator/qt-creator
Qnx: Add new QccToolChain class for qcc compilers
Qcc compiler doesn't support "dumpmachine" option provided by the gcc to get a list of supported abis from the compiler, and needs to pass -Wp option when running qcc to get predefined macros and header paths. GccToolChain fails to get those information from qcc and print warning messages on the console. This patch adds new QccToolChain class and reinterprets the compiler options to detect predefined macros and header paths. It also provids list of supported abis and suggested mkspecs. Task-number: QTCREATORBUG-10116 Change-Id: Ic48d5c58c5b957f5a8536248888c9a63ca499f34 Reviewed-by: Leena Miettinen <riitta-leena.miettinen@digia.com> Reviewed-by: Tobias Hunger <tobias.hunger@digia.com>
This commit is contained in:
committed by
Tobias Hunger
parent
041421ea40
commit
78d69eb0e5
269
src/plugins/qnx/qnxtoolchain.cpp
Normal file
269
src/plugins/qnx/qnxtoolchain.cpp
Normal file
@@ -0,0 +1,269 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** Copyright (C) 2013 BlackBerry Limited. All rights reserved.
|
||||
**
|
||||
** Contact: BlackBerry (qt@blackberry.com)
|
||||
** Contact: KDAB (info@kdab.com)
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
**
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and Digia. For licensing terms and
|
||||
** conditions see http://qt.digia.com/licensing. For further information
|
||||
** use the contact form at http://qt.digia.com/contact-us.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 2.1 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 2.1 requirements
|
||||
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||
**
|
||||
** In addition, as a special exception, Digia gives you certain additional
|
||||
** rights. These rights are described in the Digia Qt LGPL Exception
|
||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "qnxtoolchain.h"
|
||||
#include "qnxconstants.h"
|
||||
#include "qnxutils.h"
|
||||
|
||||
#include "blackberryconfigurationmanager.h"
|
||||
#include "blackberryconfiguration.h"
|
||||
|
||||
#include <utils/pathchooser.h>
|
||||
|
||||
#include <QFormLayout>
|
||||
|
||||
using namespace ProjectExplorer;
|
||||
namespace Qnx {
|
||||
namespace Internal {
|
||||
|
||||
static const char CompilernNdkPath[] = "Qnx.QnxToolChain.NDKPath";
|
||||
|
||||
static const QList<Abi> qccSupportedAbis()
|
||||
{
|
||||
QList<Abi> abis;
|
||||
abis << Abi(Abi::ArmArchitecture, Abi::LinuxOS, Abi::GenericLinuxFlavor, Abi::ElfFormat, 32);
|
||||
abis << Abi(Abi::X86Architecture, Abi::LinuxOS, Abi::GenericLinuxFlavor, Abi::ElfFormat, 32);
|
||||
|
||||
return abis;
|
||||
}
|
||||
|
||||
static void setQnxEnvironment(Utils::Environment &env, const QList<Utils::EnvironmentItem> &qnxEnv)
|
||||
{
|
||||
// We only need to set QNX_HOST and QNX_TARGET needed when running qcc
|
||||
foreach (const Utils::EnvironmentItem &item, qnxEnv) {
|
||||
if (item.name == QLatin1String("QNX_HOST") ||
|
||||
item.name == QLatin1String("QNX_TARGET") )
|
||||
env.set(item.name, item.value);
|
||||
}
|
||||
}
|
||||
|
||||
QnxToolChain::QnxToolChain(ToolChain::Detection d)
|
||||
: GccToolChain(QLatin1String(Constants::QNX_TOOLCHAIN_ID), d)
|
||||
{
|
||||
}
|
||||
|
||||
QString QnxToolChain::type() const
|
||||
{
|
||||
return QLatin1String(Constants::QNX_TOOLCHAIN_ID);
|
||||
}
|
||||
|
||||
QString QnxToolChain::typeDisplayName() const
|
||||
{
|
||||
return QnxToolChainFactory::tr("QCC");
|
||||
}
|
||||
|
||||
ToolChainConfigWidget *QnxToolChain::configurationWidget()
|
||||
{
|
||||
return new QnxToolChainConfigWidget(this);
|
||||
}
|
||||
|
||||
void QnxToolChain::addToEnvironment(Utils::Environment &env) const
|
||||
{
|
||||
foreach (BlackBerryConfiguration* config, BlackBerryConfigurationManager::instance().configurations()) {
|
||||
if (config->gccCompiler() == compilerCommand()) {
|
||||
setQnxEnvironment(env, config->qnxEnv());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (env.value(QLatin1String("QNX_HOST")).isEmpty()
|
||||
|| env.value(QLatin1String("QNX_TARGET")).isEmpty())
|
||||
setQnxEnvironment(env, QnxUtils::qnxEnvironment(m_ndkPath));
|
||||
|
||||
GccToolChain::addToEnvironment(env);
|
||||
}
|
||||
|
||||
QList<Utils::FileName> QnxToolChain::suggestedMkspecList() const
|
||||
{
|
||||
QList<Utils::FileName> mkspecList;
|
||||
mkspecList << Utils::FileName::fromString(QLatin1String("qnx-armv7le-qcc"));
|
||||
mkspecList << Utils::FileName::fromString(QLatin1String("qnx-x86-qcc"));
|
||||
mkspecList << Utils::FileName::fromString(QLatin1String("blackberry-armv7le-qcc"));
|
||||
mkspecList << Utils::FileName::fromString(QLatin1String("blackberry-x86-qcc"));
|
||||
|
||||
return mkspecList;
|
||||
}
|
||||
|
||||
QVariantMap QnxToolChain::toMap() const
|
||||
{
|
||||
QVariantMap data = GccToolChain::toMap();
|
||||
data.insert(QLatin1String(CompilernNdkPath), m_ndkPath);
|
||||
return data;
|
||||
}
|
||||
|
||||
bool QnxToolChain::fromMap(const QVariantMap &data)
|
||||
{
|
||||
if (!GccToolChain::fromMap(data))
|
||||
return false;
|
||||
|
||||
m_ndkPath = data.value(QLatin1String(CompilernNdkPath)).toString();
|
||||
return true;
|
||||
}
|
||||
|
||||
QString QnxToolChain::ndkPath() const
|
||||
{
|
||||
return m_ndkPath;
|
||||
}
|
||||
|
||||
void QnxToolChain::setNdkPath(const QString &ndkPath)
|
||||
{
|
||||
m_ndkPath = ndkPath;
|
||||
}
|
||||
|
||||
// qcc doesn't support a "-dumpmachine" option to get supported abis
|
||||
QList<Abi> QnxToolChain::detectSupportedAbis() const
|
||||
{
|
||||
return qccSupportedAbis();
|
||||
}
|
||||
|
||||
// Qcc is a multi-compiler driver, and most of the gcc options can be accomplished by using the -Wp, and -Wc
|
||||
// options to pass the options directly down to the compiler
|
||||
QStringList QnxToolChain::reinterpretOptions(const QStringList &args) const
|
||||
{
|
||||
QStringList arguments;
|
||||
foreach (const QString &str, args) {
|
||||
if (str.startsWith(QLatin1String("--sysroot=")))
|
||||
continue;
|
||||
QString arg = str;
|
||||
if (arg == QLatin1String("-v")
|
||||
|| arg == QLatin1String("-dM"))
|
||||
arg.prepend(QLatin1String("-Wp,"));
|
||||
arguments << arg;
|
||||
}
|
||||
|
||||
return arguments;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// QnxToolChainFactory
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
QnxToolChainFactory::QnxToolChainFactory()
|
||||
{
|
||||
setId(Constants::QNX_TOOLCHAIN_ID);
|
||||
setDisplayName(tr("QCC"));
|
||||
}
|
||||
|
||||
bool QnxToolChainFactory::canRestore(const QVariantMap &data)
|
||||
{
|
||||
const QString id = idFromMap(data);
|
||||
return id.startsWith(QLatin1String(Constants::QNX_TOOLCHAIN_ID) + QLatin1Char(':'));
|
||||
}
|
||||
|
||||
ToolChain *QnxToolChainFactory::restore(const QVariantMap &data)
|
||||
{
|
||||
QnxToolChain *tc = new QnxToolChain(ToolChain::ManualDetection);
|
||||
if (tc->fromMap(data))
|
||||
return tc;
|
||||
|
||||
delete tc;
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool QnxToolChainFactory::canCreate()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
ToolChain *QnxToolChainFactory::create()
|
||||
{
|
||||
return new QnxToolChain(ToolChain::ManualDetection);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------
|
||||
// QnxToolChainConfigWidget
|
||||
//---------------------------------------------------------------------------------
|
||||
|
||||
QnxToolChainConfigWidget::QnxToolChainConfigWidget(QnxToolChain *tc)
|
||||
: ToolChainConfigWidget(tc)
|
||||
, m_compilerCommand(new Utils::PathChooser)
|
||||
, m_ndkPath(new Utils::PathChooser)
|
||||
, m_abiWidget(new AbiWidget)
|
||||
{
|
||||
m_compilerCommand->setExpectedKind(Utils::PathChooser::ExistingCommand);
|
||||
m_compilerCommand->setFileName(tc->compilerCommand());
|
||||
m_compilerCommand->setEnabled(!tc->isAutoDetected());
|
||||
|
||||
m_ndkPath->setExpectedKind(Utils::PathChooser::ExistingDirectory);
|
||||
m_ndkPath->setPath(tc->ndkPath());
|
||||
m_ndkPath->setEnabled(!tc->isAutoDetected());
|
||||
|
||||
m_abiWidget->setAbis(qccSupportedAbis(), tc->targetAbi());
|
||||
m_abiWidget->setEnabled(!tc->isAutoDetected());
|
||||
|
||||
m_mainLayout->addRow(tr("&Compiler path:"), m_compilerCommand);
|
||||
//: SDP refers to 'Software Development Platform'.
|
||||
m_mainLayout->addRow(tr("NDK/SDP path:"), m_ndkPath);
|
||||
m_mainLayout->addRow(tr("&ABI:"), m_abiWidget);
|
||||
|
||||
connect(m_compilerCommand, SIGNAL(changed(QString)), this, SIGNAL(dirty()));
|
||||
connect(m_ndkPath, SIGNAL(changed(QString)), this, SIGNAL(dirty()));
|
||||
connect(m_abiWidget, SIGNAL(abiChanged()), this, SIGNAL(dirty()));
|
||||
}
|
||||
|
||||
void QnxToolChainConfigWidget::applyImpl()
|
||||
{
|
||||
if (toolChain()->isAutoDetected())
|
||||
return;
|
||||
|
||||
QnxToolChain *tc = static_cast<QnxToolChain *>(toolChain());
|
||||
Q_ASSERT(tc);
|
||||
QString displayName = tc->displayName();
|
||||
tc->setCompilerCommand(m_compilerCommand->fileName());
|
||||
tc->setDisplayName(displayName); // reset display name
|
||||
tc->setNdkPath(m_ndkPath->fileName().toString());
|
||||
tc->setTargetAbi(m_abiWidget->currentAbi());
|
||||
}
|
||||
|
||||
void QnxToolChainConfigWidget::discardImpl()
|
||||
{
|
||||
// subwidgets are not yet connected!
|
||||
bool blocked = blockSignals(true);
|
||||
QnxToolChain *tc = static_cast<QnxToolChain *>(toolChain());
|
||||
m_compilerCommand->setFileName(tc->compilerCommand());
|
||||
m_ndkPath->setPath(tc->ndkPath());
|
||||
m_abiWidget->setAbis(tc->supportedAbis(), tc->targetAbi());
|
||||
if (!m_compilerCommand->path().isEmpty())
|
||||
m_abiWidget->setEnabled(true);
|
||||
blockSignals(blocked);
|
||||
}
|
||||
|
||||
bool QnxToolChainConfigWidget::isDirtyImpl() const
|
||||
{
|
||||
QnxToolChain *tc = static_cast<QnxToolChain *>(toolChain());
|
||||
Q_ASSERT(tc);
|
||||
return m_compilerCommand->fileName() != tc->compilerCommand()
|
||||
|| m_ndkPath->path() != tc->ndkPath()
|
||||
|| m_abiWidget->currentAbi() != tc->targetAbi();
|
||||
}
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Qnx
|
||||
Reference in New Issue
Block a user