diff options
author | Tobias Hunger <tobias.hunger@nokia.com> | 2011-02-01 18:36:00 +0100 |
---|---|---|
committer | Tobias Hunger <tobias.hunger@nokia.com> | 2011-02-21 18:33:23 +0100 |
commit | 8d0c47724599ad279a88e3632784be40cc4175da (patch) | |
tree | 7c4408a1d2f14f3ac5d33711fc1241ea8b4821d1 | |
parent | be31c80b02f752484e76faa215eae616a80e24e3 (diff) | |
download | qt-creator-8d0c47724599ad279a88e3632784be40cc4175da.tar.gz |
ToolChain: Refactor toolchain support
Refactor ToolChains in Qt Creator:
* Allow for several toolchains of the same type
* Be smarter wrt. guessing what kind of output a toolchain
produces. This allows us to eventually handle e.g. embedded
linux setups way better than before.
* Be smarter wrt. guessing what kind of environment a Qt version
needs.
* Improve auto-detection of toolchains a bit
* Decide on which debugger to use based on the kind of output
produced by the compiler.
* Add options page to configure toolchains
* Remove toolchain related options from the Qt version dialog
Reviewed-by: dt
112 files changed, 6440 insertions, 3629 deletions
diff --git a/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.cpp b/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.cpp index e6b6bd98a0..3f952ed74c 100644 --- a/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.cpp +++ b/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.cpp @@ -38,7 +38,7 @@ #include "cmaketarget.h" #include <projectexplorer/projectexplorerconstants.h> -#include <projectexplorer/toolchain.h> +#include <projectexplorer/toolchainmanager.h> #include <projectexplorer/buildsteplist.h> #include <utils/qtcassert.h> @@ -50,7 +50,7 @@ using namespace Internal; namespace { const char * const CMAKE_BC_ID("CMakeProjectManager.CMakeBuildConfiguration"); -const char * const MSVC_VERSION_KEY("CMakeProjectManager.CMakeBuildConfiguration.MsvcVersion"); +const char * const TOOLCHAIN_KEY("CMakeProjectManager.CMakeBuildConfiguration.ToolChain"); const char * const BUILD_DIRECTORY_KEY("CMakeProjectManager.CMakeBuildConfiguration.BuildDirectory"); } // namespace @@ -74,7 +74,7 @@ CMakeBuildConfiguration::CMakeBuildConfiguration(CMakeTarget *parent, CMakeBuild QVariantMap CMakeBuildConfiguration::toMap() const { QVariantMap map(ProjectExplorer::BuildConfiguration::toMap()); - map.insert(QLatin1String(MSVC_VERSION_KEY), m_msvcVersion); + map.insert(QLatin1String(TOOLCHAIN_KEY), m_toolChain ? m_toolChain->id() : QString()); map.insert(QLatin1String(BUILD_DIRECTORY_KEY), m_buildDirectory); return map; } @@ -84,7 +84,8 @@ bool CMakeBuildConfiguration::fromMap(const QVariantMap &map) if (!BuildConfiguration::fromMap(map)) return false; - m_msvcVersion = map.value(QLatin1String(MSVC_VERSION_KEY)).toString(); + m_toolChain = ProjectExplorer::ToolChainManager::instance()-> + findToolChain(map.value(QLatin1String(TOOLCHAIN_KEY)).toString()); m_buildDirectory = map.value(QLatin1String(BUILD_DIRECTORY_KEY), cmakeTarget()->defaultBuildDirectory()).toString(); return true; @@ -105,41 +106,6 @@ QString CMakeBuildConfiguration::buildDirectory() const return m_buildDirectory; } -ProjectExplorer::ToolChainType CMakeBuildConfiguration::toolChainType() const -{ - if (m_toolChain) - return m_toolChain->type(); - return ProjectExplorer::ToolChain_UNKNOWN; -} - -ProjectExplorer::ToolChain *CMakeBuildConfiguration::toolChain() const -{ - updateToolChain(); - return m_toolChain; -} - -void CMakeBuildConfiguration::updateToolChain() const -{ - ProjectExplorer::ToolChain *newToolChain = 0; - if (msvcVersion().isEmpty()) { -#ifdef Q_OS_WIN - newToolChain = ProjectExplorer::ToolChain::createMinGWToolChain("gcc", QString()); -#else - newToolChain = ProjectExplorer::ToolChain::createGccToolChain("gcc"); -#endif - } else { // msvc - newToolChain = ProjectExplorer::ToolChain::createMSVCToolChain(m_msvcVersion, false); - } - - if (ProjectExplorer::ToolChain::equals(newToolChain, m_toolChain)) { - delete newToolChain; - newToolChain = 0; - } else { - delete m_toolChain; - m_toolChain = newToolChain; - } -} - void CMakeBuildConfiguration::setBuildDirectory(const QString &buildDirectory) { if (m_buildDirectory == buildDirectory) @@ -149,21 +115,6 @@ void CMakeBuildConfiguration::setBuildDirectory(const QString &buildDirectory) emit environmentChanged(); } -QString CMakeBuildConfiguration::msvcVersion() const -{ - return m_msvcVersion; -} - -void CMakeBuildConfiguration::setMsvcVersion(const QString &msvcVersion) -{ - if (m_msvcVersion == msvcVersion) - return; - m_msvcVersion = msvcVersion; - updateToolChain(); - - emit msvcVersionChanged(); -} - ProjectExplorer::IOutputParser *CMakeBuildConfiguration::createOutputParser() const { if (m_toolChain) @@ -255,10 +206,10 @@ CMakeBuildConfiguration *CMakeBuildConfigurationFactory::create(ProjectExplorer: delete bc; return 0; } + bc->setToolChain(copw.toolChain()); cmtarget->addBuildConfiguration(bc); // this also makes the name unique bc->setBuildDirectory(copw.buildDirectory()); - bc->setMsvcVersion(copw.msvcVersion()); cmtarget->cmakeProject()->parseCMakeLists(); // Default to all diff --git a/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.h b/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.h index 808dbe9426..c26dcf542e 100644 --- a/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.h +++ b/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.h @@ -35,7 +35,7 @@ #define CMAKEBUILDCONFIGURATION_H #include <projectexplorer/buildconfiguration.h> -#include <projectexplorer/toolchaintype.h> +#include <projectexplorer/abi.h> namespace ProjectExplorer { class ToolChain; @@ -60,23 +60,14 @@ public: virtual QString buildDirectory() const; - ProjectExplorer::ToolChainType toolChainType() const; - ProjectExplorer::ToolChain *toolChain() const; - void setBuildDirectory(const QString &buildDirectory); - QString msvcVersion() const; - void setMsvcVersion(const QString &msvcVersion); - QVariantMap toMap() const; ProjectExplorer::IOutputParser *createOutputParser() const; Utils::Environment baseEnvironment() const; -signals: - void msvcVersionChanged(); - protected: CMakeBuildConfiguration(CMakeTarget *parent, CMakeBuildConfiguration *source); virtual bool fromMap(const QVariantMap &map); diff --git a/src/plugins/cmakeprojectmanager/cmakeopenprojectwizard.cpp b/src/plugins/cmakeprojectmanager/cmakeopenprojectwizard.cpp index d141666134..39e74a76db 100644 --- a/src/plugins/cmakeprojectmanager/cmakeopenprojectwizard.cpp +++ b/src/plugins/cmakeprojectmanager/cmakeopenprojectwizard.cpp @@ -44,7 +44,7 @@ #include "cmakeprojectmanager.h" #include <utils/pathchooser.h> -#include <projectexplorer/toolchain.h> +#include <projectexplorer/toolchainmanager.h> #include <QtGui/QVBoxLayout> #include <QtGui/QFormLayout> @@ -72,7 +72,8 @@ CMakeOpenProjectWizard::CMakeOpenProjectWizard(CMakeManager *cmakeManager, const : m_cmakeManager(cmakeManager), m_sourceDirectory(sourceDirectory), m_creatingCbpFiles(false), - m_environment(env) + m_environment(env), + m_toolChain(0) { int startid; if (hasInSourceBuild()) { @@ -106,7 +107,8 @@ CMakeOpenProjectWizard::CMakeOpenProjectWizard(CMakeManager *cmakeManager, const : m_cmakeManager(cmakeManager), m_sourceDirectory(sourceDirectory), m_creatingCbpFiles(true), - m_environment(env) + m_environment(env), + m_toolChain(0) { CMakeRunPage::Mode rmode; @@ -126,7 +128,8 @@ CMakeOpenProjectWizard::CMakeOpenProjectWizard(CMakeManager *cmakeManager, const : m_cmakeManager(cmakeManager), m_sourceDirectory(sourceDirectory), m_creatingCbpFiles(true), - m_environment(env) + m_environment(env), + m_toolChain(0) { m_buildDirectory = oldBuildDirectory; addPage(new ShadowBuildPage(this, true)); @@ -196,26 +199,27 @@ void CMakeOpenProjectWizard::setBuildDirectory(const QString &directory) m_buildDirectory = directory; } -QString CMakeOpenProjectWizard::msvcVersion() const +QString CMakeOpenProjectWizard::arguments() const { - return m_msvcVersion; + return m_arguments; } -void CMakeOpenProjectWizard::setMsvcVersion(const QString &version) +void CMakeOpenProjectWizard::setArguments(const QString &args) { - m_msvcVersion = version; + m_arguments = args; } -QString CMakeOpenProjectWizard::arguments() const +ProjectExplorer::ToolChain *CMakeOpenProjectWizard::toolChain() const { - return m_arguments; + return m_toolChain; } -void CMakeOpenProjectWizard::setArguments(const QString &args) +void CMakeOpenProjectWizard::setToolChain(ProjectExplorer::ToolChain *tc) { - m_arguments = args; + m_toolChain = tc; } + Utils::Environment CMakeOpenProjectWizard::environment() const { return m_environment; @@ -236,7 +240,6 @@ InSourceBuildPage::InSourceBuildPage(CMakeOpenProjectWizard *cmakeWizard) setTitle(tr("Build Location")); } - ShadowBuildPage::ShadowBuildPage(CMakeOpenProjectWizard *cmakeWizard, bool change) : QWizardPage(cmakeWizard), m_cmakeWizard(cmakeWizard) { @@ -378,9 +381,8 @@ void CMakeRunPage::initializePage() m_descriptionLabel->setText(tr("Refreshing cbp file in %1.").arg(m_buildDirectory)); } if (m_cmakeWizard->cmakeManager()->hasCodeBlocksMsvcGenerator()) { - m_generatorComboBox->setVisible(true); + // Try to find out generator from CMakeCache file, if it exists QString cachedGenerator; - // Try to find out generator from CMakeCachhe file, if it exists QFile fi(m_buildDirectory + "/CMakeCache.txt"); if (fi.exists()) { @@ -398,67 +400,66 @@ void CMakeRunPage::initializePage() } } } - m_generatorComboBox->clear(); - // Find out whether we have multiple msvc versions - QStringList msvcVersions = ProjectExplorer::ToolChain::availableMSVCVersions(); - if (msvcVersions.isEmpty()) { - - } else if (msvcVersions.count() == 1) { - m_generatorComboBox->addItem(tr("NMake Generator"), msvcVersions.first()); - } else { - foreach (const QString &msvcVersion, msvcVersions) - m_generatorComboBox->addItem(tr("NMake Generator (%1)").arg(msvcVersion), msvcVersion); - } - - if (cachedGenerator == "NMake Makefiles" && !msvcVersions.isEmpty()) { - m_generatorComboBox->setCurrentIndex(0); - m_cmakeWizard->setMsvcVersion(msvcVersions.first()); - } - m_generatorComboBox->addItem(tr("MinGW Generator"), "mingw"); - if (cachedGenerator == "MinGW Makefiles") { - m_generatorComboBox->setCurrentIndex(m_generatorComboBox->count() - 1); - m_cmakeWizard->setMsvcVersion(""); + m_generatorComboBox->setVisible(true); + m_generatorComboBox->clear(); + QList<ProjectExplorer::ToolChain *> tcs = + ProjectExplorer::ToolChainManager::instance()->findToolChains(ProjectExplorer::Abi::hostAbi()); + foreach (ProjectExplorer::ToolChain *tc, tcs) { + ProjectExplorer::Abi targetAbi = tc->targetAbi(); + QVariant tcVariant = qVariantFromValue(static_cast<void *>(tc)); + if (targetAbi.os() == ProjectExplorer::Abi::Windows) { + if (targetAbi.osFlavor() == ProjectExplorer::Abi::Windows_msvc) + m_generatorComboBox->addItem(tr("NMake Generator (%1)").arg(tc->displayName()), tcVariant); + else if (targetAbi.osFlavor() == ProjectExplorer::Abi::Windows_msys) + m_generatorComboBox->addItem(tr("MinGW Generator (%1)").arg(tc->displayName()), tcVariant); + else + continue; + } } } else { // No new enough cmake, simply hide the combo box m_generatorComboBox->setVisible(false); + QList<ProjectExplorer::ToolChain *> tcs = + ProjectExplorer::ToolChainManager::instance()->findToolChains(ProjectExplorer::Abi::hostAbi()); + if (tcs.isEmpty()) + return; + m_cmakeWizard->setToolChain(tcs.at(0)); } } void CMakeRunPage::runCMake() { + int index = m_generatorComboBox->currentIndex(); + + ProjectExplorer::ToolChain *tc = 0; + if (index >= 0) { + tc = static_cast<ProjectExplorer::ToolChain *>(m_generatorComboBox->itemData(index).value<void *>()); + if (!tc) + return; + m_cmakeWizard->setToolChain(tc); + } else { + tc = m_cmakeWizard->toolChain(); + } + Q_ASSERT(tc); + m_runCMake->setEnabled(false); m_argumentsLineEdit->setEnabled(false); + m_generatorComboBox->setEnabled(false); CMakeManager *cmakeManager = m_cmakeWizard->cmakeManager(); -#ifdef Q_OS_WIN - m_cmakeWizard->setMsvcVersion(QString()); - QString generator = QLatin1String("-GCodeBlocks - MinGW Makefiles"); - if (m_generatorComboBox->isVisible()) { - // the combobox is shown, check which generator is selected - int index = m_generatorComboBox->currentIndex(); - if (index != -1) { - QString version = m_generatorComboBox->itemData(index).toString(); - if (version != "mingw") { - generator = "-GCodeBlocks - NMake Makefiles"; - m_cmakeWizard->setMsvcVersion(version); - } else { - m_cmakeWizard->setMsvcVersion(""); - } - } - } -#else // Q_OS_WIN QString generator = QLatin1String("-GCodeBlocks - Unix Makefiles"); -#endif - Utils::Environment env = m_cmakeWizard->environment(); - if (!m_cmakeWizard->msvcVersion().isEmpty()) { - // Add the environment of that msvc version to environment - ProjectExplorer::ToolChain *tc = ProjectExplorer::ToolChain::createMSVCToolChain(m_cmakeWizard->msvcVersion(), false); - tc->addToEnvironment(env); - delete tc; + if (tc->targetAbi().os() == ProjectExplorer::Abi::Windows) { + if (tc->targetAbi().osFlavor() == ProjectExplorer::Abi::Windows_msvc) + generator = QLatin1String("-GCodeBlocks - NMake Makefiles"); + else + generator = QLatin1String("-GCodeBlocks - MinGW Makefiles"); } + + Utils::Environment env = m_cmakeWizard->environment(); + tc->addToEnvironment(env); + if (m_cmakeExecutable) { // We asked the user for the cmake executable m_cmakeWizard->cmakeManager()->setCMakeExecutable(m_cmakeExecutable->path()); @@ -475,6 +476,7 @@ void CMakeRunPage::runCMake() } else { m_runCMake->setEnabled(true); m_argumentsLineEdit->setEnabled(true); + m_generatorComboBox->setEnabled(true); m_output->appendPlainText(tr("No valid CMake executable specified.")); } } @@ -515,6 +517,8 @@ void CMakeRunPage::cmakeFinished() { m_runCMake->setEnabled(true); m_argumentsLineEdit->setEnabled(true); + m_generatorComboBox->setEnabled(true); + if (m_cmakeProcess->exitCode() != 0) { m_exitCodeLabel->setVisible(true); m_exitCodeLabel->setText(tr("CMake exited with errors. Please check cmake output.")); @@ -542,4 +546,3 @@ bool CMakeRunPage::isComplete() const { return m_complete; } - diff --git a/src/plugins/cmakeprojectmanager/cmakeopenprojectwizard.h b/src/plugins/cmakeprojectmanager/cmakeopenprojectwizard.h index 88715540f2..af6e575a36 100644 --- a/src/plugins/cmakeprojectmanager/cmakeopenprojectwizard.h +++ b/src/plugins/cmakeprojectmanager/cmakeopenprojectwizard.h @@ -48,6 +48,10 @@ namespace Utils { class PathChooser; } +namespace ProjectExplorer { +class ToolChain; +} + namespace CMakeProjectManager { namespace Internal { @@ -87,10 +91,11 @@ public: CMakeManager *cmakeManager() const; QString arguments() const; void setArguments(const QString &args); + ProjectExplorer::ToolChain *toolChain() const; + void setToolChain(ProjectExplorer::ToolChain *); Utils::Environment environment() const; - QString msvcVersion() const; - void setMsvcVersion(const QString &version); bool existsUpToDateXmlFile() const; + private: void init(); bool hasInSourceBuild() const; @@ -98,9 +103,9 @@ private: QString m_buildDirectory; QString m_sourceDirectory; QString m_arguments; - QString m_msvcVersion; bool m_creatingCbpFiles; Utils::Environment m_environment; + ProjectExplorer::ToolChain *m_toolChain; }; class InSourceBuildPage : public QWizardPage diff --git a/src/plugins/cmakeprojectmanager/cmakeproject.cpp b/src/plugins/cmakeprojectmanager/cmakeproject.cpp index 014cd52632..a7f5ceff4e 100644 --- a/src/plugins/cmakeprojectmanager/cmakeproject.cpp +++ b/src/plugins/cmakeprojectmanager/cmakeproject.cpp @@ -169,7 +169,6 @@ void CMakeProject::changeActiveBuildConfiguration(ProjectExplorer::BuildConfigur mode, cmakebc->environment()); copw.exec(); - cmakebc->setMsvcVersion(copw.msvcVersion()); } // reparse parseCMakeLists(); @@ -282,6 +281,9 @@ bool CMakeProject::parseCMakeLists() //qDebug()<<"Updating CodeModel"; createUiCodeModelSupport(); + if (!activeBC->toolChain()) + return true; + QStringList allIncludePaths; QStringList allFrameworkPaths; QList<ProjectExplorer::HeaderPath> allHeaderPaths = activeBC->toolChain()->systemHeaderPaths(); @@ -527,9 +529,9 @@ bool CMakeProject::fromMap(const QVariantMap &map) CMakeBuildConfiguration *bc = static_cast<CMakeBuildConfiguration *>(t->buildConfigurations().at(0)); - bc->setMsvcVersion(copw.msvcVersion()); if (!copw.buildDirectory().isEmpty()) bc->setBuildDirectory(copw.buildDirectory()); + bc->setToolChain(copw.toolChain()); addTarget(t); } else { @@ -554,7 +556,7 @@ bool CMakeProject::fromMap(const QVariantMap &map) activeBC->environment()); if (copw.exec() != QDialog::Accepted) return false; - activeBC->setMsvcVersion(copw.msvcVersion()); + activeBC->setToolChain(copw.toolChain()); } } diff --git a/src/plugins/cmakeprojectmanager/cmakerunconfiguration.cpp b/src/plugins/cmakeprojectmanager/cmakerunconfiguration.cpp index 79976c9f55..0cea71779d 100644 --- a/src/plugins/cmakeprojectmanager/cmakerunconfiguration.cpp +++ b/src/plugins/cmakeprojectmanager/cmakerunconfiguration.cpp @@ -299,14 +299,6 @@ void CMakeRunConfiguration::setUserEnvironmentChanges(const QList<Utils::Environ } } -ProjectExplorer::ToolChainType CMakeRunConfiguration::toolChainType() const -{ - CMakeBuildConfiguration *bc = activeBuildConfiguration(); - if (!bc) - return ProjectExplorer::ToolChain_UNKNOWN; - return bc->toolChainType(); -} - void CMakeRunConfiguration::setEnabled(bool b) { if (m_enabled == b) diff --git a/src/plugins/cmakeprojectmanager/cmakerunconfiguration.h b/src/plugins/cmakeprojectmanager/cmakerunconfiguration.h index fc8b3b39a5..1e3df0de11 100644 --- a/src/plugins/cmakeprojectmanager/cmakerunconfiguration.h +++ b/src/plugins/cmakeprojectmanager/cmakerunconfiguration.h @@ -37,6 +37,7 @@ #include <projectexplorer/applicationrunconfiguration.h> #include <projectexplorer/persistentsettings.h> #include <projectexplorer/environmentwidget.h> +#include <projectexplorer/toolchain.h> #include <utils/environment.h> #include <utils/pathchooser.h> #include <utils/detailswidget.h> @@ -83,7 +84,6 @@ public: QString dumperLibrary() const; QStringList dumperLibraryLocations() const; - ProjectExplorer::ToolChainType toolChainType() const; QVariantMap toMap() const; diff --git a/src/plugins/debugger/cdb/cdbengine.cpp b/src/plugins/debugger/cdb/cdbengine.cpp index 86a11b6290..8dfd96709a 100644 --- a/src/plugins/debugger/cdb/cdbengine.cpp +++ b/src/plugins/debugger/cdb/cdbengine.cpp @@ -309,10 +309,10 @@ static inline bool validMode(DebuggerStartMode sm) return true; } -static inline QString msgCdbDisabled(ToolChainType tc) +static inline QString msgCdbDisabled(const ProjectExplorer::Abi &abi) { return CdbEngine::tr("The CDB debug engine required for %1 is currently disabled."). - arg(ToolChain::toolChainName(tc)); + arg(abi.toString()); } // Accessed by RunControlFactory @@ -322,7 +322,7 @@ DebuggerEngine *createCdbEngine(const DebuggerStartParameters &sp, #ifdef Q_OS_WIN CdbOptionsPage *op = CdbOptionsPage::instance(); if (!op || !op->options()->isValid()) { - *errorMessage = msgCdbDisabled(sp.toolChainType); + *errorMessage = msgCdbDisabled(sp.toolChainAbi); return 0; } if (!validMode(sp.startMode)) { @@ -347,25 +347,18 @@ bool isCdbEngineEnabled() #endif } -ConfigurationCheck checkCdbConfiguration(ToolChainType toolChain) +ConfigurationCheck checkCdbConfiguration(const ProjectExplorer::Abi &abi) { ConfigurationCheck check; - switch (toolChain) { - case ToolChain_MinGW: // Do our best - case ToolChain_MSVC: - case ToolChain_WINCE: - case ToolChain_OTHER: - case ToolChain_UNKNOWN: - case ToolChain_INVALID: + if (abi.binaryFormat() == ProjectExplorer::Abi::Format_PE + && abi.osFlavor() != ProjectExplorer::Abi::Windows_msys) { if (!isCdbEngineEnabled()) { - check.errorMessage = msgCdbDisabled(toolChain); + check.errorMessage = msgCdbDisabled(abi); check.settingsPage = CdbOptionsPage::settingsId(); } - break; - default: - //: %1 is something like "GCCE" or "Intel C++ Compiler (Linux)" (see ToolChain context) - check.errorMessage = CdbEngine::tr("The CDB debug engine does not support the %1 toolchain."). - arg(ToolChain::toolChainName(toolChain)); + } else { + check.errorMessage = CdbEngine::tr("The CDB debug engine does not support the %1 ABI."). + arg(abi.toString()); check.settingsPage = CdbOptionsPage::settingsId(); } return check; diff --git a/src/plugins/debugger/debuggercore.h b/src/plugins/debugger/debuggercore.h index da85e4c4d8..f86d5122c3 100644 --- a/src/plugins/debugger/debuggercore.h +++ b/src/plugins/debugger/debuggercore.h @@ -36,6 +36,8 @@ #include "debuggerconstants.h" +#include <projectexplorer/abi.h> + #include <QtCore/QObject> QT_BEGIN_NAMESPACE @@ -101,7 +103,7 @@ public: virtual bool initialize(const QStringList &arguments, QString *errorMessage) = 0; virtual QWidget *mainWindow() const = 0; virtual bool isDockVisible(const QString &objectName) const = 0; - virtual QString gdbBinaryForToolChain(int toolChain) const = 0; + virtual QString gdbBinaryForAbi(const ProjectExplorer::Abi &abi) const = 0; virtual void showModuleSymbols(const QString &moduleName, const QVector<Symbol> &symbols) = 0; virtual void openMemoryEditor() = 0; diff --git a/src/plugins/debugger/debuggerengine.cpp b/src/plugins/debugger/debuggerengine.cpp index 7b82b9a4a7..5b1030651c 100644 --- a/src/plugins/debugger/debuggerengine.cpp +++ b/src/plugins/debugger/debuggerengine.cpp @@ -57,9 +57,6 @@ #include <coreplugin/progressmanager/progressmanager.h> #include <coreplugin/progressmanager/futureprogress.h> -#include <projectexplorer/toolchain.h> -#include <projectexplorer/toolchaintype.h> - #include <texteditor/itexteditor.h> #include <texteditor/basetextmark.h> @@ -123,7 +120,7 @@ QDebug operator<<(QDebug str, const DebuggerStartParameters &sp) << " symbolFileName=" << sp.symbolFileName << " useServerStartScript=" << sp.useServerStartScript << " serverStartScript=" << sp.serverStartScript - << " toolchain=" << sp.toolChainType << '\n'; + << " abi=" << sp.toolChainAbi.toString() << '\n'; return str; } diff --git a/src/plugins/debugger/debuggerplugin.cpp b/src/plugins/debugger/debuggerplugin.cpp index caaa78a2df..af0ef86b09 100644 --- a/src/plugins/debugger/debuggerplugin.cpp +++ b/src/plugins/debugger/debuggerplugin.cpp @@ -97,8 +97,6 @@ #include <projectexplorer/projectexplorerconstants.h> #include <projectexplorer/session.h> #include <projectexplorer/target.h> -#include <projectexplorer/toolchain.h> -#include <projectexplorer/toolchaintype.h> #include <qt4projectmanager/qt4projectmanagerconstants.h> @@ -904,7 +902,7 @@ public slots: void runControlStarted(DebuggerEngine *engine); void runControlFinished(DebuggerEngine *engine); DebuggerLanguages activeLanguages() const; - QString gdbBinaryForToolChain(int toolChain) const; + QString gdbBinaryForAbi(const ProjectExplorer::Abi &abi) const; void remoteCommand(const QStringList &options, const QStringList &); bool isReverseDebugging() const; @@ -1536,7 +1534,8 @@ void DebuggerPluginPrivate::startExternalApplication() sp.processArgs = dlg.executableArguments(); // Fixme: 1 of 3 testing hacks. if (sp.processArgs.startsWith(__("@tcf@ ")) || sp.processArgs.startsWith(__("@sym@ "))) - sp.toolChainType = ToolChain_RVCT2_ARMV5; + // Set up an ARM Symbian Abi + sp.toolChainAbi = Abi(Abi::ARM, Abi::Symbian, Abi::Symbian_device, Abi::Format_ELF, false); if (dlg.breakAtMain()) { #ifdef Q_OS_WIN @@ -1615,7 +1614,12 @@ void DebuggerPluginPrivate::startRemoteCdbSession() { const QString connectionKey = _("CdbRemoteConnection"); DebuggerStartParameters sp; - sp.toolChainType = ToolChain_MSVC; + Abi hostAbi = Abi::hostAbi(); + sp.toolChainAbi = ProjectExplorer::Abi(hostAbi.architecture(), + ProjectExplorer::Abi::Windows, + ProjectExplorer::Abi::Windows_msvc, + ProjectExplorer::Abi::Format_PE, + true); sp.startMode = AttachToRemote; StartRemoteCdbDialog dlg(mainWindow()); QString previousConnection = configValue(connectionKey).toString(); @@ -1681,7 +1685,7 @@ void DebuggerPluginPrivate::startRemoteApplication() sp.displayName = dlg.localExecutable(); sp.debuggerCommand = dlg.debugger(); // Override toolchain-detection. if (!sp.debuggerCommand.isEmpty()) - sp.toolChainType = ToolChain_INVALID; + sp.toolChainAbi = ProjectExplorer::Abi(); sp.startMode = AttachToRemote; sp.useServerStartScript = dlg.useServerStartScript(); sp.serverStartScript = dlg.serverStartScript(); @@ -2494,10 +2498,9 @@ void DebuggerPluginPrivate::createNewDock(QWidget *widget) void DebuggerPluginPrivate::runControlStarted(DebuggerEngine *engine) { activateDebugMode(); - QString toolChainName = - ToolChain::toolChainName(engine->startParameters().toolChainType); - const QString message = tr("Starting debugger '%1' for tool chain '%2'...") - .arg(engine->objectName()).arg(toolChainName); + const QString message = tr("Starting debugger '%1' for ABI '%2'...") + .arg(engine->objectName()) + .arg(engine->startParameters().toolChainAbi.toString()); showMessage(message, StatusBar); showMessage(m_debuggerSettings->dump(), LogDebug); m_snapshotHandler->appendSnapshot(engine); @@ -2534,9 +2537,9 @@ void DebuggerPluginPrivate::remoteCommand(const QStringList &options, runScheduled(); } -QString DebuggerPluginPrivate::gdbBinaryForToolChain(int toolChain) const +QString DebuggerPluginPrivate::gdbBinaryForAbi(const ProjectExplorer::Abi &abi) const { - return GdbOptionsPage::gdbBinaryToolChainMap.key(toolChain); + return GdbOptionsPage::abiToGdbMap.value(abi.toString()); } DebuggerLanguages DebuggerPluginPrivate::activeLanguages() const @@ -2757,7 +2760,7 @@ void DebuggerPluginPrivate::extensionsInitialized() dock->setProperty(DOCKWIDGET_DEFAULT_AREA, Qt::RightDockWidgetArea); m_debuggerSettings->readSettings(); - GdbOptionsPage::readGdbBinarySettings(); + GdbOptionsPage::readGdbSettings(); // Register factory of DebuggerRunControl. m_debuggerRunControlFactory = new DebuggerRunControlFactory @@ -3158,8 +3161,7 @@ void DebuggerPluginPrivate::aboutToShutdown() this, 0); m_debuggerSettings->writeSettings(); m_mainWindow->writeSettings(); - if (GdbOptionsPage::gdbBinariesChanged) - GdbOptionsPage::writeGdbBinarySettings(); + GdbOptionsPage::writeGdbSettings(); } } // namespace Internal diff --git a/src/plugins/debugger/debuggerrunner.cpp b/src/plugins/debugger/debuggerrunner.cpp index 6ad856cff5..512ffb3534 100644 --- a/src/plugins/debugger/debuggerrunner.cpp +++ b/src/plugins/debugger/debuggerrunner.cpp @@ -49,9 +49,9 @@ # include "peutils.h" #endif +#include <projectexplorer/abi.h> #include <projectexplorer/debugginghelper.h> #include <projectexplorer/project.h> -#include <projectexplorer/toolchain.h> #include <projectexplorer/projectexplorerconstants.h> #include <projectexplorer/target.h> #include <projectexplorer/buildconfiguration.h> @@ -74,7 +74,7 @@ namespace Debugger { namespace Internal { bool isCdbEngineEnabled(); // Check the configuration page -ConfigurationCheck checkCdbConfiguration(ToolChainType toolChain); +ConfigurationCheck checkCdbConfiguration(const ProjectExplorer::Abi &); DebuggerEngine *createCdbEngine(const DebuggerStartParameters &, DebuggerEngine *masterEngine, QString *error); @@ -88,7 +88,7 @@ DebuggerEngine *createQmlEngine(const DebuggerStartParameters &, DebuggerEngine *createQmlCppEngine(const DebuggerStartParameters &); DebuggerEngine *createLldbEngine(const DebuggerStartParameters &); -extern QString msgNoBinaryForToolChain(int tc); +extern QString msgNoBinaryForToolChain(const ProjectExplorer::Abi &abi); static QString msgEngineNotAvailable(const char *engine) { @@ -165,8 +165,13 @@ DebuggerEngineType DebuggerRunControlPrivate::engineForExecutable // We need the CDB debugger in order to be able to debug VS // executables. - ConfigurationCheck check = checkDebugConfiguration(ToolChain_MSVC); - if (!check) { + Abi hostAbi = Abi::hostAbi(); + ConfigurationCheck check = checkDebugConfiguration(Abi(hostAbi.architecture(), + Abi::Windows, + hostAbi.osFlavor(), + Abi::Format_PE, + hostAbi.wordWidth())); + if (!check) { m_errorMessage = check.errorMessage; m_settingsIdHint = check.settingsPage; if (enabledEngineTypes & CdbEngineType) @@ -216,38 +221,18 @@ DebuggerEngineType DebuggerRunControlPrivate::engineForMode // //////////////////////////////////////////////////////////////////////// -static DebuggerEngineType engineForToolChain(ToolChainType toolChainType) +static DebuggerEngineType engineForToolChain(const Abi &toolChain) { - switch (toolChainType) { - case ToolChain_LINUX_ICC: - case ToolChain_MinGW: - case ToolChain_GCC: - case ToolChain_WINSCW: // S60 - case ToolChain_GCCE: - case ToolChain_RVCT2_ARMV5: - case ToolChain_RVCT2_ARMV6: - case ToolChain_RVCT_ARMV5_GNUPOC: - case ToolChain_GCCE_GNUPOC: - case ToolChain_GCC_MAEMO5: - case ToolChain_GCC_HARMATTAN: - case ToolChain_GCC_MEEGO: + if (toolChain.binaryFormat() == Abi::Format_ELF || toolChain.binaryFormat() == Abi::Format_Mach_O + || (toolChain.binaryFormat() == Abi::Format_PE && toolChain.osFlavor() == Abi::Windows_msys)) { #ifdef WITH_LLDB // lldb override if (Core::ICore::instance()->settings()->value("LLDB/enabled").toBool()) return LldbEngineType; #endif return GdbEngineType; - - - case ToolChain_MSVC: - case ToolChain_WINCE: + } else if (toolChain.binaryFormat() == Abi::Format_PE && toolChain.osFlavor() != Abi::Windows_msys) { return CdbEngineType; - - case ToolChain_OTHER: - case ToolChain_UNKNOWN: - case ToolChain_INVALID: - default: - break; } return NoEngineType; } @@ -280,7 +265,7 @@ DebuggerRunControl::DebuggerRunControl(RunConfiguration *runConfiguration, else if (sp.executable.endsWith(_(".py"))) engineType = PdbEngineType; else { - engineType = engineForToolChain(sp.toolChainType); + engineType = engineForToolChain(sp.toolChainAbi); if (engineType == CdbEngineType && !(enabledEngineTypes & CdbEngineType)) { d->m_errorMessage = msgEngineNotAvailable("Cdb Engine"); engineType = NoEngineType; @@ -351,9 +336,8 @@ DebuggerRunControl::DebuggerRunControl(RunConfiguration *runConfiguration, // Could not find anything suitable. debuggingFinished(); // Create Message box with possibility to go to settings. - QString toolChainName = ToolChain::toolChainName(sp.toolChainType); - const QString msg = tr("Cannot debug '%1' (tool chain: '%2'): %3") - .arg(sp.executable, toolChainName, d->m_errorMessage); + const QString msg = tr("Cannot debug '%1' (binary format: '%2'): %3") + .arg(sp.executable, sp.toolChainAbi.toString(), d->m_errorMessage); Core::ICore::instance()->showWarningWithOptions(tr("Warning"), msg, QString(), QLatin1String(Constants::DEBUGGER_SETTINGS_CATEGORY), d->m_settingsIdHint); @@ -388,37 +372,27 @@ void DebuggerRunControl::setCustomEnvironment(Utils::Environment env) d->m_engine->startParameters().environment = env; } -DEBUGGER_EXPORT ConfigurationCheck checkDebugConfiguration(ToolChainType toolChain) +ConfigurationCheck checkDebugConfiguration(const ProjectExplorer::Abi &abi) { ConfigurationCheck result; if (!(debuggerCore()->activeLanguages() & CppLanguage)) return result; - switch(toolChain) { - case ToolChain_GCC: - case ToolChain_LINUX_ICC: - case ToolChain_MinGW: - case ToolChain_WINCE: // S60 - case ToolChain_WINSCW: - case ToolChain_GCCE: - case ToolChain_RVCT2_ARMV5: - case ToolChain_RVCT2_ARMV6: - if (debuggerCore()->gdbBinaryForToolChain(toolChain).isEmpty()) { - result.errorMessage = msgNoBinaryForToolChain(toolChain); + if (abi.binaryFormat() == Abi::Format_ELF || + abi.binaryFormat() == Abi::Format_Mach_O || + (abi.binaryFormat() == Abi::Format_PE && abi.osFlavor() == Abi::Windows_msys)) { + if (debuggerCore()->gdbBinaryForAbi(abi).isEmpty()) { + result.errorMessage = msgNoBinaryForToolChain(abi); result.errorMessage += QLatin1Char(' ') + msgEngineNotAvailable("Gdb"); result.settingsPage = GdbOptionsPage::settingsId(); } - break; - case ToolChain_MSVC: - result = checkCdbConfiguration(toolChain); + } else if (abi.binaryFormat() == Abi::Format_PE && abi.osFlavor() != Abi::Windows_msys) { + result = checkCdbConfiguration(abi); if (!result) { result.errorMessage += msgEngineNotAvailable("Cdb"); result.settingsPage = QLatin1String("Cdb"); } - break; - default: - break; } if (!result && !result.settingsPage.isEmpty()) @@ -586,7 +560,7 @@ static DebuggerStartParameters localStartParameters(RunConfiguration *runConfigu sp.workingDirectory = rc->workingDirectory(); sp.executable = rc->executable(); sp.processArgs = rc->commandLineArguments(); - sp.toolChainType = rc->toolChainType(); + sp.toolChainAbi = rc->abi(); sp.useTerminal = rc->runMode() == LocalApplicationRunConfiguration::Console; sp.dumperLibrary = rc->dumperLibrary(); sp.dumperLibraryLocations = rc->dumperLibraryLocations(); @@ -644,7 +618,7 @@ DebuggerRunControl *DebuggerRunControlFactory::create { DebuggerStartParameters sp = sp0; sp.enabledEngines = m_enabledEngines; - ConfigurationCheck check = checkDebugConfiguration(sp.toolChainType); + ConfigurationCheck check = checkDebugConfiguration(sp.toolChainAbi); if (!check) { //appendMessage(errorMessage, true); diff --git a/src/plugins/debugger/debuggerrunner.h b/src/plugins/debugger/debuggerrunner.h index 76e1b5cae5..1da943d02a 100644 --- a/src/plugins/debugger/debuggerrunner.h +++ b/src/plugins/debugger/debuggerrunner.h @@ -36,8 +36,8 @@ #include "debugger_global.h" +#include <projectexplorer/abi.h> #include <projectexplorer/runconfiguration.h> -#include <projectexplorer/toolchaintype.h> #include <QtCore/QScopedPointer> @@ -68,7 +68,7 @@ public: QString settingsPage; }; -DEBUGGER_EXPORT ConfigurationCheck checkDebugConfiguration(ProjectExplorer::ToolChainType toolChain); +DEBUGGER_EXPORT ConfigurationCheck checkDebugConfiguration(const ProjectExplorer::Abi &abi); // This is a job description containing all data "local" to the jobs, including // the models of the individual debugger views. diff --git a/src/plugins/debugger/debuggerstartparameters.h b/src/plugins/debugger/debuggerstartparameters.h index 2fe82d4bc0..011042d734 100644 --- a/src/plugins/debugger/debuggerstartparameters.h +++ b/src/plugins/debugger/debuggerstartparameters.h @@ -39,7 +39,7 @@ #include <utils/ssh/sshconnection.h> #include <utils/environment.h> -#include <projectexplorer/toolchaintype.h> +#include <projectexplorer/abi.h> #include <QtCore/QMetaType> @@ -70,7 +70,6 @@ public: qmlServerPort(0), useServerStartScript(false), connParams(Utils::SshConnectionParameters::NoProxy), - toolChainType(ProjectExplorer::ToolChain_UNKNOWN), startMode(NoStartMode), executableUid(0), communicationChannel(CommunicationChannelUsb), @@ -117,7 +116,7 @@ public: Utils::SshConnectionParameters connParams; QString debuggerCommand; - ProjectExplorer::ToolChainType toolChainType; + ProjectExplorer::Abi toolChainAbi; QString qtInstallPath; QString dumperLibrary; diff --git a/src/plugins/debugger/gdb/gdbchooserwidget.cpp b/src/plugins/debugger/gdb/gdbchooserwidget.cpp index 50d84ba036..283f297222 100644 --- a/src/plugins/debugger/gdb/gdbchooserwidget.cpp +++ b/src/plugins/debugger/gdb/gdbchooserwidget.cpp @@ -52,51 +52,15 @@ #include <QtGui/QIcon> #include <QtGui/QGroupBox> #include <QtGui/QCheckBox> -#include <QtCore/QDebug> #include <QtCore/QSet> #include <QtCore/QDir> #include <QtCore/QFileInfo> #include <QtCore/QProcess> -enum { binaryRole = Qt::UserRole + 1, toolChainRole = Qt::UserRole + 2 }; -enum Columns { binaryColumn, toolChainColumn, ColumnCount }; +enum Columns { abiColumn, binaryColumn, ColumnCount }; typedef QList<QStandardItem *> StandardItemList; -Q_DECLARE_METATYPE(QList<int>) - -static QList<int> allGdbToolChains() -{ - QList<int> rc; - rc -#ifdef Q_OS_UNIX - << ProjectExplorer::ToolChain_GCC - << ProjectExplorer::ToolChain_LINUX_ICC -#endif -#ifdef Q_OS_WIN - << ProjectExplorer::ToolChain_MinGW - << ProjectExplorer::ToolChain_WINSCW - << ProjectExplorer::ToolChain_GCCE - << ProjectExplorer::ToolChain_RVCT2_ARMV5 - << ProjectExplorer::ToolChain_RVCT2_ARMV6 -#endif - << ProjectExplorer::ToolChain_GCC_MAEMO5 - << ProjectExplorer::ToolChain_GCC_HARMATTAN - << ProjectExplorer::ToolChain_GCC_MEEGO -#ifdef Q_OS_UNIX - << ProjectExplorer::ToolChain_GCCE_GNUPOC - << ProjectExplorer::ToolChain_RVCT_ARMV5_GNUPOC -#endif - << ProjectExplorer::ToolChain_OTHER - << ProjectExplorer::ToolChain_UNKNOWN; - return rc; -} - -static inline QString toolChainName(int tc) -{ - return ProjectExplorer::ToolChain::toolChainName(static_cast<ProjectExplorer::ToolChainType>(tc)); -} - namespace Debugger { namespace Internal { @@ -105,6 +69,10 @@ namespace Internal { // Obtain a tooltip for a gdb binary by running --version static inline QString gdbToolTip(const QString &binary) { + if (binary.isEmpty()) + return QString(); + if (!QFileInfo(binary).exists()) + return GdbChooserWidget::tr("File not found."); QProcess process; process.start(binary, QStringList(QLatin1String("--version"))); process.closeWriteChannel(); @@ -122,37 +90,32 @@ static inline QString gdbToolTip(const QString &binary) // Provides a delayed tooltip listing the gdb version as // obtained by running it. Provides conveniences for getting/setting the maps and // for listing the toolchains used and the ones still available. - class GdbBinaryModel : public QStandardItemModel { public: - typedef GdbChooserWidget::BinaryToolChainMap BinaryToolChainMap; - explicit GdbBinaryModel(QObject * parent = 0); - virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; + QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; + bool setData(const QModelIndex &index, const QVariant &value, int role); // get / set data as map. - BinaryToolChainMap gdbBinaries() const; - void setGdbBinaries(const BinaryToolChainMap &m); + QMap<QString, QString> gdbMapping() const; + void setGdbMapping(const QMap<QString, QString> &m); QString binary(int row) const; - QList<int> toolChains(int row) const; + QString abi(int row) const; - QStringList binaries() const; - QList<int> usedToolChains() const; - QSet<int> unusedToolChainSet() const; - QList<int> unusedToolChains() const; + void append(const QString &abi, const QString &binary); - void append(const QString &binary, const QList<int> &toolChains); + bool isDirty() const; + static void setAbiItem(QStandardItem *item, const QString &abi); static void setBinaryItem(QStandardItem *item, const QString &binary); - static void setToolChainItem(QStandardItem *item, const QList<int> &toolChain); }; GdbBinaryModel::GdbBinaryModel(QObject *parent) : QStandardItemModel(0, ColumnCount, parent) { QStringList headers; - headers << GdbChooserWidget::tr("Binary") << GdbChooserWidget::tr("Toolchains"); + headers << GdbChooserWidget::tr("ABI") << GdbChooserWidget::tr("Debugger"); setHorizontalHeaderLabels(headers); } @@ -166,455 +129,119 @@ QVariant GdbBinaryModel::data(const QModelIndex &index, int role) const // Run the gdb and obtain the tooltip const QString tooltip = gdbToolTip(binary(index.row())); // Set on the whole row + item(index.row(), abiColumn)->setToolTip(tooltip); item(index.row(), binaryColumn)->setToolTip(tooltip); - item(index.row(), toolChainColumn)->setToolTip(tooltip); return QVariant(tooltip); } return QStandardItemModel::data(index, role); } -QStringList GdbBinaryModel::binaries() const -{ - QStringList rc; - const int binaryCount = rowCount(); - for (int b = 0; b < binaryCount; b++) - rc.push_back(binary(b)); - return rc; -} - -QList<int> GdbBinaryModel::usedToolChains() const -{ - // Loop over model and collect all toolchains. - QList<int> rc; - const int binaryCount = rowCount(); - for (int b = 0; b < binaryCount; b++) - foreach(int tc, toolChains(b)) - rc.push_back(tc); - return rc; -} - -QSet<int> GdbBinaryModel::unusedToolChainSet() const +bool GdbBinaryModel::setData(const QModelIndex &index, const QVariant &value, int role) { - const QSet<int> used = usedToolChains().toSet(); - QSet<int> all = allGdbToolChains().toSet(); - return all.subtract(used); -} - -QList<int> GdbBinaryModel::unusedToolChains() const -{ - QList<int> unused = unusedToolChainSet().toList(); - qSort(unused); - return unused; + if (index.isValid() && role == Qt::EditRole) { + Q_ASSERT(index.column() == binaryColumn); + item(index.row(), abiColumn)->setToolTip(QString()); + item(index.row(), binaryColumn)->setToolTip(QString()); + item(index.row(), binaryColumn)->setData(true); + QFont f(item(index.row(), binaryColumn)->font()); + f.setBold(true); + item(index.row(), binaryColumn)->setFont(f); + } + return QStandardItemModel::setData(index, value, role); } -GdbBinaryModel::BinaryToolChainMap GdbBinaryModel::gdbBinaries() const +QMap<QString, QString> GdbBinaryModel::gdbMapping() const { - BinaryToolChainMap rc; + QMap<QString, QString> rc; const int binaryCount = rowCount(); - for (int r = 0; r < binaryCount; r++) { - const QString bin = binary(r); - foreach(int tc, toolChains(r)) - rc.insert(bin, tc); - } + for (int r = 0; r < binaryCount; ++r) + rc.insert(abi(r), binary(r)); return rc; } -void GdbBinaryModel::setGdbBinaries(const BinaryToolChainMap &m) +void GdbBinaryModel::setGdbMapping(const QMap<QString, QString> &m) { removeRows(0, rowCount()); - foreach(const QString &binary, m.uniqueKeys()) - append(binary, m.values(binary)); + for (QMap<QString, QString>::const_iterator i = m.constBegin(); i != m.constEnd(); ++i) + append(i.key(), i.value()); } QString GdbBinaryModel::binary(int row) const { - return item(row, binaryColumn)->data(binaryRole).toString(); + return QDir::fromNativeSeparators(item(row, binaryColumn)->data(Qt::DisplayRole).toString()); } -QList<int> GdbBinaryModel::toolChains(int row) const +QString GdbBinaryModel::abi(int row) const { - const QVariant data = item(row, toolChainColumn)->data(toolChainRole); - return qVariantValue<QList<int> >(data); + return item(row, abiColumn)->data(Qt::DisplayRole).toString(); } void GdbBinaryModel::setBinaryItem(QStandardItem *item, const QString &binary) { - const QFileInfo fi(binary); - item->setText(fi.isAbsolute() ? fi.fileName() : QDir::toNativeSeparators(binary)); + item->setText(binary.isEmpty() ? QString() : QDir::toNativeSeparators(binary)); item->setToolTip(QString());; // clean out delayed tooltip - item->setData(QVariant(binary), binaryRole); - item->setFlags(Qt::ItemIsEnabled|Qt::ItemIsSelectable); + item->setFlags(Qt::ItemIsEnabled|Qt::ItemIsSelectable|Qt::ItemIsEditable); + item->setData(false); } -void GdbBinaryModel::setToolChainItem(QStandardItem *item, const QList<int> &toolChains) +void GdbBinaryModel::setAbiItem(QStandardItem *item, const QString &abi) { - // Format comma-separated list - const QString toolChainSeparator = QLatin1String(", "); - QString toolChainDesc; - const int count = toolChains.size(); - for (int i = 0; i < count; i++) { - if (i) - toolChainDesc += toolChainSeparator; - toolChainDesc += toolChainName(toolChains.at(i)); - } - - item->setText(toolChainDesc); - item->setToolTip(QString());; // clean out delayed tooltip - item->setData(qVariantFromValue(toolChains), toolChainRole); + item->setText(abi); + item->setToolTip(QString()); // clean out delayed tooltip item->setFlags(Qt::ItemIsEnabled|Qt::ItemIsSelectable); } -void GdbBinaryModel::append(const QString &binary, const QList<int> &toolChains) +void GdbBinaryModel::append(const QString &abi, const QString &binary) { QStandardItem *binaryItem = new QStandardItem; - QStandardItem *toolChainItem = new QStandardItem; + QStandardItem *abiItem = new QStandardItem; + GdbBinaryModel::setAbiItem(abiItem, abi); GdbBinaryModel::setBinaryItem(binaryItem, binary); - GdbBinaryModel::setToolChainItem(toolChainItem, toolChains); + StandardItemList row; - row << binaryItem << toolChainItem; + row << abiItem << binaryItem; appendRow(row); } +bool GdbBinaryModel::isDirty() const +{ + for (int i = 0; i < rowCount(); ++i) { + if (item(i, binaryColumn)->data().toBool()) + return true; + } + return false; +} + // ----------- GdbChooserWidget GdbChooserWidget::GdbChooserWidget(QWidget *parent) : QWidget(parent), m_treeView(new QTreeView), - m_model(new GdbBinaryModel(m_treeView)), - m_addButton(new QToolButton), - m_deleteButton(new QToolButton), - m_dirty(false) + m_model(new GdbBinaryModel(m_treeView)) { - QHBoxLayout *mainHLayout = new QHBoxLayout; - + QVBoxLayout *layout = new QVBoxLayout(this); m_treeView->setRootIsDecorated(false); m_treeView->setModel(m_model); m_treeView->setUniformRowHeights(true); m_treeView->setAllColumnsShowFocus(true); m_treeView->setSelectionMode(QAbstractItemView::SingleSelection); - connect(m_treeView->selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)), - this, SLOT(slotCurrentChanged(QModelIndex,QModelIndex))); - connect(m_treeView, SIGNAL(doubleClicked(QModelIndex)), - this, SLOT(slotDoubleClicked(QModelIndex))); - mainHLayout->addWidget(m_treeView); - - m_addButton->setIcon(QIcon(QLatin1String(Core::Constants::ICON_PLUS))); - connect(m_addButton, SIGNAL(clicked()), this, SLOT(slotAdd())); - - m_deleteButton->setIcon(QIcon(QLatin1String(Core::Constants::ICON_MINUS))); - m_deleteButton->setEnabled(false); - connect(m_deleteButton, SIGNAL(clicked()), this, SLOT(slotRemove())); - - QVBoxLayout *vButtonLayout = new QVBoxLayout; - vButtonLayout->addWidget(m_addButton); - vButtonLayout->addWidget(m_deleteButton); - vButtonLayout->addItem(new QSpacerItem(0, 0, QSizePolicy::Ignored, QSizePolicy::MinimumExpanding)); - - mainHLayout->addLayout(vButtonLayout); - setLayout(mainHLayout); -} - -QStandardItem *GdbChooserWidget::currentItem() const -{ - // Return the column-0-item - QModelIndex currentIndex = m_treeView->currentIndex(); - if (!currentIndex.isValid()) - return 0; - if (currentIndex.column() != binaryColumn) - currentIndex = currentIndex.sibling(currentIndex.row(), binaryColumn); - return m_model->itemFromIndex(currentIndex); -} - -void GdbChooserWidget::slotAdd() -{ - // Any toolchains left? - const QList<int> unusedToolChains = m_model->unusedToolChains(); - if (unusedToolChains.isEmpty()) - return; - - // On a binary or no current item: Add binary + toolchain - BinaryToolChainDialog binaryDialog(this); - binaryDialog.setToolChainChoices(unusedToolChains); - if (binaryDialog.exec() != QDialog::Accepted) - return; - // Refuse binaries that already exist - const QString path = binaryDialog.path(); - if (m_model->binaries().contains(path)) { - QMessageBox::warning(this, tr("Duplicate binary"), - tr("The binary '%1' already exists.").arg(path)); - return; - } - // Add binary + toolchain to model - m_model->append(path, binaryDialog.toolChains()); - m_dirty = true; -} - -void GdbChooserWidget::slotRemove() -{ - if (QStandardItem *item = currentItem()) - removeItem(item); -} - -void GdbChooserWidget::removeItem(QStandardItem *item) -{ - m_model->removeRow(item->row()); - m_dirty = true; -} - -void GdbChooserWidget::slotCurrentChanged(const QModelIndex ¤t, const QModelIndex &) -{ - const bool hasItem = current.isValid() && m_model->itemFromIndex(current); - m_deleteButton->setEnabled(hasItem); -} - -void GdbChooserWidget::slotDoubleClicked(const QModelIndex ¤t) -{ - QTC_ASSERT(current.isValid(), return) - // Show dialog to edit. Make all unused toolchains including the ones - // previously assigned to that binary available. - const int row = current.row(); - const QString oldBinary = m_model->binary(row); - const QList<int> oldToolChains = m_model->toolChains(row); - const QSet<int> toolChainChoices = m_model->unusedToolChainSet().unite(oldToolChains.toSet()); - - BinaryToolChainDialog dialog(this); - dialog.setPath(oldBinary); - const BinaryToolChainMap map = gdbBinaries(); - dialog.setToolChainChoices(toolChainChoices.toList(), &map); - dialog.setToolChains(oldToolChains); - if (dialog.exec() != QDialog::Accepted) - return; - // Check if anything changed. - const QString newBinary = dialog.path(); - const QList<int> newToolChains = dialog.toolChains(); - if (newBinary == oldBinary && newToolChains == oldToolChains) - return; - - GdbBinaryModel::setBinaryItem(m_model->item(row, binaryColumn), newBinary); - GdbBinaryModel::setToolChainItem(m_model->item(row, toolChainColumn), newToolChains); - m_dirty = true; + layout->addWidget(m_treeView); } -GdbChooserWidget::BinaryToolChainMap GdbChooserWidget::gdbBinaries() const +QMap<QString, QString> GdbChooserWidget::gdbMapping() const { - return m_model->gdbBinaries(); + return m_model->gdbMapping(); } -void GdbChooserWidget::setGdbBinaries(const BinaryToolChainMap &m) +void GdbChooserWidget::setGdbMapping(const QMap<QString, QString> &m) { - m_model->setGdbBinaries(m); + m_model->setGdbMapping(m); for (int c = 0; c < ColumnCount; c++) m_treeView->resizeColumnToContents(c); - m_dirty = false; } bool GdbChooserWidget::isDirty() const { - return m_dirty; -} - -void GdbChooserWidget::clearDirty() -{ - m_dirty = false; -} - -// -------------- ToolChainSelectorWidget -static const char *toolChainPropertyC = "toolChain"; - -static inline int toolChainOfCheckBox(const QCheckBox *c) -{ - return c->property(toolChainPropertyC).toInt(); -} - -static inline QVBoxLayout *createGroupBox(const QString &title, QVBoxLayout *lt) -{ - QGroupBox *gb = new QGroupBox(title); - QVBoxLayout *gbLayout = new QVBoxLayout; - gb->setLayout(gbLayout); - lt->addWidget(gb); - return gbLayout; -} - -ToolChainSelectorWidget::ToolChainSelectorWidget(QWidget *parent) : - QWidget(parent), m_valid(false) -{ - QVBoxLayout *mainLayout = new QVBoxLayout; - QVBoxLayout *desktopLayout = createGroupBox(tr("Desktop/General"), mainLayout); - QVBoxLayout *symbianLayout = createGroupBox(tr("Symbian"), mainLayout); - QVBoxLayout *maemoLayout = createGroupBox(tr("Maemo"), mainLayout); - - // Group checkboxes into categories - foreach(int tc, allGdbToolChains()) { - switch (tc) { - case ProjectExplorer::ToolChain_GCC: - case ProjectExplorer::ToolChain_LINUX_ICC: - case ProjectExplorer::ToolChain_MinGW: - case ProjectExplorer::ToolChain_OTHER: - case ProjectExplorer::ToolChain_UNKNOWN: - desktopLayout->addWidget(createToolChainCheckBox(tc)); - break; - case ProjectExplorer::ToolChain_MSVC: - case ProjectExplorer::ToolChain_WINCE: - break; - case ProjectExplorer::ToolChain_WINSCW: - case ProjectExplorer::ToolChain_GCCE: - case ProjectExplorer::ToolChain_RVCT2_ARMV5: - case ProjectExplorer::ToolChain_RVCT2_ARMV6: - case ProjectExplorer::ToolChain_GCCE_GNUPOC: - case ProjectExplorer::ToolChain_RVCT_ARMV5_GNUPOC: - symbianLayout->addWidget(createToolChainCheckBox(tc)); - break; - case ProjectExplorer::ToolChain_GCC_MAEMO5: - case ProjectExplorer::ToolChain_GCC_HARMATTAN: - case ProjectExplorer::ToolChain_GCC_MEEGO: - maemoLayout->addWidget(createToolChainCheckBox(tc)); - break; - case ProjectExplorer::ToolChain_INVALID: - break; - } - } - setLayout(mainLayout); -} - -QCheckBox *ToolChainSelectorWidget::createToolChainCheckBox(int tc) -{ - // Add checkbox - QCheckBox *cb = new QCheckBox(toolChainName(tc)); - cb->setProperty(toolChainPropertyC, QVariant(tc)); - connect(cb, SIGNAL(stateChanged(int)), this, SLOT(slotCheckStateChanged(int))); - m_checkBoxes.push_back(cb); - return cb; -} - -static inline QString msgDisabledToolChainToolTip(const QString &binary, int toolChain) -{ - return ToolChainSelectorWidget::tr( - "<html><head/><body><p>Another gdb binary (<i>%1</i>) is currently configured " - "to handle the toolchain <i>%2</i>.</p></body></html>"). - arg(QFileInfo(binary).fileName(), toolChainName(toolChain)); -} - -void ToolChainSelectorWidget::setEnabledToolChains(const QList<int> &enabled, - const BinaryToolChainMap *binaryToolChainMap) -{ - foreach(QCheckBox *cb, m_checkBoxes) { - const int toolChain = toolChainOfCheckBox(cb); - if (enabled.contains(toolChain)) { - cb->setToolTip(QString()); - } else { - // Toolchain is handled by a different binary, hint to user. - cb->setEnabled(false); - const QString binary = binaryToolChainMap ? binaryToolChainMap->key(toolChain) : QString(); - if (!binary.isEmpty()) - cb->setToolTip(msgDisabledToolChainToolTip(binary, toolChain)); - } - } -} - -void ToolChainSelectorWidget::setCheckedToolChains(const QList<int> &checked) -{ - foreach(QCheckBox *cb, m_checkBoxes) - if (checked.contains(toolChainOfCheckBox(cb))) - cb->setChecked(true); - // Trigger 'valid changed' - slotCheckStateChanged(checked.isEmpty() ? Qt::Unchecked : Qt::Checked); -} - -QList<int> ToolChainSelectorWidget::checkedToolChains() const -{ - QList<int> rc; - foreach(const QCheckBox *cb, m_checkBoxes) - if (cb->isChecked()) - rc.push_back(toolChainOfCheckBox(cb)); - return rc; -} - -bool ToolChainSelectorWidget::isValid() const -{ - return m_valid; -} - -void ToolChainSelectorWidget::slotCheckStateChanged(int state) -{ - // Emit signal if valid state changed - const bool newValid = state == Qt::Checked || hasCheckedToolChain(); - if (newValid != m_valid) { - m_valid = newValid; - emit validChanged(m_valid); - } -} - -bool ToolChainSelectorWidget::hasCheckedToolChain() const -{ - foreach(const QCheckBox *cb, m_checkBoxes) - if (cb->isChecked()) - return true; - return false; -} - -// -------------- ToolChainDialog -BinaryToolChainDialog::BinaryToolChainDialog(QWidget *parent) : - QDialog(parent), - m_toolChainSelector(new ToolChainSelectorWidget), - m_mainLayout(new QFormLayout), - m_buttonBox(new QDialogButtonBox(QDialogButtonBox::Ok|QDialogButtonBox::Cancel)), - m_pathChooser(new Utils::PathChooser) -{ - - setModal(true); - setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint); - setWindowTitle(tr("Select binary and toolchains")); - - m_pathChooser->setExpectedKind(Utils::PathChooser::ExistingCommand); - m_pathChooser->setPromptDialogTitle(tr("Gdb binary")); - connect(m_pathChooser, SIGNAL(validChanged()), this, SLOT(slotValidChanged())); - m_mainLayout->addRow(tr("Path:"), m_pathChooser); - - connect(m_toolChainSelector, SIGNAL(validChanged(bool)), this, SLOT(slotValidChanged())); - m_mainLayout->addRow(m_toolChainSelector); - - connect(m_buttonBox, SIGNAL(accepted()), this, SLOT(accept())); - connect(m_buttonBox, SIGNAL(rejected()), this, SLOT(reject())); - m_mainLayout->addRow(m_buttonBox); - setLayout(m_mainLayout); - - setOkButtonEnabled(false); - m_pathChooser->setFocus(); -} - -void BinaryToolChainDialog::setToolChainChoices(const QList<int> &tcs, - const BinaryToolChainMap *binaryToolChainMap) -{ - m_toolChainSelector->setEnabledToolChains(tcs, binaryToolChainMap); -} - -void BinaryToolChainDialog::setToolChains(const QList<int> &tcs) -{ - m_toolChainSelector->setCheckedToolChains(tcs); -} - -QList<int> BinaryToolChainDialog::toolChains() const -{ - return m_toolChainSelector->checkedToolChains(); -} - -void BinaryToolChainDialog::setOkButtonEnabled(bool v) -{ - m_buttonBox->button(QDialogButtonBox::Ok)->setEnabled(v); -} - -void BinaryToolChainDialog::setPath(const QString &p) -{ - m_pathChooser->setPath(p); -} - -QString BinaryToolChainDialog::path() const -{ - return m_pathChooser->rawPath(); -} - -void BinaryToolChainDialog::slotValidChanged() -{ - setOkButtonEnabled(m_pathChooser->isValid() && m_toolChainSelector->isValid()); + return m_model->isDirty(); } } // namespace Internal diff --git a/src/plugins/debugger/gdb/gdbchooserwidget.h b/src/plugins/debugger/gdb/gdbchooserwidget.h index da62e60dda..45f20eacb5 100644 --- a/src/plugins/debugger/gdb/gdbchooserwidget.h +++ b/src/plugins/debugger/gdb/gdbchooserwidget.h @@ -67,96 +67,17 @@ class GdbChooserWidget : public QWidget public: explicit GdbChooserWidget(QWidget *parent = 0); - typedef QMultiMap<QString, int> BinaryToolChainMap; - - BinaryToolChainMap gdbBinaries() const; - void setGdbBinaries(const BinaryToolChainMap &m); + QMap<QString, QString> gdbMapping() const; + void setGdbMapping(const QMap<QString, QString> &m); bool isDirty() const; -public slots: - void clearDirty(); - -private slots: - void slotAdd(); - void slotRemove(); - void slotCurrentChanged(const QModelIndex ¤t, const QModelIndex & previous); - void slotDoubleClicked(const QModelIndex ¤t); - private: void removeItem(QStandardItem *item); QToolButton *createAddToolMenuButton(); - QStandardItem *currentItem() const; QTreeView *m_treeView; GdbBinaryModel *m_model; - QToolButton *m_addButton; - QToolButton *m_deleteButton; - bool m_dirty; -}; - -// Present toolchains with checkboxes grouped in QGroupBox panes -// and provide valid-handling. Unavailabe toolchains can be grayed -// out using setEnabledToolChains(). -class ToolChainSelectorWidget : public QWidget { - Q_OBJECT -public: - typedef GdbChooserWidget::BinaryToolChainMap BinaryToolChainMap; - - explicit ToolChainSelectorWidget(QWidget *parent = 0); - - void setEnabledToolChains(const QList<int> &enabled, - // Optionally used for generating a tooltip for the disabled check boxes - const BinaryToolChainMap *binaryToolChainMap = 0); - - void setCheckedToolChains(const QList<int> &); - QList<int> checkedToolChains() const; - - bool isValid() const; - -signals: - void validChanged(bool); - -private slots: - void slotCheckStateChanged(int); - -private: - bool hasCheckedToolChain() const; - QCheckBox *createToolChainCheckBox(int tc); - - QList<QCheckBox*> m_checkBoxes; - bool m_valid; -}; - -// Internal helper dialog for selecting a binary and its -// associated toolchains. -class BinaryToolChainDialog : public QDialog { - Q_OBJECT -public: - typedef GdbChooserWidget::BinaryToolChainMap BinaryToolChainMap; - - explicit BinaryToolChainDialog(QWidget *parent); - - void setToolChainChoices(const QList<int> &, - // Optionally used for generating a tooltip for the disabled check boxes - const BinaryToolChainMap *binaryToolChainMap = 0); - - void setToolChains(const QList<int> &); - QList<int> toolChains() const; - - void setPath(const QString &); - QString path() const; - -private slots: - void slotValidChanged(); - -private: - void setOkButtonEnabled(bool e); - - ToolChainSelectorWidget *m_toolChainSelector; - QFormLayout *m_mainLayout; - QDialogButtonBox *m_buttonBox; - Utils::PathChooser *m_pathChooser; }; } // namespace Internal diff --git a/src/plugins/debugger/gdb/gdbengine.cpp b/src/plugins/debugger/gdb/gdbengine.cpp index dce1d60f1b..c9030ece63 100644 --- a/src/plugins/debugger/gdb/gdbengine.cpp +++ b/src/plugins/debugger/gdb/gdbengine.cpp @@ -1795,36 +1795,29 @@ int GdbEngine::currentFrame() const return stackHandler()->currentIndex(); } -QString msgNoBinaryForToolChain(int tc) +QString msgNoBinaryForToolChain(const ProjectExplorer::Abi &tc) { using namespace ProjectExplorer; - return GdbEngine::tr("There is no gdb binary available for '%1'.") - .arg(ToolChain::toolChainName(ToolChainType(tc))); + return GdbEngine::tr("There is no gdb binary available for binaries in format '%1'") + .arg(tc.toString()); } AbstractGdbAdapter *GdbEngine::createAdapter() { const DebuggerStartParameters &sp = startParameters(); - switch (sp.toolChainType) { - case ProjectExplorer::ToolChain_WINSCW: // S60 - case ProjectExplorer::ToolChain_GCCE: - case ProjectExplorer::ToolChain_RVCT2_ARMV5: - case ProjectExplorer::ToolChain_RVCT2_ARMV6: - case ProjectExplorer::ToolChain_RVCT_ARMV5_GNUPOC: - case ProjectExplorer::ToolChain_GCCE_GNUPOC: + if (sp.toolChainAbi.os() == ProjectExplorer::Abi::Symbian) { + // FIXME: 1 of 3 testing hacks. if (sp.debugClient == DebuggerStartParameters::DebugClientCoda) return new CodaGdbAdapter(this); else return new TrkGdbAdapter(this); - default: - break; } switch (sp.startMode) { case AttachCore: return new CoreGdbAdapter(this); case AttachToRemote: - return new RemoteGdbServerAdapter(this, sp.toolChainType); + return new RemoteGdbServerAdapter(this, sp.toolChainAbi); case StartRemoteGdb: return new RemotePlainGdbAdapter(this); case AttachExternal: @@ -4220,12 +4213,12 @@ bool GdbEngine::startGdb(const QStringList &args, const QString &gdb, const DebuggerStartParameters &sp = startParameters(); m_gdb = QString::fromLocal8Bit(qgetenv("QTC_DEBUGGER_PATH")); if (m_gdb.isEmpty() && sp.startMode != StartRemoteGdb) - m_gdb = debuggerCore()->gdbBinaryForToolChain(sp.toolChainType); + m_gdb = debuggerCore()->gdbBinaryForAbi(startParameters().toolChainAbi); if (m_gdb.isEmpty()) m_gdb = gdb; if (m_gdb.isEmpty()) { handleAdapterStartFailed( - msgNoBinaryForToolChain(sp.toolChainType), + msgNoBinaryForToolChain(sp.toolChainAbi), GdbOptionsPage::settingsId()); return false; } diff --git a/src/plugins/debugger/gdb/gdboptionspage.cpp b/src/plugins/debugger/gdb/gdboptionspage.cpp index 46f69c72f8..8f64c46f9f 100644 --- a/src/plugins/debugger/gdb/gdboptionspage.cpp +++ b/src/plugins/debugger/gdb/gdboptionspage.cpp @@ -37,8 +37,8 @@ #include <coreplugin/icore.h> #include <projectexplorer/projectexplorer.h> -#include <projectexplorer/toolchain.h> -#include <projectexplorer/toolchaintype.h> +#include <projectexplorer/toolchainmanager.h> +#include <projectexplorer/abi.h> #include <QtCore/QCoreApplication> #include <QtCore/QTextStream> @@ -47,22 +47,37 @@ namespace Debugger { namespace Internal { -const char gdbBinariesSettingsGroupC[] = "GdbBinaries"; -const char debugModeGdbBinaryKeyC[] = "GdbBinary"; +static const char *GDB_MAPPING_ARRAY = "GdbMapping"; +static const char *GDB_ABI_KEY = "Abi"; +static const char *GDB_BINARY_KEY = "Binary"; -GdbOptionsPage::GdbBinaryToolChainMap GdbOptionsPage::gdbBinaryToolChainMap; -bool GdbOptionsPage::gdbBinariesChanged = true; +GdbOptionsPage::GdbBinaryToolChainMap GdbOptionsPage::abiToGdbMap; +bool GdbOptionsPage::gdbMappingChanged = true; -void GdbOptionsPage::readGdbBinarySettings() /* static */ +void GdbOptionsPage::readGdbSettings() /* static */ { + // FIXME: Convert old settings! using namespace ProjectExplorer; QSettings *settings = Core::ICore::instance()->settings(); - // Convert gdb binaries from flat settings list (see writeSettings) - // into map ("binary1=gdb,1,2", "binary2=symbian_gdb,3,4"). - gdbBinaryToolChainMap.clear(); + + abiToGdbMap.clear(); + + int size = settings->beginReadArray(GDB_MAPPING_ARRAY); + for (int i = 0; i < size; ++i) { + settings->setArrayIndex(i); + ProjectExplorer::Abi abi(settings->value(GDB_ABI_KEY).toString()); + if (!abi.isValid()) + continue; + QString binary = settings->value(GDB_BINARY_KEY).toString(); + if (binary.isEmpty()) + continue; + abiToGdbMap.insert(abi.toString(), binary); + } + settings->endArray(); + + // Map old settings (pre 2.2): const QChar separator = QLatin1Char(','); - const QString keyRoot = QLatin1String(gdbBinariesSettingsGroupC) + QLatin1Char('/') + - QLatin1String(debugModeGdbBinaryKeyC); + const QString keyRoot = QLatin1String("GdbBinaries/GdbBinaries"); for (int i = 1; ; i++) { const QString value = settings->value(keyRoot + QString::number(i)).toString(); if (value.isEmpty()) @@ -71,81 +86,116 @@ void GdbOptionsPage::readGdbBinarySettings() /* static */ QStringList tokens = value.split(separator); if (tokens.size() < 2) break; + const QString binary = tokens.front(); // Skip non-existent absolute binaries allowing for upgrades by the installer. // Force a rewrite of the settings file. const QFileInfo binaryInfo(binary); if (binaryInfo.isAbsolute() && !binaryInfo.isExecutable()) { - gdbBinariesChanged = true; const QString msg = QString::fromLatin1("Warning: The gdb binary '%1' does not exist, skipping.\n").arg(binary); qWarning("%s", qPrintable(msg)); continue; } + // Create entries for all toolchains. tokens.pop_front(); foreach (const QString &t, tokens) { // Paranoia: Check if the there is already a binary configured for the toolchain. - const int toolChain = t.toInt(); - const QString predefinedGdb = gdbBinaryToolChainMap.key(toolChain); - if (predefinedGdb.isEmpty()) { - gdbBinaryToolChainMap.insert(binary, toolChain); - } else { - const QString toolChainName = - ProjectExplorer::ToolChain::toolChainName(ToolChainType(toolChain)); - const QString msg = - QString::fromLatin1("An inconsistency has been encountered in the Ini-file '%1':\n" - "Skipping gdb binary '%2' for toolchain '%3' as '%4' is already configured for it."). - arg(settings->fileName(), binary, toolChainName, predefinedGdb); - qWarning("%s", qPrintable(msg)); + QString abi; + switch (t.toInt()) + { + case 0: // GCC + case 1: // Linux ICC +#ifndef Q_OS_WIN + abi = ProjectExplorer::Abi::hostAbi().toString(); +#endif + break; + case 2: // MinGW + case 3: // MSVC + case 4: // WINCE +#ifdef Q_OS_WIN + abi = ProjectExplorer::Abi::hostAbi().toString(); +#endif + break; + case 5: // WINSCW + abi = ProjectExplorer::Abi(ProjectExplorer::Abi::ARM, ProjectExplorer::Abi::Symbian, + ProjectExplorer::Abi::Symbian_emulator, + ProjectExplorer::Abi::Format_ELF, + 32).toString(); + break; + case 6: // GCCE + case 7: // RVCT 2, ARM v5 + case 8: // RVCT 2, ARM v6 + case 11: // RVCT GNUPOC + case 12: // RVCT 4, ARM v5 + case 13: // RVCT 4, ARM v6 + abi = ProjectExplorer::Abi(ProjectExplorer::Abi::ARM, ProjectExplorer::Abi::Symbian, + ProjectExplorer::Abi::Symbian_device, + ProjectExplorer::Abi::Format_ELF, + 32).toString(); + break; + case 9: // GCC Maemo5 + abi = ProjectExplorer::Abi(ProjectExplorer::Abi::ARM, ProjectExplorer::Abi::Linux, + ProjectExplorer::Abi::Linux_maemo, + ProjectExplorer::Abi::Format_ELF, + 32).toString(); + + break; + case 14: // GCC Harmattan + abi = ProjectExplorer::Abi(ProjectExplorer::Abi::ARM, ProjectExplorer::Abi::Linux, + ProjectExplorer::Abi::Linux_harmattan, + ProjectExplorer::Abi::Format_ELF, + 32).toString(); + break; + case 15: // GCC Meego + abi = ProjectExplorer::Abi(ProjectExplorer::Abi::ARM, ProjectExplorer::Abi::Linux, + ProjectExplorer::Abi::Linux_meego, + ProjectExplorer::Abi::Format_ELF, + 32).toString(); + break; + default: + break; } + if (abi.isEmpty() || abiToGdbMap.contains(abi)) + continue; + + abiToGdbMap.insert(abi, binary); } } - // Linux defaults -#ifdef Q_OS_UNIX - if (gdbBinaryToolChainMap.isEmpty()) { - const QString gdb = QLatin1String("gdb"); - gdbBinaryToolChainMap.insert(gdb, ToolChain_GCC); - gdbBinaryToolChainMap.insert(gdb, ToolChain_LINUX_ICC); - gdbBinaryToolChainMap.insert(gdb, ToolChain_OTHER); - gdbBinaryToolChainMap.insert(gdb, ToolChain_UNKNOWN); - } -#endif + + gdbMappingChanged = false; } -void GdbOptionsPage::writeGdbBinarySettings() /* static */ +void GdbOptionsPage::writeGdbSettings() /* static */ { + // FIXME: This should actually get called in response to ICore::saveSettingsRequested() + if (!gdbMappingChanged) + return; + QSettings *settings = Core::ICore::instance()->settings(); - // Convert gdb binaries map into a flat settings list of - // ("binary1=gdb,1,2", "binary2=symbian_gdb,3,4"). It needs to be ASCII for installers - QString lastBinary; - QStringList settingsList; - const QChar separator = QLatin1Char(','); - const GdbBinaryToolChainMap::const_iterator cend = gdbBinaryToolChainMap.constEnd(); - for (GdbBinaryToolChainMap::const_iterator it = gdbBinaryToolChainMap.constBegin(); it != cend; ++it) { - if (it.key() != lastBinary) { - lastBinary = it.key(); // Start new entry with first toolchain - settingsList.push_back(lastBinary); - } - settingsList.back().append(separator); // Append toolchain to last binary - settingsList.back().append(QString::number(it.value())); + + settings->beginWriteArray(GDB_MAPPING_ARRAY); + + int index = 0; + for (QMap<QString, QString>::const_iterator i = abiToGdbMap.constBegin(); + i != abiToGdbMap.constEnd(); ++i) { + if (i.value().isEmpty()) + continue; + + settings->setArrayIndex(index); + ++index; + + settings->setValue(GDB_ABI_KEY, i.key()); + settings->setValue(GDB_BINARY_KEY, i.value()); } - // Terminate settings list by an empty element such that consecutive keys resulting - // from ini-file merging are suppressed while reading. - settingsList.push_back(QString()); - // Write out list - settings->beginGroup(QLatin1String(gdbBinariesSettingsGroupC)); - settings->remove(QString()); // remove all keys in group. - const int count = settingsList.size(); - const QString keyRoot = QLatin1String(debugModeGdbBinaryKeyC); - for (int i = 0; i < count; i++) - settings->setValue(keyRoot + QString::number(i + 1), settingsList.at(i)); - settings->endGroup(); + settings->endArray(); + + gdbMappingChanged = false; } GdbOptionsPage::GdbOptionsPage() : m_ui(0) -{ -} +{ } QString GdbOptionsPage::settingsId() { @@ -174,10 +224,41 @@ QIcon GdbOptionsPage::categoryIcon() const QWidget *GdbOptionsPage::createPage(QWidget *parent) { + // Fix up abi mapping now that the ToolChainManager is available: + connect(ProjectExplorer::ToolChainManager::instance(), SIGNAL(toolChainAdded(ProjectExplorer::ToolChain*)), + this, SLOT(handleToolChainAdditions(ProjectExplorer::ToolChain*))); + connect(ProjectExplorer::ToolChainManager::instance(), SIGNAL(toolChainRemoved(ProjectExplorer::ToolChain*)), + this, SLOT(handleToolChainRemovals(ProjectExplorer::ToolChain*))); + + // Update mapping now that toolchains are available + QList<ProjectExplorer::ToolChain *> tcs = + ProjectExplorer::ToolChainManager::instance()->toolChains(); + + QStringList abiList; + foreach (ProjectExplorer::ToolChain *tc, tcs) { + const QString abi = tc->targetAbi().toString(); + if (!abiList.contains(abi)) + abiList.append(abi); + if (!abiToGdbMap.contains(abi)) + handleToolChainAdditions(tc); + } + + QStringList toRemove; + for (QMap<QString, QString>::const_iterator i = abiToGdbMap.constBegin(); + i != abiToGdbMap.constEnd(); ++i) { + if (!abiList.contains(i.key())) + toRemove.append(i.key()); + } + + foreach (const QString &key, toRemove) + abiToGdbMap.remove(key); + + // Actual page setup: QWidget *w = new QWidget(parent); m_ui = new Ui::GdbOptionsPage; m_ui->setupUi(w); - m_ui->gdbChooserWidget->setGdbBinaries(gdbBinaryToolChainMap); + m_ui->gdbChooserWidget->setGdbMapping(abiToGdbMap); + m_ui->scriptFileChooser->setExpectedKind(Utils::PathChooser::File); m_ui->scriptFileChooser->setPromptDialogTitle(tr("Choose Location of Startup Script File")); @@ -201,18 +282,7 @@ QWidget *GdbOptionsPage::createPage(QWidget *parent) m_ui->checkBoxEnableReverseDebugging); m_group.insert(debuggerCore()->action(GdbWatchdogTimeout), 0); -#if 1 m_ui->groupBoxPluginDebugging->hide(); -#else // The related code (handleAqcuiredInferior()) is disabled as well. - m_group.insert(debuggerCore()->action(AllPluginBreakpoints), - m_ui->radioButtonAllPluginBreakpoints); - m_group.insert(debuggerCore()->action(SelectedPluginBreakpoints), - m_ui->radioButtonSelectedPluginBreakpoints); - m_group.insert(debuggerCore()->action(NoPluginBreakpoints), - m_ui->radioButtonNoPluginBreakpoints); - m_group.insert(debuggerCore()->action(SelectedPluginBreakpointsPattern), - m_ui->lineEditSelectedPluginBreakpointsPattern); -#endif m_ui->lineEditSelectedPluginBreakpointsPattern-> setEnabled(debuggerCore()->action(SelectedPluginBreakpoints)->value().toBool()); @@ -246,11 +316,12 @@ void GdbOptionsPage::apply() { if (!m_ui) // page never shown return; + m_group.apply(Core::ICore::instance()->settings()); if (m_ui->gdbChooserWidget->isDirty()) { - gdbBinariesChanged = true; - gdbBinaryToolChainMap = m_ui->gdbChooserWidget->gdbBinaries(); - m_ui->gdbChooserWidget->clearDirty(); + abiToGdbMap = m_ui->gdbChooserWidget->gdbMapping(); + m_ui->gdbChooserWidget->setGdbMapping(abiToGdbMap); + gdbMappingChanged = true; } } @@ -268,5 +339,37 @@ bool GdbOptionsPage::matches(const QString &s) const return m_searchKeywords.contains(s, Qt::CaseInsensitive); } +void GdbOptionsPage::handleToolChainAdditions(ProjectExplorer::ToolChain *tc) +{ + ProjectExplorer::Abi tcAbi = tc->targetAbi(); + + if (tcAbi.binaryFormat() != ProjectExplorer::Abi::Format_ELF + && tcAbi.binaryFormat() != ProjectExplorer::Abi::Format_Mach_O + && !( tcAbi.os() == ProjectExplorer::Abi::Windows + && tcAbi.osFlavor() == ProjectExplorer::Abi::Windows_msys )) + return; + if (abiToGdbMap.contains(tcAbi.toString())) + return; + + QString binary; +#ifdef Q_OS_UNIX + ProjectExplorer::Abi hostAbi = ProjectExplorer::Abi::hostAbi(); + if (hostAbi == tcAbi) + binary = QLatin1String("gdb"); +#endif + abiToGdbMap.insert(tc->targetAbi().toString(), binary); +} + +void GdbOptionsPage::handleToolChainRemovals(ProjectExplorer::ToolChain *tc) +{ + QList<ProjectExplorer::ToolChain *> tcs = ProjectExplorer::ToolChainManager::instance()->toolChains(); + foreach (ProjectExplorer::ToolChain *current, tcs) { + if (current->targetAbi() == tc->targetAbi()) + return; + } + + abiToGdbMap.remove(tc->targetAbi().toString()); +} + } // namespace Internal } // namespace Debugger diff --git a/src/plugins/debugger/gdb/gdboptionspage.h b/src/plugins/debugger/gdb/gdboptionspage.h index faf28cdcc3..3a7c9a2c74 100644 --- a/src/plugins/debugger/gdb/gdboptionspage.h +++ b/src/plugins/debugger/gdb/gdboptionspage.h @@ -39,6 +39,10 @@ #include <coreplugin/dialogs/ioptionspage.h> #include <utils/savedaction.h> +namespace ProjectExplorer { +class ToolChain; +} // namespace ProjectExplorer + namespace Debugger { namespace Internal { @@ -61,11 +65,15 @@ public: static QString settingsId(); - typedef QMultiMap<QString, int> GdbBinaryToolChainMap; - static GdbBinaryToolChainMap gdbBinaryToolChainMap; - static bool gdbBinariesChanged; - static void readGdbBinarySettings(); - static void writeGdbBinarySettings(); + typedef QMap<QString, QString> GdbBinaryToolChainMap; + static GdbBinaryToolChainMap abiToGdbMap; + static bool gdbMappingChanged; + static void readGdbSettings(); + static void writeGdbSettings(); + +private slots: + static void handleToolChainAdditions(ProjectExplorer::ToolChain *); + static void handleToolChainRemovals(ProjectExplorer::ToolChain *); private: Ui::GdbOptionsPage *m_ui; diff --git a/src/plugins/debugger/gdb/remotegdbserveradapter.cpp b/src/plugins/debugger/gdb/remotegdbserveradapter.cpp index 13b8a208f5..fcef41aca1 100644 --- a/src/plugins/debugger/gdb/remotegdbserveradapter.cpp +++ b/src/plugins/debugger/gdb/remotegdbserveradapter.cpp @@ -41,7 +41,7 @@ #include <utils/qtcassert.h> #include <utils/fancymainwindow.h> -#include <projectexplorer/toolchaintype.h> +#include <projectexplorer/abi.h> #include <QtCore/QFileInfo> #include <QtGui/QMessageBox> @@ -59,9 +59,11 @@ namespace Internal { // /////////////////////////////////////////////////////////////////////// -RemoteGdbServerAdapter::RemoteGdbServerAdapter(GdbEngine *engine, int toolChainType, QObject *parent) : +RemoteGdbServerAdapter::RemoteGdbServerAdapter(GdbEngine *engine, + const ProjectExplorer::Abi &abi, + QObject *parent) : AbstractGdbAdapter(engine, parent), - m_toolChainType(toolChainType) + m_abi(abi) { connect(&m_uploadProc, SIGNAL(error(QProcess::ProcessError)), SLOT(uploadProcError(QProcess::ProcessError))); @@ -75,21 +77,10 @@ RemoteGdbServerAdapter::RemoteGdbServerAdapter(GdbEngine *engine, int toolChainT AbstractGdbAdapter::DumperHandling RemoteGdbServerAdapter::dumperHandling() const { - switch (m_toolChainType) { - case ProjectExplorer::ToolChain_MinGW: - case ProjectExplorer::ToolChain_MSVC: - case ProjectExplorer::ToolChain_WINCE: - case ProjectExplorer::ToolChain_WINSCW: - case ProjectExplorer::ToolChain_GCCE: - case ProjectExplorer::ToolChain_RVCT2_ARMV5: - case ProjectExplorer::ToolChain_RVCT2_ARMV6: - case ProjectExplorer::ToolChain_GCC_MAEMO5: - case ProjectExplorer::ToolChain_GCC_HARMATTAN: - case ProjectExplorer::ToolChain_GCC_MEEGO: + if (m_abi.os() == ProjectExplorer::Abi::Symbian + || m_abi.os() == ProjectExplorer::Abi::Windows + || m_abi.binaryFormat() == ProjectExplorer::Abi::Format_ELF) return DumperLoadedByGdb; - default: - break; - } return DumperLoadedByGdbPreload; } diff --git a/src/plugins/debugger/gdb/remotegdbserveradapter.h b/src/plugins/debugger/gdb/remotegdbserveradapter.h index 342def5eb5..9c27b2ec44 100644 --- a/src/plugins/debugger/gdb/remotegdbserveradapter.h +++ b/src/plugins/debugger/gdb/remotegdbserveradapter.h @@ -37,6 +37,8 @@ #include "abstractgdbadapter.h" #include "localgdbprocess.h" +#include <projectexplorer/abi.h> + namespace Debugger { namespace Internal { @@ -51,7 +53,7 @@ class RemoteGdbServerAdapter : public AbstractGdbAdapter Q_OBJECT public: - RemoteGdbServerAdapter(GdbEngine *engine, int toolChainType, QObject *parent = 0); + RemoteGdbServerAdapter(GdbEngine *engine, const ProjectExplorer::Abi &abi, QObject *parent = 0); private: DumperHandling dumperHandling() const; @@ -93,7 +95,7 @@ private: void handleTargetRemote(const GdbResponse &response); void handleInterruptInferior(const GdbResponse &response); - const int m_toolChainType; + const ProjectExplorer::Abi m_abi; QProcess m_uploadProc; LocalGdbProcess m_gdbProc; diff --git a/src/plugins/genericprojectmanager/genericproject.cpp b/src/plugins/genericprojectmanager/genericproject.cpp index 5e99e170f4..77fc23dcb9 100644 --- a/src/plugins/genericprojectmanager/genericproject.cpp +++ b/src/plugins/genericprojectmanager/genericproject.cpp @@ -39,7 +39,7 @@ #include <projectexplorer/buildenvironmentwidget.h> #include <projectexplorer/customexecutablerunconfiguration.h> -#include <projectexplorer/toolchain.h> +#include <projectexplorer/toolchainmanager.h> #include <projectexplorer/projectexplorerconstants.h> #include <cplusplus/ModelManagerInterface.h> #include <extensionsystem/pluginmanager.h> @@ -90,7 +90,7 @@ GenericProject::~GenericProject() m_manager->unregisterProject(this); delete m_rootNode; - delete m_toolChain; + // do not delete m_toolChain } GenericTarget *GenericProject::activeTarget() const @@ -217,8 +217,8 @@ void GenericProject::refresh(RefreshOptions options) QStringList allIncludePaths; QStringList allFrameworkPaths; - foreach (const ProjectExplorer::HeaderPath &headerPath, m_toolChain->systemHeaderPaths()) { - if (headerPath.kind() == ProjectExplorer::HeaderPath::FrameworkHeaderPath) + foreach (const HeaderPath &headerPath, m_toolChain->systemHeaderPaths()) { + if (headerPath.kind() == HeaderPath::FrameworkHeaderPath) allFrameworkPaths.append(headerPath.path()); else allIncludePaths.append(headerPath.path()); @@ -328,44 +328,20 @@ void GenericProject::setIncludePaths(const QStringList &includePaths) QByteArray GenericProject::defines() const { return m_defines; } -void GenericProject::setToolChainType(ProjectExplorer::ToolChainType type) +void GenericProject::setToolChain(ToolChain *tc) { - using namespace ProjectExplorer; - - m_toolChainType = type; - - delete m_toolChain; - m_toolChain = 0; - - if (type == ToolChain_MinGW) { - const QLatin1String qmake_cxx("g++"); // ### FIXME - const QString mingwDirectory; // ### FIXME - - m_toolChain = ToolChain::createMinGWToolChain(qmake_cxx, mingwDirectory); - - } else if (type == ToolChain_MSVC) { - const QString msvcVersion; // ### FIXME - m_toolChain = ToolChain::createMSVCToolChain(msvcVersion, false); + if (m_toolChain == tc) + return; - } else if (type == ToolChain_WINCE) { - const QString msvcVersion, wincePlatform; // ### FIXME - m_toolChain = ToolChain::createWinCEToolChain(msvcVersion, wincePlatform); - } else if (type == ToolChain_GCC) { - const QLatin1String qmake_cxx("g++"); // ### FIXME - m_toolChain = ToolChain::createGccToolChain(qmake_cxx); - } else if (type == ToolChain_LINUX_ICC) { - m_toolChain = ToolChain::createLinuxIccToolChain(); - } + m_toolChain = tc; + emit toolChainChanged(m_toolChain); } -ProjectExplorer::ToolChain *GenericProject::toolChain() const +ToolChain *GenericProject::toolChain() const { return m_toolChain; } -ProjectExplorer::ToolChainType GenericProject::toolChainType() const -{ return m_toolChainType; } - QString GenericProject::displayName() const { return m_projectName; @@ -381,19 +357,19 @@ Core::IFile *GenericProject::file() const return m_file; } -ProjectExplorer::IProjectManager *GenericProject::projectManager() const +IProjectManager *GenericProject::projectManager() const { return m_manager; } -QList<ProjectExplorer::Project *> GenericProject::dependsOn() +QList<Project *> GenericProject::dependsOn() { return QList<Project *>(); } -QList<ProjectExplorer::BuildConfigWidget*> GenericProject::subConfigWidgets() +QList<BuildConfigWidget*> GenericProject::subConfigWidgets() { - QList<ProjectExplorer::BuildConfigWidget*> list; + QList<BuildConfigWidget*> list; list << new BuildEnvironmentWidget; return list; } @@ -420,7 +396,7 @@ QStringList GenericProject::buildTargets() const QVariantMap GenericProject::toMap() const { QVariantMap map(Project::toMap()); - map.insert(QLatin1String(TOOLCHAIN_KEY), static_cast<int>(m_toolChainType)); + map.insert(QLatin1String(TOOLCHAIN_KEY), m_toolChain ? m_toolChain->id() : QString()); return map; } @@ -438,7 +414,7 @@ bool GenericProject::fromMap(const QVariantMap &map) continue; } if (!t->activeRunConfiguration()) - t->addRunConfiguration(new ProjectExplorer::CustomExecutableRunConfiguration(t)); + t->addRunConfiguration(new CustomExecutableRunConfiguration(t)); } // Add default setup: @@ -448,11 +424,17 @@ bool GenericProject::fromMap(const QVariantMap &map) addTarget(factory->create(this, QLatin1String(GENERIC_DESKTOP_TARGET_ID))); } - ToolChainType type = - static_cast<ProjectExplorer::ToolChainType> - (map.value(QLatin1String(TOOLCHAIN_KEY), 0).toInt()); - - setToolChainType(type); + QString id = map.value(QLatin1String(TOOLCHAIN_KEY)).toString(); + if (!id.isNull()) { + setToolChain(ToolChainManager::instance()->findToolChain(id)); + } else { + QList<ToolChain *> tcs = + ToolChainManager::instance()->findToolChains(Abi::hostAbi()); + if (tcs.isEmpty()) + tcs = ToolChainManager::instance()->toolChains(); + if (!tcs.isEmpty()) + setToolChain(tcs.at(0)); + } setIncludePaths(allIncludePaths()); @@ -465,7 +447,7 @@ bool GenericProject::fromMap(const QVariantMap &map) //////////////////////////////////////////////////////////////////////////////////// GenericBuildSettingsWidget::GenericBuildSettingsWidget(GenericTarget *target) - : m_target(target), m_buildConfiguration(0) + : m_target(target), m_toolChainChooser(0), m_buildConfiguration(0) { QFormLayout *fl = new QFormLayout(this); fl->setContentsMargins(0, -1, 0, -1); @@ -479,21 +461,18 @@ GenericBuildSettingsWidget::GenericBuildSettingsWidget(GenericTarget *target) connect(m_pathChooser, SIGNAL(changed(QString)), this, SLOT(buildDirectoryChanged())); // tool chain - QComboBox *toolChainChooser = new QComboBox; - toolChainChooser->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); - using namespace ProjectExplorer; - int index = 0; - int selectedIndex = -1; - foreach (ToolChainType tc, ToolChain::supportedToolChains()) { - toolChainChooser->addItem(ToolChain::toolChainName(tc), QVariant::fromValue<ToolChainType>(tc)); - if (m_target->genericProject()->toolChainType() == tc) - selectedIndex = index; - ++index; - } + m_toolChainChooser = new QComboBox; + m_toolChainChooser->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); + updateToolChainList(); - toolChainChooser->setCurrentIndex(selectedIndex); - fl->addRow(tr("Tool chain:"), toolChainChooser); - connect(toolChainChooser, SIGNAL(activated(int)), this, SLOT(toolChainSelected(int))); + fl->addRow(tr("Tool chain:"), m_toolChainChooser); + connect(m_toolChainChooser, SIGNAL(activated(int)), this, SLOT(toolChainSelected(int))); + connect(m_target->genericProject(), SIGNAL(toolChainChanged(ProjectExplorer::ToolChain*)), + this, SLOT(toolChainChanged(ProjectExplorer::ToolChain*))); + connect(ProjectExplorer::ToolChainManager::instance(), SIGNAL(toolChainAdded(ToolChain*)), + this, SLOT(updateToolChainList())); + connect(ProjectExplorer::ToolChainManager::instance(), SIGNAL(toolChainRemoved(ToolChain*)), + this, SLOT(updateToolChainList())); } GenericBuildSettingsWidget::~GenericBuildSettingsWidget() @@ -517,9 +496,36 @@ void GenericBuildSettingsWidget::toolChainSelected(int index) { using namespace ProjectExplorer; - QComboBox *toolChainChooser = qobject_cast<QComboBox*>(sender()); - ToolChainType type = toolChainChooser->itemData(index).value<ToolChainType>(); - m_target->genericProject()->setToolChainType(type); + ToolChain *tc = static_cast<ToolChain *>(m_toolChainChooser->itemData(index).value<void *>()); + m_target->genericProject()->setToolChain(tc); +} + +void GenericBuildSettingsWidget::toolChainChanged(ProjectExplorer::ToolChain *tc) +{ + for (int i = 0; i < m_toolChainChooser->count(); ++i) { + ToolChain * currentTc = static_cast<ToolChain *>(m_toolChainChooser->itemData(i).value<void *>()); + if (currentTc != tc) + continue; + m_toolChainChooser->setCurrentIndex(i); + return; + } +} + +void GenericBuildSettingsWidget::updateToolChainList() +{ + m_toolChainChooser->clear(); + + QList<ToolChain *> tcs = ToolChainManager::instance()->toolChains(); + if (!m_target->genericProject()->toolChain()) { + m_toolChainChooser->addItem(tr("<Invalid Toolchain>"), qVariantFromValue(static_cast<void *>(0))); + m_toolChainChooser->setCurrentIndex(0); + } + foreach (ToolChain *tc, tcs) { + m_toolChainChooser->addItem(tc->displayName(), qVariantFromValue(static_cast<void *>(tc))); + if (m_target->genericProject()->toolChain() + && m_target->genericProject()->toolChain()->id() == tc->id()) + m_toolChainChooser->setCurrentIndex(m_toolChainChooser->count() - 1); + } } //////////////////////////////////////////////////////////////////////////////////// diff --git a/src/plugins/genericprojectmanager/genericproject.h b/src/plugins/genericprojectmanager/genericproject.h index 6997c8696c..9c95a25ea1 100644 --- a/src/plugins/genericprojectmanager/genericproject.h +++ b/src/plugins/genericprojectmanager/genericproject.h @@ -41,13 +41,17 @@ #include <projectexplorer/project.h> #include <projectexplorer/projectnodes.h> #include <projectexplorer/target.h> +#include <projectexplorer/toolchain.h> #include <projectexplorer/buildstep.h> -#include <projectexplorer/toolchaintype.h> #include <projectexplorer/buildconfiguration.h> #include <coreplugin/ifile.h> #include <QtCore/QFuture> +QT_BEGIN_NAMESPACE +class QComboBox; +QT_END_NAMESPACE + namespace Utils { class PathChooser; } @@ -90,7 +94,6 @@ public: QStringList files(FilesMode fileMode) const; QStringList buildTargets() const; - ProjectExplorer::ToolChain *toolChain() const; bool addFiles(const QStringList &filePaths); bool removeFiles(const QStringList &filePaths); @@ -111,11 +114,14 @@ public: QStringList projectIncludePaths() const; QStringList files() const; QStringList generated() const; - ProjectExplorer::ToolChainType toolChainType() const; - void setToolChainType(ProjectExplorer::ToolChainType type); + ProjectExplorer::ToolChain *toolChain() const; + void setToolChain(ProjectExplorer::ToolChain *tc); QVariantMap toMap() const; +signals: + void toolChainChanged(ProjectExplorer::ToolChain *); + protected: virtual bool fromMap(const QVariantMap &map); @@ -143,7 +149,6 @@ private: GenericProjectNode *m_rootNode; ProjectExplorer::ToolChain *m_toolChain; - ProjectExplorer::ToolChainType m_toolChainType; QFuture<void> m_codeModelFuture; }; @@ -190,10 +195,13 @@ public: private Q_SLOTS: void buildDirectoryChanged(); void toolChainSelected(int index); + void toolChainChanged(ProjectExplorer::ToolChain *); + void updateToolChainList(); private: GenericTarget *m_target; Utils::PathChooser *m_pathChooser; + QComboBox *m_toolChainChooser; GenericBuildConfiguration *m_buildConfiguration; }; diff --git a/src/plugins/projectexplorer/abi.cpp b/src/plugins/projectexplorer/abi.cpp new file mode 100644 index 0000000000..3a02abfc39 --- /dev/null +++ b/src/plugins/projectexplorer/abi.cpp @@ -0,0 +1,429 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** No Commercial Usage +** +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +**************************************************************************/ + +#include "abi.h" + +#include <QtCore/QCoreApplication> +#include <QtCore/QFile> +#include <QtCore/QString> +#include <QtCore/QStringList> +#include <QtCore/QSysInfo> + +namespace ProjectExplorer { + +Abi::Abi(const Architecture &a, const OS &o, + const OSFlavour &of, const BinaryFormat &f, unsigned char w) : + m_architecture(a), m_os(o), m_osFlavor(of), m_binaryFormat(f), m_wordWidth(w) +{ + switch (m_os) { + case ProjectExplorer::Abi::UNKNOWN_OS: + m_osFlavor = UNKNOWN_OSFLAVOUR; + break; + case ProjectExplorer::Abi::Linux: + if (m_osFlavor < Linux_generic || m_osFlavor > Linux_meego) + m_osFlavor = UNKNOWN_OSFLAVOUR; + break; + case ProjectExplorer::Abi::Mac: + if (m_osFlavor < Mac_generic || m_osFlavor > Mac_generic) + m_osFlavor = UNKNOWN_OSFLAVOUR; + break; + case ProjectExplorer::Abi::Symbian: + if (m_osFlavor < Symbian_device || m_osFlavor > Symbian_emulator) + m_osFlavor = UNKNOWN_OSFLAVOUR; + break; + case ProjectExplorer::Abi::UNIX: + if (m_osFlavor < Unix_generic || m_osFlavor > Unix_generic) + m_osFlavor = UNKNOWN_OSFLAVOUR; + break; + case ProjectExplorer::Abi::Windows: + if (m_osFlavor < Windows_msvc || m_osFlavor > Windows_ce) + m_osFlavor = UNKNOWN_OSFLAVOUR; + break; + } +} + +Abi::Abi(const QString &abiString) : + m_architecture(UNKNOWN_ARCHITECTURE), m_os(UNKNOWN_OS), + m_osFlavor(UNKNOWN_OSFLAVOUR), m_binaryFormat(UNKNOWN_FORMAT), m_wordWidth(0) +{ + QStringList abiParts = abiString.split(QLatin1Char('-')); + if (abiParts.count() >= 1) { + if (abiParts.at(0) == QLatin1String("unknown")) + m_architecture = UNKNOWN_ARCHITECTURE; + else if (abiParts.at(0) == QLatin1String("arm")) + m_architecture = ARM; + else if (abiParts.at(0) == QLatin1String("x86")) + m_architecture = x86; + else if (abiParts.at(0) == QLatin1String("mips")) + m_architecture = Mips; + else if (abiParts.at(0) == QLatin1String("ppc")) + m_architecture = PowerPC; + else if (abiParts.at(0) == QLatin1String("itanium")) + m_architecture = Itanium; + else + return; + } + + if (abiParts.count() >= 2) { + if (abiParts.at(1) == QLatin1String("unknown")) + m_os = UNKNOWN_OS; + else if (abiParts.at(1) == QLatin1String("linux")) + m_os = Linux; + else if (abiParts.at(1) == QLatin1String("macos")) + m_os = Mac; + else if (abiParts.at(1) == QLatin1String("symbian")) + m_os = Symbian; + else if (abiParts.at(1) == QLatin1String("unix")) + m_os = UNIX; + else if (abiParts.at(1) == QLatin1String("windows")) + m_os = Windows; + else + return; + } + + if (abiParts.count() >= 3) { + if (abiParts.at(2) == QLatin1String("unknown")) + m_osFlavor = UNKNOWN_OSFLAVOUR; + else if (abiParts.at(2) == QLatin1String("generic") && m_os == Linux) + m_osFlavor = Linux_generic; + else if (abiParts.at(2) == QLatin1String("maemo") && m_os == Linux) + m_osFlavor = Linux_maemo; + else if (abiParts.at(2) == QLatin1String("meego") && m_os == Linux) + m_osFlavor = Linux_meego; + else if (abiParts.at(2) == QLatin1String("generic") && m_os == Mac) + m_osFlavor = Mac_generic; + else if (abiParts.at(2) == QLatin1String("device") && m_os == Symbian) + m_osFlavor = Symbian_device; + else if (abiParts.at(2) == QLatin1String("emulator") && m_os == Symbian) + m_osFlavor = Symbian_emulator; + else if (abiParts.at(2) == QLatin1String("generic") && m_os == UNIX) + m_osFlavor = Unix_generic; + else if (abiParts.at(2) == QLatin1String("msvc") && m_os == Windows) + m_osFlavor = Windows_msvc; + else if (abiParts.at(2) == QLatin1String("msys") && m_os == Windows) + m_osFlavor = Windows_msys; + else if (abiParts.at(2) == QLatin1String("ce") && m_os == Windows) + m_osFlavor = Windows_ce; + else + return; + } + + if (abiParts.count() >= 4) { + if (abiParts.at(3) == QLatin1String("unknown")) + m_binaryFormat = UNKNOWN_FORMAT; + else if (abiParts.at(3) == QLatin1String("elf")) + m_binaryFormat = Format_ELF; + else if (abiParts.at(3) == QLatin1String("pe")) + m_binaryFormat = Format_PE; + else if (abiParts.at(3) == QLatin1String("mach_o")) + m_binaryFormat = Format_Mach_O; + else if (abiParts.at(3) == QLatin1String("qml_rt")) + m_binaryFormat = Format_Runtime_QML; + else + return; + } + + if (abiParts.count() >= 5) { + const QString &bits = abiParts.at(4); + if (!bits.endsWith(QLatin1String("bit"))) + return; + + bool ok = false; + int bitCount = bits.left(bits.count() - 3).toInt(&ok); + if (!ok) + return; + if (bitCount != 8 && bitCount != 16 && bitCount != 32 && bitCount != 64) + return; + m_wordWidth = bitCount; + } +} + +QString Abi::toString() const +{ + QStringList dn; + dn << toString(m_architecture); + dn << toString(m_os); + dn << toString(m_osFlavor); + dn << toString(m_binaryFormat); + dn << toString(m_wordWidth); + + return dn.join(QLatin1String("-")); +} + +bool Abi::operator == (const Abi &other) const +{ + return m_architecture == other.m_architecture + && m_os == other.m_os + && m_osFlavor == other.m_osFlavor + && m_binaryFormat == other.m_binaryFormat + && m_wordWidth == other.m_wordWidth; +} + +bool Abi::isCompatibleWith(const Abi &other) const +{ + return (architecture() == other.architecture() || other.architecture() == Abi::UNKNOWN_ARCHITECTURE) + && (os() == other.os() || other.os() == Abi::UNKNOWN_OS) + && (osFlavor() == other.osFlavor() || other.osFlavor() == Abi::UNKNOWN_OSFLAVOUR) + && (binaryFormat() == other.binaryFormat() || other.binaryFormat() == Abi::UNKNOWN_FORMAT) + && ((wordWidth() == other.wordWidth() && wordWidth() != 0) || other.wordWidth() == 0); +} + +bool Abi::isValid() const +{ + return m_architecture != UNKNOWN_ARCHITECTURE + && m_os != UNKNOWN_OS + && m_osFlavor != UNKNOWN_OSFLAVOUR + && m_binaryFormat != UNKNOWN_FORMAT + && m_wordWidth != 0; +} + +QString Abi::toString(const Architecture &a) +{ + switch (a) { + case ARM: + return QLatin1String("arm"); + case x86: + return QLatin1String("x86"); + case Mips: + return QLatin1String("mips"); + case PowerPC: + return QLatin1String("ppc"); + case Itanium: + return QLatin1String("itanium"); + case UNKNOWN_ARCHITECTURE: // fall through! + default: + return QLatin1String("unknown"); + } +} + +QString Abi::toString(const OS &o) +{ + switch (o) { + case Linux: + return QLatin1String("linux"); + case Mac: + return QLatin1String("macos"); + case Symbian: + return QLatin1String("symbian"); + case UNIX: + return QLatin1String("unix"); + case Windows: + return QLatin1String("windows"); + case UNKNOWN_OS: // fall through! + default: + return QLatin1String("unknown"); + }; +} + +QString Abi::toString(const OSFlavour &of) +{ + switch (of) { + case ProjectExplorer::Abi::Linux_generic: + return QLatin1String("generic"); + case ProjectExplorer::Abi::Linux_maemo: + return QLatin1String("maemo"); + case ProjectExplorer::Abi::Linux_harmattan: + return QLatin1String("harmattan"); + case ProjectExplorer::Abi::Linux_meego: + return QLatin1String("meego"); + case ProjectExplorer::Abi::Mac_generic: + return QLatin1String("generic"); + case ProjectExplorer::Abi::Symbian_device: + return QLatin1String("device"); + case ProjectExplorer::Abi::Symbian_emulator: + return QLatin1String("emulator"); + case ProjectExplorer::Abi::Unix_generic: + return QLatin1String("generic"); + case ProjectExplorer::Abi::Windows_msvc: + return QLatin1String("msvc"); + case ProjectExplorer::Abi::Windows_msys: + return QLatin1String("msys"); + case ProjectExplorer::Abi::Windows_ce: + return QLatin1String("ce"); + case ProjectExplorer::Abi::UNKNOWN_OSFLAVOUR: // fall throught! + default: + return QLatin1String("unknown"); + } +} + +QString Abi::toString(const BinaryFormat &bf) +{ + switch (bf) { + case Format_ELF: + return QLatin1String("elf"); + case Format_PE: + return QLatin1String("pe"); + case Format_Mach_O: + return QLatin1String("mach_o"); + case Format_Runtime_QML: + return QLatin1String("qml_rt"); + case UNKNOWN_FORMAT: // fall through! + default: + return QLatin1String("unknown"); + } +} + +QString Abi::toString(int w) +{ + if (w == 0) + return QLatin1String("unknown"); + return QString::fromLatin1("%1bit").arg(w); +} + + +Abi Abi::hostAbi() +{ + Architecture arch = QTC_CPU; // define set by qmake + OS os = UNKNOWN_OS; + OSFlavour subos = UNKNOWN_OSFLAVOUR; + BinaryFormat format = UNKNOWN_FORMAT; + +#if defined (Q_OS_WIN) + os = Windows; + subos = Windows_msvc; + format = Format_PE; +#elif defined (Q_OS_LINUX) + os = Linux; + subos = Linux_generic; + format = Format_ELF; +#elif defined (Q_OS_MAC) + os = Mac; + subos = Mac_generic; + format = Format_Mach_O; +#endif + + return Abi(arch, os, subos, format, QSysInfo::WordSize); +} + +static Abi macAbiForCpu(quint32 type) { + switch (type) { + case 7: // CPU_TYPE_X86, CPU_TYPE_I386 + return Abi(Abi::x86, Abi::Mac, Abi::Mac_generic, Abi::Format_Mach_O, 32); + case 0x01000000 + 7: // CPU_TYPE_X86_64 + return Abi(Abi::x86, Abi::Mac, Abi::Mac_generic, Abi::Format_Mach_O, 64); + case 18: // CPU_TYPE_POWERPC + return Abi(Abi::PowerPC, Abi::Mac, Abi::Mac_generic, Abi::Format_Mach_O, 32); + case 0x01000000 + 18: // CPU_TYPE_POWERPC64 + return Abi(Abi::PowerPC, Abi::Mac, Abi::Mac_generic, Abi::Format_Mach_O, 32); + case 12: // CPU_TYPE_ARM + return Abi(Abi::ARM, Abi::Mac, Abi::Mac_generic, Abi::Format_Mach_O, 32); + default: + return Abi(); + } +} + +QList<Abi> Abi::abisOfBinary(const QString &path) +{ + QList<Abi> result; + if (path.isEmpty()) + return result; + + QFile f(path); + if (!f.exists()) + return result; + + f.open(QFile::ReadOnly); + QByteArray data = f.read(1024); + f.close(); + + if (data.size() >= 20 + && static_cast<unsigned char>(data.at(0)) == 0x7f && static_cast<unsigned char>(data.at(1)) == 'E' + && static_cast<unsigned char>(data.at(2)) == 'L' && static_cast<unsigned char>(data.at(3)) == 'F') { + // ELF format: + quint16 machine = (data.at(19) << 8) + data.at(18); + switch (machine) { + case 3: // EM_386 + result.append(Abi(Abi::x86, Abi::Linux, Abi::Linux_generic, Abi::Format_ELF, 32)); + break; + case 8: // EM_MIPS + result.append(Abi(Abi::Mips, Abi::Linux, Abi::Linux_generic, Abi::Format_ELF, 32)); + break; + case 20: // EM_PPC + result.append(Abi(Abi::PowerPC, Abi::Linux, Abi::Linux_generic, Abi::Format_ELF, 32)); + break; + case 21: // EM_PPC64 + result.append(Abi(Abi::PowerPC, Abi::Linux, Abi::Linux_generic, Abi::Format_ELF, 64)); + break; + case 62: // EM_X86_64 + result.append(Abi(Abi::x86, Abi::Linux, Abi::Linux_generic, Abi::Format_ELF, 64)); + break; + case 50: // EM_IA_64 + result.append(Abi(Abi::Itanium, Abi::Linux, Abi::Linux_generic, Abi::Format_ELF, 64)); + break; + default: + ;; + } + } else if (data.size() >= 8 + && (static_cast<unsigned char>(data.at(0)) == 0xce || static_cast<unsigned char>(data.at(0)) == 0xcf) + && static_cast<unsigned char>(data.at(1)) == 0xfa + && static_cast<unsigned char>(data.at(2)) == 0xed && static_cast<unsigned char>(data.at(3)) == 0xfe) { + // Mach-O format (Mac non-fat binary, 32 and 64bit magic) + quint32 type = (data.at(7) << 24) + (data.at(6) << 16) + (data.at(5) << 8) + data.at(4); + result.append(macAbiForCpu(type)); + } else if (data.size() >= 8 + && static_cast<unsigned char>(data.at(0)) == 0xca && static_cast<unsigned char>(data.at(1)) == 0xfe + && static_cast<unsigned char>(data.at(2)) == 0xba && static_cast<unsigned char>(data.at(3)) == 0xbe) { + // Mac fat binary: + quint32 count = (data.at(4) << 24) + (data.at(5) << 16) + (data.at(6) << 8) + data.at(7); + int pos = 8; + for (quint32 i = 0; i < count; ++i) { + if (data.size() <= pos + 4) + break; + + quint32 type = (data.at(pos) << 24) + (data.at(pos + 1) << 16) + (data.at(pos + 2) << 8) + data.at(pos + 3); + result.append(macAbiForCpu(type)); + pos += 20; + } + } else { + // Windows PE + // Windows can have its magic bytes everywhere... + int pePos = data.indexOf("PE\0\0"); + if (pePos >= 0 && pePos + 5 < data.size()) { + quint16 machine = (data.at(pePos + 5) << 8) + data.at(pePos + 4); + switch (machine) { + case 0x8664: // x86_64 + result.append(Abi(Abi::x86, Abi::Windows, Abi::Windows_msvc, Abi::Format_PE, 64)); + break; + case 0x014c: // i386 + result.append(Abi(Abi::x86, Abi::Windows, Abi::Windows_msvc, Abi::Format_PE, 32)); + break; + case 0x0200: // ia64 + result.append(Abi(Abi::Itanium, Abi::Windows, Abi::Windows_msvc, Abi::Format_PE, 64)); + break; + } + } + } + return result; +} + +} // namespace ProjectExplorer diff --git a/src/plugins/projectexplorer/abi.h b/src/plugins/projectexplorer/abi.h new file mode 100644 index 0000000000..069eec4f32 --- /dev/null +++ b/src/plugins/projectexplorer/abi.h @@ -0,0 +1,142 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** No Commercial Usage +** +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +**************************************************************************/ + +#ifndef PROJECTEXPLORER_ABI_H +#define PROJECTEXPLORER_ABI_H + +#include "projectexplorer_export.h" + +#include <QtCore/QList> + +namespace ProjectExplorer { + +// -------------------------------------------------------------------------- +// ABI +// -------------------------------------------------------------------------- + +class PROJECTEXPLORER_EXPORT Abi +{ +public: + enum Architecture { + UNKNOWN_ARCHITECTURE, + ARM, + x86, + Itanium, + Mips, + PowerPC + }; + + enum OS { + UNKNOWN_OS, + Linux, + Mac, + Symbian, + UNIX, + Windows + }; + + enum OSFlavour { + UNKNOWN_OSFLAVOUR, + + // Linux + Linux_generic, + Linux_harmattan, + Linux_maemo, + Linux_meego, + + // Mac + Mac_generic, + + // Symbian + Symbian_device, + Symbian_emulator, + + // Unix + Unix_generic, + + // Windows + Windows_msvc, + Windows_msys, + Windows_ce + }; + + enum BinaryFormat { + UNKNOWN_FORMAT, + Format_ELF, + Format_Mach_O, + Format_PE, + Format_Runtime_QML + }; + + Abi() : + m_architecture(UNKNOWN_ARCHITECTURE), m_os(UNKNOWN_OS), + m_osFlavor(UNKNOWN_OSFLAVOUR), m_binaryFormat(UNKNOWN_FORMAT), m_wordWidth(0) + { } + + Abi(const Architecture &a, const OS &o, + const OSFlavour &so, const BinaryFormat &f, unsigned char w); + Abi(const QString &abiString); + + bool operator == (const Abi &other) const; + bool isCompatibleWith(const Abi &other) const; + + bool isValid() const; + + Architecture architecture() const { return m_architecture; } + OS os() const { return m_os; } + OSFlavour osFlavor() const { return m_osFlavor; } + BinaryFormat binaryFormat() const { return m_binaryFormat; } + unsigned char wordWidth() const { return m_wordWidth; } + + QString toString() const; + + static QString toString(const Architecture &a); + static QString toString(const OS &o); + static QString toString(const OSFlavour &of); + static QString toString(const BinaryFormat &bf); + static QString toString(int w); + + static Abi hostAbi(); + static QList<Abi> abisOfBinary(const QString &path); + +private: + Architecture m_architecture; + OS m_os; + OSFlavour m_osFlavor; + BinaryFormat m_binaryFormat; + unsigned char m_wordWidth; +}; + +} // namespace ProjectExplorer + +#endif // PROJECTEXPLORER_ABI_H diff --git a/src/plugins/projectexplorer/applicationrunconfiguration.h b/src/plugins/projectexplorer/applicationrunconfiguration.h index d6441dbcf4..4faadd19c4 100644 --- a/src/plugins/projectexplorer/applicationrunconfiguration.h +++ b/src/plugins/projectexplorer/applicationrunconfiguration.h @@ -34,11 +34,11 @@ #ifndef APPLICATIONRUNCONFIGURATION_H #define APPLICATIONRUNCONFIGURATION_H -#include <projectexplorer/toolchaintype.h> - #include "runconfiguration.h" #include "applicationlauncher.h" +#include "abi.h" + namespace Utils { class AbstractMacroExpander; class Environment; @@ -63,7 +63,6 @@ public: virtual Utils::Environment environment() const = 0; virtual QString dumperLibrary() const = 0; virtual QStringList dumperLibraryLocations() const = 0; - virtual ProjectExplorer::ToolChainType toolChainType() const = 0; protected: explicit LocalApplicationRunConfiguration(Target *target, const QString &id); diff --git a/src/plugins/projectexplorer/buildconfiguration.cpp b/src/plugins/projectexplorer/buildconfiguration.cpp index a6735d8128..40e81d3c91 100644 --- a/src/plugins/projectexplorer/buildconfiguration.cpp +++ b/src/plugins/projectexplorer/buildconfiguration.cpp @@ -38,6 +38,7 @@ #include "projectexplorer.h" #include "projectexplorerconstants.h" #include "target.h" +#include "toolchainmanager.h" #include "project.h" #include <coreplugin/variablemanager.h> @@ -52,13 +53,15 @@ const char * const BUILD_STEP_LIST_COUNT("ProjectExplorer.BuildConfiguration.Bui const char * const BUILD_STEP_LIST_PREFIX("ProjectExplorer.BuildConfiguration.BuildStepList."); const char * const CLEAR_SYSTEM_ENVIRONMENT_KEY("ProjectExplorer.BuildConfiguration.ClearSystemEnvironment"); const char * const USER_ENVIRONMENT_CHANGES_KEY("ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"); +const char * const TOOLCHAIN_KEY("ProjectExplorer.BuildCOnfiguration.ToolChain"); } // namespace BuildConfiguration::BuildConfiguration(Target *target, const QString &id) : ProjectConfiguration(target, id), m_clearSystemEnvironment(false), - m_macroExpander(this) + m_macroExpander(this), + m_toolChain(0) { Q_ASSERT(target); BuildStepList *bsl = new BuildStepList(this, QLatin1String(Constants::BUILDSTEPS_BUILD)); @@ -75,7 +78,8 @@ BuildConfiguration::BuildConfiguration(Target *target, BuildConfiguration *sourc ProjectConfiguration(target, source), m_clearSystemEnvironment(source->m_clearSystemEnvironment), m_userEnvironmentChanges(source->m_userEnvironmentChanges), - m_macroExpander(this) + m_macroExpander(this), + m_toolChain(source->m_toolChain) { Q_ASSERT(target); // Do not clone stepLists here, do that in the derived constructor instead @@ -112,6 +116,8 @@ QVariantMap BuildConfiguration::toMap() const for (int i = 0; i < m_stepLists.count(); ++i) map.insert(QLatin1String(BUILD_STEP_LIST_PREFIX) + QString::number(i), m_stepLists.at(i)->toMap()); + map.insert(QLatin1String(TOOLCHAIN_KEY), m_toolChain ? m_toolChain->id() : QLatin1String("INVALID")); + return map; } @@ -139,6 +145,9 @@ bool BuildConfiguration::fromMap(const QVariantMap &map) m_stepLists.append(list); } + QString id = map.value(QLatin1String(TOOLCHAIN_KEY)).toString(); + m_toolChain = ToolChainManager::instance()->findToolChain(id); + // TODO: We currently assume there to be at least a clean and build list! Q_ASSERT(knownStepLists().contains(QLatin1String(ProjectExplorer::Constants::BUILDSTEPS_BUILD))); Q_ASSERT(knownStepLists().contains(QLatin1String(ProjectExplorer::Constants::BUILDSTEPS_CLEAN))); @@ -151,6 +160,19 @@ Target *BuildConfiguration::target() const return static_cast<Target *>(parent()); } +ProjectExplorer::ToolChain *BuildConfiguration::toolChain() const +{ + return m_toolChain; +} + +void BuildConfiguration::setToolChain(ProjectExplorer::ToolChain *tc) +{ + if (m_toolChain == tc) + return; + m_toolChain = tc; + emit toolChainChanged(); +} + Utils::Environment BuildConfiguration::baseEnvironment() const { Utils::Environment result; diff --git a/src/plugins/projectexplorer/buildconfiguration.h b/src/plugins/projectexplorer/buildconfiguration.h index 780304cc56..f60597bcad 100644 --- a/src/plugins/projectexplorer/buildconfiguration.h +++ b/src/plugins/projectexplorer/buildconfiguration.h @@ -43,13 +43,12 @@ #include <QtCore/QString> #include <QtCore/QStringList> - - namespace ProjectExplorer { class BuildConfiguration; class BuildStepList; class Target; +class ToolChain; class IOutputParser; class BuildConfigMacroExpander : public Utils::AbstractQtcMacroExpander { @@ -97,10 +96,14 @@ public: Utils::AbstractMacroExpander *macroExpander() { return &m_macroExpander; } + virtual ProjectExplorer::ToolChain *toolChain() const; + virtual void setToolChain(ProjectExplorer::ToolChain *tc); + signals: void environmentChanged(); void buildDirectoryChanged(); void enabledChanged(); + void toolChainChanged(); protected: BuildConfiguration(Target *target, const QString &id); @@ -115,6 +118,7 @@ private: QList<Utils::EnvironmentItem> m_userEnvironmentChanges; QList<BuildStepList *> m_stepLists; BuildConfigMacroExpander m_macroExpander; + ToolChain *m_toolChain; }; class PROJECTEXPLORER_EXPORT IBuildConfigurationFactory : diff --git a/src/plugins/projectexplorer/customexecutablerunconfiguration.cpp b/src/plugins/projectexplorer/customexecutablerunconfiguration.cpp index dcfc7c9cf9..fdf4e0dd62 100644 --- a/src/plugins/projectexplorer/customexecutablerunconfiguration.cpp +++ b/src/plugins/projectexplorer/customexecutablerunconfiguration.cpp @@ -33,11 +33,11 @@ #include "customexecutablerunconfiguration.h" #include "customexecutableconfigurationwidget.h" -#include "toolchaintype.h" + #include "buildconfiguration.h" #include "debugginghelper.h" -#include "target.h" #include "projectexplorerconstants.h" +#include "target.h" #include <coreplugin/icore.h> @@ -334,9 +334,9 @@ QStringList CustomExecutableRunConfiguration::dumperLibraryLocations() const return ProjectExplorer::DebuggingHelperLibrary::locationsByInstallData(qtInstallData); } -ProjectExplorer::ToolChainType CustomExecutableRunConfiguration::toolChainType() const +ProjectExplorer::Abi CustomExecutableRunConfiguration::abi() const { - return ProjectExplorer::ToolChain_UNKNOWN; + return ProjectExplorer::Abi::hostAbi(); } // Factory diff --git a/src/plugins/projectexplorer/customexecutablerunconfiguration.h b/src/plugins/projectexplorer/customexecutablerunconfiguration.h index 99dcf9c8b3..76c10c1140 100644 --- a/src/plugins/projectexplorer/customexecutablerunconfiguration.h +++ b/src/plugins/projectexplorer/customexecutablerunconfiguration.h @@ -79,7 +79,7 @@ public: QString dumperLibrary() const; QStringList dumperLibraryLocations() const; - ProjectExplorer::ToolChainType toolChainType() const; + ProjectExplorer::Abi abi() const; QVariantMap toMap() const; diff --git a/src/plugins/projectexplorer/gcctoolchain.cpp b/src/plugins/projectexplorer/gcctoolchain.cpp new file mode 100644 index 0000000000..a7323ceb2e --- /dev/null +++ b/src/plugins/projectexplorer/gcctoolchain.cpp @@ -0,0 +1,786 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** No Commercial Usage +** +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +**************************************************************************/ + +#include "gcctoolchain.h" +#include "gccparser.h" +#include "linuxiccparser.h" +#include "projectexplorerconstants.h" + +#include <utils/environment.h> +#include <utils/synchronousprocess.h> + +#include <QtCore/QBuffer> +#include <QtCore/QCoreApplication> +#include <QtCore/QFileInfo> +#include <QtCore/QProcess> + +#include <QtGui/QGridLayout> +#include <QtGui/QLabel> +#include <QtGui/QCheckBox> + +namespace ProjectExplorer { + +// -------------------------------------------------------------------------- +// Helpers: +// -------------------------------------------------------------------------- + +static const char *const COMPILER_PATH_KEY = "ProjectExplorer.GccToolChain.Path"; +static const char *const FORCE_32BIT_KEY = "ProjectExplorer.GccToolChain.Force32Bit"; + +static QByteArray runGcc(const QString &gcc, const QStringList &arguments, const QStringList &env) +{ + if (gcc.isEmpty()) + return QByteArray(); + + QProcess cpp; + cpp.setEnvironment(env); + cpp.start(gcc, arguments); + if (!cpp.waitForStarted()) { + qWarning("%s: Cannot start '%s': %s", Q_FUNC_INFO, qPrintable(gcc), + qPrintable(cpp.errorString())); + return QByteArray(); + } + cpp.closeWriteChannel(); + if (!cpp.waitForFinished()) { + Utils::SynchronousProcess::stopProcess(cpp); + qWarning("%s: Timeout running '%s'.", Q_FUNC_INFO, qPrintable(gcc)); + return QByteArray(); + } + if (cpp.exitStatus() != QProcess::NormalExit) { + qWarning("%s: '%s' crashed.", Q_FUNC_INFO, qPrintable(gcc)); + return QByteArray(); + } + return cpp.readAllStandardOutput(); +} + +static QByteArray gccPredefinedMacros(const QString &gcc, const QStringList &env) +{ + QStringList arguments; + arguments << QLatin1String("-xc++") + << QLatin1String("-E") + << QLatin1String("-dM") + << QLatin1String("-"); + + QByteArray predefinedMacros = runGcc(gcc, arguments, env); +#ifdef Q_OS_MAC + // Turn off flag indicating Apple's blocks support + const QByteArray blocksDefine("#define __BLOCKS__ 1"); + const QByteArray blocksUndefine("#undef __BLOCKS__"); + const int idx = predefinedMacros.indexOf(blocksDefine); + if (idx != -1) { + predefinedMacros.replace(idx, blocksDefine.length(), blocksUndefine); + } + + // Define __strong and __weak (used for Apple's GC extension of C) to be empty + predefinedMacros.append("#define __strong\n"); + predefinedMacros.append("#define __weak\n"); +#endif // Q_OS_MAC + return predefinedMacros; +} + +static QList<HeaderPath> gccHeaderPathes(const QString &gcc, const QStringList &env) +{ + QList<HeaderPath> systemHeaderPaths; + QStringList arguments; + arguments << QLatin1String("-xc++") + << QLatin1String("-E") + << QLatin1String("-v") + << QLatin1String("-"); + + QByteArray line; + QByteArray data = runGcc(gcc, arguments, env); + QBuffer cpp(&data); + while (cpp.canReadLine()) { + line = cpp.readLine(); + if (line.startsWith("#include")) + break; + } + + if (!line.isEmpty() && line.startsWith("#include")) { + HeaderPath::Kind kind = HeaderPath::UserHeaderPath; + while (cpp.canReadLine()) { + line = cpp.readLine(); + if (line.startsWith("#include")) { + kind = HeaderPath::GlobalHeaderPath; + } else if (! line.isEmpty() && QChar(line.at(0)).isSpace()) { + HeaderPath::Kind thisHeaderKind = kind; + + line = line.trimmed(); + + const int index = line.indexOf(" (framework directory)"); + if (index != -1) { + line.truncate(index); + thisHeaderKind = HeaderPath::FrameworkHeaderPath; + } + + systemHeaderPaths.append(HeaderPath(QFile::decodeName(line), thisHeaderKind)); + } else if (line.startsWith("End of search list.")) { + break; + } else { + qWarning() << "ignore line:" << line; + } + } + } + return systemHeaderPaths; +} + +static ProjectExplorer::Abi guessGccAbi(const QString &m) +{ + QString machine = m.toLower(); + if (machine.isEmpty()) + return ProjectExplorer::Abi(); + + QStringList parts = machine.split(QRegExp("[ /-]")); + + ProjectExplorer::Abi host = ProjectExplorer::Abi::hostAbi(); + + ProjectExplorer::Abi::Architecture arch = ProjectExplorer::Abi::UNKNOWN_ARCHITECTURE; + ProjectExplorer::Abi::OS os = ProjectExplorer::Abi::UNKNOWN_OS; + ProjectExplorer::Abi::OSFlavour flavor = ProjectExplorer::Abi::UNKNOWN_OSFLAVOUR; + ProjectExplorer::Abi::BinaryFormat format = ProjectExplorer::Abi::UNKNOWN_FORMAT; + int width = 32; + int unknownCount = 0; + + foreach (const QString &p, parts) { + if (p == QLatin1String("unknown") || p == QLatin1String("pc") || p == QLatin1String("none") + || p == QLatin1String("gnu") || p == QLatin1String("86_64")) { + continue; + } else if (p == QLatin1String("i386") || p == QLatin1String("i486") || p == QLatin1String("i586") + || p == QLatin1String("i686") || p == QLatin1String("x86")) { + arch = ProjectExplorer::Abi::x86; + } else if (p == QLatin1String("arm")) { + arch = ProjectExplorer::Abi::ARM; + width = 32; + } else if (p == QLatin1String("x86_64")) { + arch = ProjectExplorer::Abi::x86; + width = 64; + } else if (p == QLatin1String("w64")) { + width = 64; + } else if (p == QLatin1String("linux")) { + os = ProjectExplorer::Abi::Linux; + flavor = ProjectExplorer::Abi::Linux_generic; + format = ProjectExplorer::Abi::Format_ELF; + } else if (p == QLatin1String("symbianelf")) { + os = ProjectExplorer::Abi::Symbian; + flavor = ProjectExplorer::Abi::Symbian_device; + format = ProjectExplorer::Abi::Format_ELF; + } else if (p == QLatin1String("mingw32")) { + arch = ProjectExplorer::Abi::x86; + os = ProjectExplorer::Abi::Windows; + flavor = ProjectExplorer::Abi::Windows_msys; + format = ProjectExplorer::Abi::Format_PE; + } else if (p == QLatin1String("apple")) { + os = ProjectExplorer::Abi::Mac; + flavor = ProjectExplorer::Abi::Mac_generic; + format = ProjectExplorer::Abi::Format_Mach_O; + } else if (p == QLatin1String("darwin10")) { + width = 64; + } else if (p == QLatin1String("gnueabi")) { + format = ProjectExplorer::Abi::Format_ELF; + } else { + ++unknownCount; + } + } + + if (unknownCount == parts.count()) + return ProjectExplorer::Abi(); + return ProjectExplorer::Abi(arch, os, flavor, format, width); +} + +static ProjectExplorer::Abi guessGccAbi(const QString &path, const QStringList &env) +{ + QStringList arguments(QLatin1String("-dumpmachine")); + QString machine = QString::fromLocal8Bit(runGcc(path, arguments, env)).trimmed(); + return guessGccAbi(machine); +} + +// -------------------------------------------------------------------------- +// GccToolChain +// -------------------------------------------------------------------------- + +GccToolChain::GccToolChain(bool autodetect) : + ToolChain(QLatin1String(Constants::GCC_TOOLCHAIN_ID), autodetect), + m_forcedTo32Bit(false), + m_supports64Bit(false) +{ } + +GccToolChain::GccToolChain(const QString &id, bool autodetect) : + ToolChain(id, autodetect), + m_forcedTo32Bit(false), + m_supports64Bit(false) +{ } + +GccToolChain::GccToolChain(const GccToolChain &tc) : + ToolChain(tc), + m_compilerPath(tc.compilerPath()), + m_forcedTo32Bit(tc.m_forcedTo32Bit), + m_supports64Bit(tc.m_supports64Bit), + m_targetAbi(tc.m_targetAbi) +{ + setCompilerPath(tc.m_compilerPath); +} + +QString GccToolChain::defaultDisplayName() const +{ + if (!m_targetAbi.isValid()) + return typeName(); + return QString::fromLatin1("%1 (%2 %3)").arg(typeName(), + ProjectExplorer::Abi::toString(m_targetAbi.architecture()), + ProjectExplorer::Abi::toString(m_targetAbi.wordWidth())); +} + +void GccToolChain::updateId() +{ + QString i = id(); + i = i.left(i.indexOf(QLatin1Char(':'))); + setId(QString::fromLatin1("%1:%2.%3").arg(i).arg(m_compilerPath).arg(m_forcedTo32Bit)); +} + +QString GccToolChain::typeName() const +{ + return Internal::GccToolChainFactory::tr("GCC"); +} + +Abi GccToolChain::targetAbi() const +{ + if (!m_targetAbi.isValid()) { + Utils::Environment env = Utils::Environment::systemEnvironment(); + addToEnvironment(env); + m_targetAbi = guessGccAbi(m_compilerPath, env.toStringList()); + m_supports64Bit = (m_targetAbi.wordWidth() == 64); + if (m_targetAbi.wordWidth() == 64 && m_forcedTo32Bit) + m_targetAbi = Abi(m_targetAbi.architecture(), m_targetAbi.os(), m_targetAbi.osFlavor(), + m_targetAbi.binaryFormat(), 32); + + if (displayName() == typeName()) + setDisplayName(defaultDisplayName()); + } + return m_targetAbi; +} + +bool GccToolChain::isValid() const +{ + return !m_compilerPath.isNull(); +} + +QByteArray GccToolChain::predefinedMacros() const +{ + if (m_predefinedMacros.isEmpty()) { + // Using a clean environment breaks ccache/distcc/etc. + Utils::Environment env = Utils::Environment::systemEnvironment(); + addToEnvironment(env); + m_predefinedMacros = gccPredefinedMacros(m_compilerPath, env.toStringList()); + } + return m_predefinedMacros; +} + +QList<HeaderPath> GccToolChain::systemHeaderPaths() const +{ + if (m_headerPathes.isEmpty()) { + // Using a clean environment breaks ccache/distcc/etc. + Utils::Environment env = Utils::Environment::systemEnvironment(); + addToEnvironment(env); + m_headerPathes = gccHeaderPathes(m_compilerPath, env.toStringList()); + } + return m_headerPathes; +} + +void GccToolChain::addToEnvironment(Utils::Environment &env) const +{ + if (!m_compilerPath.isEmpty()) + env.prependOrSetPath(QFileInfo(m_compilerPath).absolutePath()); +} + +QString GccToolChain::makeCommand() const +{ + return QLatin1String("make"); +} + +IOutputParser *GccToolChain::outputParser() const +{ + return new GccParser; +} + +void GccToolChain::setCompilerPath(const QString &path) +{ + if (path == m_compilerPath) + return; + + if (displayName() == defaultDisplayName()) + setDisplayName(typeName()); + m_compilerPath = path; + m_targetAbi = Abi(); + updateId(); + + if (m_compilerPath.isEmpty()) + return; + + targetAbi(); // update ABI information (and default display name) +} + +QString GccToolChain::compilerPath() const +{ + return m_compilerPath; +} + +bool GccToolChain::isForcedTo32Bit() const +{ + return m_forcedTo32Bit; +} +void GccToolChain::forceTo32Bit(bool f) +{ + if (f == m_forcedTo32Bit) + return; + + if (displayName() == defaultDisplayName()) + setDisplayName(typeName()); + + m_forcedTo32Bit = f; + m_targetAbi = Abi(); // Invalidate ABI. + updateId(); + + targetAbi(); +} + +bool GccToolChain::supports64Bit() const +{ + return m_supports64Bit; +} + +ToolChain *GccToolChain::clone() const +{ + return new GccToolChain(*this); +} + +QVariantMap GccToolChain::toMap() const +{ + QVariantMap data = ToolChain::toMap(); + data.insert(QLatin1String(COMPILER_PATH_KEY), m_compilerPath); + data.insert(QLatin1String(FORCE_32BIT_KEY), m_forcedTo32Bit); + return data; +} + +bool GccToolChain::fromMap(const QVariantMap &data) +{ + if (!ToolChain::fromMap(data)) + return false; + + m_compilerPath = data.value(QLatin1String(COMPILER_PATH_KEY)).toString(); + m_forcedTo32Bit = data.value(QLatin1String(FORCE_32BIT_KEY)).toBool(); + return true; +} + +bool GccToolChain::operator ==(const ToolChain &other) const +{ + if (!ToolChain::operator ==(other)) + return false; + + const GccToolChain *gccTc = static_cast<const GccToolChain *>(&other); + return m_compilerPath == gccTc->m_compilerPath && m_forcedTo32Bit == gccTc->m_forcedTo32Bit; +} + +ToolChainConfigWidget *GccToolChain::configurationWidget() +{ + return new Internal::GccToolChainConfigWidget(this); +} + +// -------------------------------------------------------------------------- +// GccToolChainFactory +// -------------------------------------------------------------------------- + +QString Internal::GccToolChainFactory::displayName() const +{ + return tr("GCC"); +} + +QString Internal::GccToolChainFactory::id() const +{ + return QLatin1String(Constants::GCC_TOOLCHAIN_ID); +} + +bool Internal::GccToolChainFactory::canCreate() +{ + return true; +} + +ToolChain *Internal::GccToolChainFactory::create() +{ + return createToolChain(false); +} + +QList<ToolChain *> Internal::GccToolChainFactory::autoDetect() +{ + return autoDetectCompiler(QLatin1String("gcc")); +} + +// Used by the ToolChainManager to restore user-generated ToolChains +bool Internal::GccToolChainFactory::canRestore(const QVariantMap &data) +{ + return idFromMap(data).startsWith(QLatin1String(Constants::GCC_TOOLCHAIN_ID) + QLatin1Char(':')); +} + +ToolChain *Internal::GccToolChainFactory::restore(const QVariantMap &data) +{ + GccToolChain *tc = new GccToolChain(false); + if (tc->fromMap(data)) + return tc; + + delete tc; + return 0; +} + +GccToolChain *Internal::GccToolChainFactory::createToolChain(bool autoDetect) +{ + return new GccToolChain(autoDetect); +} + +QList<ToolChain *> Internal::GccToolChainFactory::autoDetectCompiler(const QString &cc) +{ + QList<ToolChain *> result; + + QString path = Utils::Environment::systemEnvironment().searchInPath(cc); + if (path.isEmpty()) + return result; + + GccToolChain *tc = createToolChain(true); + if (!tc) + return result; + + tc->setCompilerPath(path); + ProjectExplorer::Abi abi = tc->targetAbi(); + if (abi.isValid()) + result.append(tc); + else + delete tc; + + if (abi.wordWidth() != 64) + return result; + + tc = createToolChain(true); + Q_ASSERT(tc); // worked once, so should work again:-) + tc->forceTo32Bit(true); + tc->setCompilerPath(path); + if (tc->targetAbi().isValid()) + result.append(tc); + else + delete tc; + + return result; +} + +// -------------------------------------------------------------------------- +// GccToolChainConfigWidget +// -------------------------------------------------------------------------- + +Internal::GccToolChainConfigWidget::GccToolChainConfigWidget(GccToolChain *tc) : + ToolChainConfigWidget(tc) +{ + Q_ASSERT(tc); + + QGridLayout *layout = new QGridLayout(this); + QLabel *label = new QLabel(this); + label->setText(tr("Compiler path:")); + layout->addWidget(label, 0, 0); + + m_compilerPath = new Utils::PathChooser(this); + m_compilerPath->setExpectedKind(Utils::PathChooser::ExistingCommand); + layout->addWidget(m_compilerPath, 0, 1); + connect(m_compilerPath, SIGNAL(changed(QString)), this, SLOT(handlePathChange())); + + label = new QLabel(this); + label->setText(tr("Force 32bit compilation:")); + layout->addWidget(label, 1, 0); + + m_force32BitCheckBox = new QCheckBox(this); + layout->addWidget(m_force32BitCheckBox, 1, 1); + connect(m_force32BitCheckBox, SIGNAL(toggled(bool)), this, SLOT(handle32BitChange())); + + discard(); +} + +void Internal::GccToolChainConfigWidget::apply() +{ + if (toolChain()->isAutoDetected()) + return; + + GccToolChain *tc = static_cast<GccToolChain *>(toolChain()); + Q_ASSERT(tc); + QString displayName = tc->displayName(); + QString path = m_compilerPath->path(); + if (path.isEmpty()) + path = m_compilerPath->rawPath(); + tc->forceTo32Bit(m_force32BitCheckBox->isChecked()); + tc->setCompilerPath(path); + tc->setDisplayName(displayName); // reset display name +} + +void Internal::GccToolChainConfigWidget::discard() +{ + GccToolChain *tc = static_cast<GccToolChain *>(toolChain()); + Q_ASSERT(tc); + m_compilerPath->setPath(tc->compilerPath()); + m_force32BitCheckBox->setChecked(tc->isForcedTo32Bit()); + m_force32BitCheckBox->setEnabled(tc->supports64Bit()); +} + +bool Internal::GccToolChainConfigWidget::isDirty() const +{ + GccToolChain *tc = static_cast<GccToolChain *>(toolChain()); + Q_ASSERT(tc); + return m_compilerPath->path() != tc->compilerPath() + || m_force32BitCheckBox->isChecked() != tc->isForcedTo32Bit(); +} + +void Internal::GccToolChainConfigWidget::handlePathChange() +{ + QString path = m_compilerPath->path(); + if (!QFileInfo(path).isExecutable()) { + m_force32BitCheckBox->setEnabled(false); + m_force32BitCheckBox->setChecked(true); + } else { + ProjectExplorer::Abi abi = guessGccAbi(path, Utils::Environment::systemEnvironment().toStringList()); + m_force32BitCheckBox->setEnabled(abi.wordWidth() == 64); + m_force32BitCheckBox->setChecked(abi.wordWidth() == 32); + } + emit dirty(toolChain()); +} + +void Internal::GccToolChainConfigWidget::handle32BitChange() +{ + emit dirty(toolChain()); +} + +// -------------------------------------------------------------------------- +// MingwToolChain +// -------------------------------------------------------------------------- + +MingwToolChain::MingwToolChain(bool autodetect) : + GccToolChain(QLatin1String(Constants::MINGW_TOOLCHAIN_ID), autodetect) +{ } + +QString MingwToolChain::typeName() const +{ + return Internal::MingwToolChainFactory::tr("MinGW"); +} + +QString MingwToolChain::makeCommand() const +{ + return QLatin1String("mingw32-make.exe"); +} + +ToolChain *MingwToolChain::clone() const +{ + return new MingwToolChain(*this); +} + +// -------------------------------------------------------------------------- +// MingwToolChainFactory +// -------------------------------------------------------------------------- + +QString Internal::MingwToolChainFactory::displayName() const +{ + return tr("MinGW"); +} + +QString Internal::MingwToolChainFactory::id() const +{ + return QLatin1String(Constants::MINGW_TOOLCHAIN_ID); +} + +QList<ToolChain *> Internal::MingwToolChainFactory::autoDetect() +{ + return autoDetectCompiler(QLatin1String("gcc")); +} + +bool Internal::MingwToolChainFactory::canCreate() +{ + return true; +} + +ToolChain *Internal::MingwToolChainFactory::create() +{ + return createToolChain(false); +} + +bool Internal::MingwToolChainFactory::canRestore(const QVariantMap &data) +{ + return idFromMap(data).startsWith(QLatin1String(Constants::MINGW_TOOLCHAIN_ID) + QLatin1Char(':')); +} + +ToolChain *Internal::MingwToolChainFactory::restore(const QVariantMap &data) +{ + MingwToolChain *tc = new MingwToolChain(false); + if (tc->fromMap(data)) + return tc; + + delete tc; + return 0; +} + +GccToolChain *Internal::MingwToolChainFactory::createToolChain(bool autoDetect) +{ + return new MingwToolChain(autoDetect); +} + +// -------------------------------------------------------------------------- +// LinuxIccToolChain +// -------------------------------------------------------------------------- + +LinuxIccToolChain::LinuxIccToolChain(bool autodetect) : + GccToolChain(QLatin1String(Constants::LINUXICC_TOOLCHAIN_ID), autodetect) +{ } + +QString LinuxIccToolChain::typeName() const +{ + return Internal::LinuxIccToolChainFactory::tr("Linux ICC"); +} + +IOutputParser *LinuxIccToolChain::outputParser() const +{ + return new LinuxIccParser; +} + +ToolChain *LinuxIccToolChain::clone() const +{ + return new LinuxIccToolChain(*this); +} + +// -------------------------------------------------------------------------- +// LinuxIccToolChainFactory +// -------------------------------------------------------------------------- + +QString Internal::LinuxIccToolChainFactory::displayName() const +{ + return tr("Linux ICC"); +} + +QString Internal::LinuxIccToolChainFactory::id() const +{ + return QLatin1String(Constants::LINUXICC_TOOLCHAIN_ID); +} + +QList<ToolChain *> Internal::LinuxIccToolChainFactory::autoDetect() +{ + return autoDetectCompiler(QLatin1String("icpc")); +} + +ToolChain *Internal::LinuxIccToolChainFactory::create() +{ + return createToolChain(false); +} + +bool Internal::LinuxIccToolChainFactory::canRestore(const QVariantMap &data) +{ + return idFromMap(data).startsWith(QLatin1String(Constants::LINUXICC_TOOLCHAIN_ID) + QLatin1Char(':')); +} + +ToolChain *Internal::LinuxIccToolChainFactory::restore(const QVariantMap &data) +{ + LinuxIccToolChain *tc = new LinuxIccToolChain(false); + if (tc->fromMap(data)) + return tc; + + delete tc; + return 0; +} + +GccToolChain *Internal::LinuxIccToolChainFactory::createToolChain(bool autoDetect) +{ + return new LinuxIccToolChain(autoDetect); +} + +} // namespace ProjectExplorer + +// Unit tests: + +#ifdef WITH_TESTS +# include "projectexplorer.h" + +# include <QTest> +# include <QtCore/QUrl> + +namespace ProjectExplorer { + +void ProjectExplorerPlugin::testGccAbiGuessing_data() +{ + QTest::addColumn<QString>("input"); + QTest::addColumn<QString>("abi"); + + QTest::newRow("invalid input") + << QString::fromLatin1("Some text") + << QString::fromLatin1("unknown-unknown-unknown-unknown-unknown"); + QTest::newRow("empty input") + << QString::fromLatin1("") + << QString::fromLatin1("unknown-unknown-unknown-unknown-unknown"); + QTest::newRow("broken input") + << QString::fromLatin1("arm-none-foo-gnueabi") + << QString::fromLatin1("arm-unknown-unknown-elf-32bit"); + + QTest::newRow("Maemo 1") + << QString::fromLatin1("arm-none-linux-gnueabi") + << QString::fromLatin1("arm-linux-generic-elf-32bit"); + QTest::newRow("Linux 1") + << QString::fromLatin1("i686-linux-gnu") + << QString::fromLatin1("x86-linux-generic-elf-32bit"); + QTest::newRow("Linux 2") + << QString::fromLatin1("i486-linux-gnu") + << QString::fromLatin1("x86-linux-generic-elf-32bit"); + QTest::newRow("Linux 3") + << QString::fromLatin1("x86_64-linux-gnu") + << QString::fromLatin1("x86-linux-generic-elf-64bit"); + QTest::newRow("Mingw 1") + << QString::fromLatin1("i686-w64-mingw32") + << QString::fromLatin1("x86-windows-msys-pe-64bit"); + QTest::newRow("Mingw 2") + << QString::fromLatin1("mingw32") + << QString::fromLatin1("x86-windows-msys-pe-32bit"); + QTest::newRow("Mac 1") + << QString::fromLatin1("i686-apple-darwin10") + << QString::fromLatin1("x86-macos-generic-mach_o-64bit"); + QTest::newRow("Intel 1") + << QString::fromLatin1("86_64 x86_64 GNU/Linux") + << QString::fromLatin1("x86-linux-generic-elf-64bit"); +} + +void ProjectExplorerPlugin::testGccAbiGuessing() +{ + QFETCH(QString, input); + QFETCH(QString, abi); + + ProjectExplorer::Abi a = guessGccAbi(input); + QCOMPARE(a.toString(), abi); +} + +} // namespace ProjectExplorer + +#endif diff --git a/src/plugins/projectexplorer/gcctoolchain.h b/src/plugins/projectexplorer/gcctoolchain.h new file mode 100644 index 0000000000..90cd0d0535 --- /dev/null +++ b/src/plugins/projectexplorer/gcctoolchain.h @@ -0,0 +1,275 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** No Commercial Usage +** +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +**************************************************************************/ + +#ifndef GCCTOOLCHAIN_H +#define GCCTOOLCHAIN_H + +#include "projectexplorer_export.h" + +#include "toolchain.h" + +#include "toolchainconfigwidget.h" + +#include <utils/pathchooser.h> + +QT_BEGIN_NAMESPACE +class QCheckBox; +QT_END_NAMESPACE + +namespace ProjectExplorer { + +namespace Internal { +class GccToolChainFactory; +class MingwToolChainFactory; +class LinuxIccToolChainFactory; +} + +// -------------------------------------------------------------------------- +// GccToolChain +// -------------------------------------------------------------------------- + +class PROJECTEXPLORER_EXPORT GccToolChain : public ToolChain +{ +public: + QString typeName() const; + Abi targetAbi() const; + + bool isValid() const; + + QByteArray predefinedMacros() const; + QList<HeaderPath> systemHeaderPaths() const; + void addToEnvironment(Utils::Environment &env) const; + QString makeCommand() const; + IOutputParser *outputParser() const; + + QVariantMap toMap() const; + bool fromMap(const QVariantMap &data); + + ToolChainConfigWidget *configurationWidget(); + + bool operator ==(const ToolChain &) const; + + void setCompilerPath(const QString &); + QString compilerPath() const; + + bool isForcedTo32Bit() const; + void forceTo32Bit(bool); + + bool supports64Bit() const; + + ToolChain *clone() const; + +protected: + GccToolChain(const QString &id, bool autodetect); + GccToolChain(const GccToolChain &); + + QString defaultDisplayName() const; + + void updateId(); + + mutable QByteArray m_predefinedMacros; + +private: + GccToolChain(bool autodetect); + + QString m_compilerPath; + bool m_forcedTo32Bit; + mutable bool m_supports64Bit; + + mutable Abi m_targetAbi; + mutable QList<HeaderPath> m_headerPathes; + + friend class Internal::GccToolChainFactory; + friend class ToolChainFactory; +}; + + +// -------------------------------------------------------------------------- +// GccToolChainFactory +// -------------------------------------------------------------------------- + +namespace Internal { + +class GccToolChainFactory : public ToolChainFactory +{ + Q_OBJECT + +public: + // Name used to display the name of the toolchain that will be created. + QString displayName() const; + QString id() const; + + QList<ToolChain *> autoDetect(); + + bool canCreate(); + ToolChain *create(); + + // Used by the ToolChainManager to restore user-generated ToolChains + bool canRestore(const QVariantMap &data); + ToolChain *restore(const QVariantMap &data); + +protected: + virtual GccToolChain *createToolChain(bool autoDetect); + QList<ToolChain *> autoDetectCompiler(const QString &path); +}; + +} // namespace Internal + +// -------------------------------------------------------------------------- +// GccToolChainConfigWidget +// -------------------------------------------------------------------------- + +namespace Internal { + +class GccToolChainConfigWidget : public ToolChainConfigWidget +{ + Q_OBJECT + +public: + GccToolChainConfigWidget(GccToolChain *); + void apply(); + void discard(); + bool isDirty() const; + +private slots: + void handlePathChange(); + void handle32BitChange(); + +private: + Utils::PathChooser *m_compilerPath; + QCheckBox *m_force32BitCheckBox; +}; + +} // namespace Internal + +// -------------------------------------------------------------------------- +// MingwToolChain +// -------------------------------------------------------------------------- + +class PROJECTEXPLORER_EXPORT MingwToolChain : public GccToolChain +{ +public: + QString typeName() const; + QString makeCommand() const; + + ToolChain *clone() const; + +private: + MingwToolChain(bool autodetect); + + friend class Internal::MingwToolChainFactory; + friend class ToolChainFactory; +}; + +// -------------------------------------------------------------------------- +// MingwToolChainFactory +// -------------------------------------------------------------------------- + +namespace Internal { + +class MingwToolChainFactory : public GccToolChainFactory +{ + Q_OBJECT + +public: + // Name used to display the name of the toolchain that will be created. + QString displayName() const; + QString id() const; + + QList<ToolChain *> autoDetect(); + + bool canCreate(); + ToolChain *create(); + + // Used by the ToolChainManager to restore user-generated ToolChains + bool canRestore(const QVariantMap &data); + ToolChain *restore(const QVariantMap &data); + +protected: + GccToolChain *createToolChain(bool autoDetect); +}; + +} // namespace Internal + +// -------------------------------------------------------------------------- +// LinuxIccToolChain +// -------------------------------------------------------------------------- + +class PROJECTEXPLORER_EXPORT LinuxIccToolChain : public GccToolChain +{ +public: + + QString typeName() const; + + IOutputParser *outputParser() const; + + ToolChain *clone() const; + +private: + LinuxIccToolChain(bool autodetect); + + friend class Internal::LinuxIccToolChainFactory; + friend class ToolChainFactory; +}; + +// -------------------------------------------------------------------------- +// LinuxIccToolChainFactory +// -------------------------------------------------------------------------- + +namespace Internal { + +class LinuxIccToolChainFactory : public GccToolChainFactory +{ + Q_OBJECT + +public: + // Name used to display the name of the toolchain that will be created. + QString displayName() const; + QString id() const; + + QList<ToolChain *> autoDetect(); + + ToolChain *create(); + + // Used by the ToolChainManager to restore user-generated ToolChains + bool canRestore(const QVariantMap &data); + ToolChain *restore(const QVariantMap &data); + +protected: + GccToolChain *createToolChain(bool autoDetect); +}; + +} // namespace Internal +} // namespace ProjectExplorer + +#endif // GCCTOOLCHAIN_H diff --git a/src/plugins/projectexplorer/msvcparser.cpp b/src/plugins/projectexplorer/msvcparser.cpp index 3ba3f76ec0..5c582ad940 100644 --- a/src/plugins/projectexplorer/msvcparser.cpp +++ b/src/plugins/projectexplorer/msvcparser.cpp @@ -269,7 +269,6 @@ void ProjectExplorerPlugin::testMsvcOutputParsers_data() QLatin1String("debug\\Experimentation.exe"), -1, QLatin1String(ProjectExplorer::Constants::TASK_CATEGORY_COMPILE))) << QString(); - } void ProjectExplorerPlugin::testMsvcOutputParsers() diff --git a/src/plugins/projectexplorer/msvctoolchain.cpp b/src/plugins/projectexplorer/msvctoolchain.cpp new file mode 100644 index 0000000000..aac1b5f370 --- /dev/null +++ b/src/plugins/projectexplorer/msvctoolchain.cpp @@ -0,0 +1,525 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** No Commercial Usage +** +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +**************************************************************************/ + +#include "msvctoolchain.h" +#include "msvcparser.h" +#include "projectexplorerconstants.h" + +#include <projectexplorer/projectexplorer.h> +#include <projectexplorer/projectexplorersettings.h> + +#include <utils/qtcprocess.h> +#include <utils/synchronousprocess.h> + +#include <QtCore/QCoreApplication> +#include <QtCore/QDir> +#include <QtCore/QFileInfo> +#include <QtCore/QSettings> +#include <QtCore/QTemporaryFile> +#include <QtGui/QLabel> +#include <QtGui/QVBoxLayout> + +namespace ProjectExplorer { +namespace Internal { + +// -------------------------------------------------------------------------- +// Helpers: +// -------------------------------------------------------------------------- + +static QString platformName(MsvcToolChain::Platform t) +{ + switch (t) { + case MsvcToolChain::s32: + return QLatin1String(" (x86)"); + case MsvcToolChain::s64: + return QLatin1String(" (x64)"); + case MsvcToolChain::ia64: + return QLatin1String(" (ia64)"); + case MsvcToolChain::amd64: + return QLatin1String(" (amd64)"); + } + return QString(); +} + +static QString generateDisplayName(const QString &name, + MsvcToolChain::Type t, + MsvcToolChain::Platform p) +{ + if (t == MsvcToolChain::WindowsSDK) { + QString sdkName = name; + sdkName += platformName(p); + return sdkName; + } + // Comes as "9.0" from the registry + QString vcName = QLatin1String("Microsoft Visual C++ Compiler "); + vcName += name; + vcName += platformName(p); + return vcName; +} + +static QByteArray msvcCompilationFile() +{ + static const char* macros[] = {"_ATL_VER", "_CHAR_UNSIGNED", "__CLR_VER", + "__cplusplus_cli", "__COUNTER__", "__cplusplus", + "_CPPLIB_VER", "_CPPRTTI", "_CPPUNWIND", + "_DEBUG", "_DLL", "__FUNCDNAME__", + "__FUNCSIG__","__FUNCTION__","_INTEGRAL_MAX_BITS", + "_M_ALPHA","_M_CEE","_M_CEE_PURE", + "_M_CEE_SAFE","_M_IX86","_M_IA64", + "_M_IX86_FP","_M_MPPC","_M_MRX000", + "_M_PPC","_M_X64","_MANAGED", + "_MFC_VER","_MSC_BUILD", /* "_MSC_EXTENSIONS", */ + "_MSC_FULL_VER","_MSC_VER","__MSVC_RUNTIME_CHECKS", + "_MT", "_NATIVE_WCHAR_T_DEFINED", "_OPENMP", + "_VC_NODEFAULTLIB", "_WCHAR_T_DEFINED", "_WIN32", + "_WIN32_WCE", "_WIN64", "_Wp64", "__DATE__", + "__DATE__", "__TIME__", "__TIMESTAMP__", + 0}; + QByteArray file = "#define __PPOUT__(x) V##x=x\n\n"; + for (int i = 0; macros[i] != 0; ++i) { + const QByteArray macro(macros[i]); + file += "#if defined(" + macro + ")\n__PPOUT__(" + + macro + ")\n#endif\n"; + } + file += "\nvoid main(){}\n\n"; + return file; +} + +// Run MSVC 'cl' compiler to obtain #defines. +static QByteArray msvcPredefinedMacros(const QStringList &env) +{ + QByteArray predefinedMacros = "#define __MSVCRT__\n" + "#define __w64\n" + "#define __int64 long long\n" + "#define __int32 long\n" + "#define __int16 short\n" + "#define __int8 char\n" + "#define __ptr32\n" + "#define __ptr64\n"; + + QString tmpFilePath; + { + // QTemporaryFile is buggy and will not unlock the file for cl.exe + QTemporaryFile tmpFile(QDir::tempPath()+"/envtestXXXXXX.cpp"); + tmpFile.setAutoRemove(false); + if (!tmpFile.open()) + return predefinedMacros; + tmpFilePath = QFileInfo(tmpFile).canonicalFilePath(); + tmpFile.write(msvcCompilationFile()); + tmpFile.close(); + } + QProcess cpp; + cpp.setEnvironment(env); + cpp.setWorkingDirectory(QDir::tempPath()); + QStringList arguments; + const QString binary = QLatin1String("cl.exe"); + arguments << QLatin1String("/EP") << QDir::toNativeSeparators(tmpFilePath); + cpp.start(QLatin1String("cl.exe"), arguments); + if (!cpp.waitForStarted()) { + qWarning("%s: Cannot start '%s': %s", Q_FUNC_INFO, qPrintable(binary), + qPrintable(cpp.errorString())); + return predefinedMacros; + } + cpp.closeWriteChannel(); + if (!cpp.waitForFinished()) { + Utils::SynchronousProcess::stopProcess(cpp); + qWarning("%s: Timeout running '%s'.", Q_FUNC_INFO, qPrintable(binary)); + return predefinedMacros; + } + if (cpp.exitStatus() != QProcess::NormalExit) { + qWarning("%s: '%s' crashed.", Q_FUNC_INFO, qPrintable(binary)); + return predefinedMacros; + } + + const QList<QByteArray> output = cpp.readAllStandardOutput().split('\n'); + foreach (const QByteArray& line, output) { + if (line.startsWith('V')) { + QList<QByteArray> split = line.split('='); + const QByteArray key = split.at(0).mid(1); + QByteArray value = split.at(1); + if (!value.isEmpty()) { + value.chop(1); //remove '\n' + } + predefinedMacros += "#define "; + predefinedMacros += key; + predefinedMacros += ' '; + predefinedMacros += value; + predefinedMacros += '\n'; + } + } + QFile::remove(tmpFilePath); + return predefinedMacros; +} + +static QString winExpandDelayedEnvReferences(QString in, const Utils::Environment &env) +{ + const QChar exclamationMark = QLatin1Char('!'); + for (int pos = 0; pos < in.size(); ) { + // Replace "!REF!" by its value in process environment + pos = in.indexOf(exclamationMark, pos); + if (pos == -1) + break; + const int nextPos = in.indexOf(exclamationMark, pos + 1); + if (nextPos == -1) + break; + const QString var = in.mid(pos + 1, nextPos - pos - 1); + const QString replacement = env.value(var.toUpper()); + in.replace(pos, nextPos + 1 - pos, replacement); + pos += replacement.size(); + } + return in; +} + +static Utils::Environment msvcReadEnvironmentSetting(const QString &varsBat, + const QString &args, + Utils::Environment &env) +{ + // Run the setup script and extract the variables + if (!QFileInfo(varsBat).exists()) + return env; + + const QString tempOutputFileName = QDir::tempPath() + QLatin1String("\\qtcreator-msvc-environment.txt"); + QTemporaryFile tf(QDir::tempPath() + "\\XXXXXX.bat"); + tf.setAutoRemove(true); + if (!tf.open()) + return env; + + const QString filename = tf.fileName(); + + QByteArray call = "call "; + call += Utils::QtcProcess::quoteArg(varsBat).toLocal8Bit(); + if (!args.isEmpty()) { + call += ' '; + call += args.toLocal8Bit(); + } + call += "\r\n"; + tf.write(call); + const QByteArray redirect = "set > " + Utils::QtcProcess::quoteArg( + QDir::toNativeSeparators(tempOutputFileName)).toLocal8Bit() + "\r\n"; + tf.write(redirect); + tf.flush(); + tf.waitForBytesWritten(30000); + + Utils::QtcProcess run; + run.setEnvironment(env); + const QString cmdPath = QString::fromLocal8Bit(qgetenv("COMSPEC")); + run.setCommand(cmdPath, QString::fromLatin1("/c \"%1\"").arg(QDir::toNativeSeparators(filename))); + run.start(); + if (!run.waitForStarted()) { + qWarning("%s: Unable to run '%s': %s", Q_FUNC_INFO, qPrintable(varsBat), + qPrintable(run.errorString())); + return env; + } + if (!run.waitForFinished()) { + qWarning("%s: Timeout running '%s'", Q_FUNC_INFO, qPrintable(varsBat)); + Utils::SynchronousProcess::stopProcess(run); + return env; + } + tf.close(); + + QFile varsFile(tempOutputFileName); + if (!varsFile.open(QIODevice::ReadOnly|QIODevice::Text)) + return env; + + QRegExp regexp(QLatin1String("(\\w*)=(.*)")); + Utils::Environment result; + while (!varsFile.atEnd()) { + const QString line = QString::fromLocal8Bit(varsFile.readLine()).trimmed(); + if (regexp.exactMatch(line)) { + const QString varName = regexp.cap(1); + const QString expandedValue = winExpandDelayedEnvReferences(regexp.cap(2), env); + if (!expandedValue.isEmpty()) + env.set(varName, expandedValue); + } + } + varsFile.close(); + varsFile.remove(); + + return env; +} + +// -------------------------------------------------------------------------- +// MsvcToolChain +// -------------------------------------------------------------------------- + +MsvcToolChain::MsvcToolChain(Type type, const QString &name, Platform platform, + const QString &varsBat, const QString &varsBatArg, bool autodetect) : + ToolChain(QLatin1String(Constants::MSVC_TOOLCHAIN_ID), autodetect), + m_varsBat(varsBat), + m_varsBatArg(varsBatArg), + m_is64bit(true), + m_architecture(Abi::x86) +{ + Q_ASSERT(!name.isEmpty()); + Q_ASSERT(!m_varsBat.isEmpty()); + Q_ASSERT(QFileInfo(m_varsBat).exists()); + + switch (platform) + { + case ProjectExplorer::Internal::MsvcToolChain::s32: + m_is64bit = false; + break; + case ProjectExplorer::Internal::MsvcToolChain::ia64: + m_architecture = Abi::Itanium; + break; + case ProjectExplorer::Internal::MsvcToolChain::s64: + case ProjectExplorer::Internal::MsvcToolChain::amd64: + break; + }; + + setId(QString::fromLatin1("%1:%2.%3").arg(Constants::MSVC_TOOLCHAIN_ID).arg(m_varsBat) + .arg(m_varsBatArg)); + + setDisplayName(generateDisplayName(name, type, platform)); +} + +QString MsvcToolChain::typeName() const +{ + return MsvcToolChainFactory::tr("MSVC"); +} + +Abi MsvcToolChain::targetAbi() const +{ + return Abi(m_architecture, Abi::Windows, Abi::Windows_msvc, Abi::Format_PE, m_is64bit ? 64 : 32); +} + +bool MsvcToolChain::isValid() const +{ + return !m_varsBat.isEmpty(); +} + +QByteArray MsvcToolChain::predefinedMacros() const +{ + if (m_predefinedMacros.isEmpty()) { + Utils::Environment env(m_lastEnvironment); + addToEnvironment(env); + m_predefinedMacros = msvcPredefinedMacros(env.toStringList()); + } + return m_predefinedMacros; +} + +QList<HeaderPath> MsvcToolChain::systemHeaderPaths() const +{ + if (m_headerPathes.isEmpty()) { + Utils::Environment env(m_lastEnvironment); + addToEnvironment(env); + foreach (const QString &path, env.value("INCLUDE").split(QLatin1Char(';'))) + m_headerPathes.append(HeaderPath(path, HeaderPath::GlobalHeaderPath)); + } + return m_headerPathes; +} + +void MsvcToolChain::addToEnvironment(Utils::Environment &env) const +{ + // We cache the full environment (incoming + modifications by setup script). + if (!m_resultEnvironment.size() || env != m_lastEnvironment) { + m_lastEnvironment = env; + m_resultEnvironment = msvcReadEnvironmentSetting(m_varsBat, m_varsBatArg, env); + } + env = m_resultEnvironment; +} + +QString MsvcToolChain::makeCommand() const +{ + if (ProjectExplorerPlugin::instance()->projectExplorerSettings().useJom) { + // We want jom! Try to find it. + QString jom = QCoreApplication::applicationDirPath() + QLatin1String("/jom.exe"); + if (QFileInfo(jom).exists()) + return jom; + else + return QLatin1String("jom.exe"); + } + return QLatin1String("nmake.exe"); +} + +IOutputParser *MsvcToolChain::outputParser() const +{ + return new MsvcParser; +} + +ToolChainConfigWidget *MsvcToolChain::configurationWidget() +{ + return new MsvcToolChainConfigWidget(this); +} + +bool MsvcToolChain::canClone() const +{ + return false; +} + +ToolChain *MsvcToolChain::clone() const +{ + return 0; +} + +// -------------------------------------------------------------------------- +// MsvcToolChainConfigWidget +// -------------------------------------------------------------------------- + +MsvcToolChainConfigWidget::MsvcToolChainConfigWidget(ToolChain *tc) : + ToolChainConfigWidget(tc) +{ + QLabel *label = new QLabel; + label->setText(tc->displayName()); + QVBoxLayout *layout = new QVBoxLayout(this); + layout->addWidget(label); +} + +void MsvcToolChainConfigWidget::apply() +{ + // Nothing to apply! +} + +void MsvcToolChainConfigWidget::discard() +{ + // Nothing to apply! +} + +bool MsvcToolChainConfigWidget::isDirty() const +{ + return false; +} + +// -------------------------------------------------------------------------- +// MsvcToolChainFactory +// -------------------------------------------------------------------------- + +QString MsvcToolChainFactory::displayName() const +{ + return tr("MSVC"); +} + +QString MsvcToolChainFactory::id() const +{ + return QLatin1String(Constants::MSVC_TOOLCHAIN_ID); +} + +QList<ToolChain *> MsvcToolChainFactory::autoDetect() +{ + QList<ToolChain *> results; + +#ifdef Q_OS_WIN + // 1) Installed SDKs preferred over standalone Visual studio + const QSettings sdkRegistry("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Microsoft SDKs\\Windows", + QSettings::NativeFormat); + const QString defaultSdkPath = sdkRegistry.value(QLatin1String("CurrentInstallFolder")).toString(); + if (!defaultSdkPath.isEmpty()) { + foreach (const QString &sdkKey, sdkRegistry.childGroups()) { + const QString name = sdkRegistry.value(sdkKey + QLatin1String("/ProductName")).toString(); + const QString folder = sdkRegistry.value(sdkKey + QLatin1String("/InstallationFolder")).toString(); + if (folder.isEmpty()) + continue; + + const QString sdkVcVarsBat = folder + QLatin1String("bin\\SetEnv.cmd"); + if (!QFileInfo(sdkVcVarsBat).exists()) + continue; + QList<ToolChain *> tmp; + tmp.append(new MsvcToolChain(MsvcToolChain::WindowsSDK, name,MsvcToolChain::s32, + sdkVcVarsBat, QLatin1String("/x86"), true)); +#ifdef Q_OS_WIN64 + // Add all platforms + tmp.append(new MsvcToolChain(MsvcToolChain::WindowsSDK, name, MsvcToolChain::s64, + sdkVcVarsBat, QLatin1String("/x64"), true)); + tmp.append(new MsvcToolChain(MsvcToolChain::WindowsSDK, name, MsvcToolChain::ia64, + sdkVcVarsBat, QLatin1String("/ia64"), true)); +#endif + // Make sure the default is front. + if (folder == defaultSdkPath) + results = tmp + results; + else + results += tmp; + } // foreach + } + + // 2) Installed MSVCs + const QSettings vsRegistry( +#ifdef Q_OS_WIN64 + QLatin1String("HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\Microsoft\\VisualStudio\\SxS\\VC7"), +#else + QLatin1String("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\SxS\\VC7"), +#endif + QSettings::NativeFormat); + foreach (const QString &vsName, vsRegistry.allKeys()) { + // Scan for version major.minor + const int dotPos = vsName.indexOf(QLatin1Char('.')); + if (dotPos == -1) + continue; + + const QString path = vsRegistry.value(vsName).toString(); + const int version = vsName.left(dotPos).toInt(); + // Check existence of various install scripts + const QString vcvars32bat = path + QLatin1String("bin\\vcvars32.bat"); + if (QFileInfo(vcvars32bat).isFile()) + results.append(new MsvcToolChain(MsvcToolChain::VS, vsName, MsvcToolChain::s32, + vcvars32bat, QString(), true)); + if (version >= 10) { + // Just one common file + const QString vcvarsAllbat = path + QLatin1String("vcvarsall.bat"); + if (QFileInfo(vcvarsAllbat).isFile()) { + results.append(new MsvcToolChain(MsvcToolChain::VS, vsName, MsvcToolChain::s32, + vcvarsAllbat, QLatin1String("x86"), true)); + results.append(new MsvcToolChain(MsvcToolChain::VS, vsName, MsvcToolChain::amd64, + vcvarsAllbat, QLatin1String("amd64"), true)); + results.append(new MsvcToolChain(MsvcToolChain::VS, vsName, MsvcToolChain::s64, + vcvarsAllbat, QLatin1String("x64"), true)); + results.append(new MsvcToolChain(MsvcToolChain::VS, vsName, MsvcToolChain::ia64, + vcvarsAllbat, QLatin1String("ia64"), true)); + } else { + qWarning("Unable to find MSVC setup script %s in version %d", qPrintable(vcvarsAllbat), version); + } + } else { + // Amd 64 is the preferred 64bit platform + const QString vcvarsAmd64bat = path + QLatin1String("bin\\amd64\\vcvarsamd64.bat"); + if (QFileInfo(vcvarsAmd64bat).isFile()) + results.append(new MsvcToolChain(MsvcToolChain::VS, vsName, MsvcToolChain::amd64, + vcvarsAmd64bat, QString(), true)); + const QString vcvarsAmd64bat2 = path + QLatin1String("bin\\vcvarsx86_amd64.bat"); + if (QFileInfo(vcvarsAmd64bat2).isFile()) + results.append(new MsvcToolChain(MsvcToolChain::VS, vsName, MsvcToolChain::amd64, + vcvarsAmd64bat2, QString(), true)); + const QString vcvars64bat = path + QLatin1String("bin\\vcvars64.bat"); + if (QFileInfo(vcvars64bat).isFile()) + results.append(new MsvcToolChain(MsvcToolChain::VS, vsName, MsvcToolChain::s64, + vcvars64bat, QString(), true)); + const QString vcvarsIA64bat = path + QLatin1String("bin\\vcvarsx86_ia64.bat"); + if (QFileInfo(vcvarsIA64bat).isFile()) + results.append(new MsvcToolChain(MsvcToolChain::VS, vsName, MsvcToolChain::ia64, + vcvarsIA64bat, QString(), true)); + } + } +#endif + return results; +} + +} // namespace Internal +} // namespace ProjectExplorer diff --git a/src/plugins/projectexplorer/msvctoolchain.h b/src/plugins/projectexplorer/msvctoolchain.h new file mode 100644 index 0000000000..512c6eb6d7 --- /dev/null +++ b/src/plugins/projectexplorer/msvctoolchain.h @@ -0,0 +1,121 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** No Commercial Usage +** +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +**************************************************************************/ + +#ifndef MSVCTOOLCHAIN_H +#define MSVCTOOLCHAIN_H + +#include "toolchain.h" +#include "toolchainconfigwidget.h" + +#include <utils/environment.h> + +namespace ProjectExplorer { +namespace Internal { + +// -------------------------------------------------------------------------- +// MsvcToolChain +// -------------------------------------------------------------------------- + +class MsvcToolChain : public ToolChain +{ +public: + enum Type { WindowsSDK, VS }; + enum Platform { s32, s64, ia64, amd64 }; + + MsvcToolChain(Type type, const QString &name, Platform platform, const QString &varsBat, + const QString &varsBatArg, bool autodetect = false); + + QString typeName() const; + Abi targetAbi() const; + + bool isValid() const; + + QByteArray predefinedMacros() const; + QList<HeaderPath> systemHeaderPaths() const; + void addToEnvironment(Utils::Environment &env) const; + QString makeCommand() const; + IOutputParser *outputParser() const; + + ToolChainConfigWidget *configurationWidget(); + + bool canClone() const; + ToolChain *clone() const; + +private: + QString m_varsBat; // Script to setup environment + QString m_varsBatArg; // Argument + mutable QByteArray m_predefinedMacros; + mutable Utils::Environment m_lastEnvironment; + mutable Utils::Environment m_resultEnvironment; + mutable QList<HeaderPath> m_headerPathes; + bool m_is64bit; + Abi::Architecture m_architecture; +}; + +// -------------------------------------------------------------------------- +// MsvcToolChainFactory +// -------------------------------------------------------------------------- + +class MsvcToolChainFactory : public ToolChainFactory +{ + Q_OBJECT + +public: + QString displayName() const; + QString id() const; + + QList<ToolChain *> autoDetect(); + + ToolChainConfigWidget *configurationWidget(ToolChain *); +}; + +// -------------------------------------------------------------------------- +// MsvcToolChainConfigWidget +// -------------------------------------------------------------------------- + +class MsvcToolChainConfigWidget : public ToolChainConfigWidget +{ + Q_OBJECT + +public: + MsvcToolChainConfigWidget(ToolChain *); + + void apply(); + void discard(); + bool isDirty() const; +}; + +} // namespace Internal +} // namespace ProjectExplorer + +#endif // MSVCTOOLCHAIN_H diff --git a/src/plugins/projectexplorer/projectexplorer.cpp b/src/plugins/projectexplorer/projectexplorer.cpp index 8cbd0004b9..a32e516377 100644 --- a/src/plugins/projectexplorer/projectexplorer.cpp +++ b/src/plugins/projectexplorer/projectexplorer.cpp @@ -35,10 +35,14 @@ #include "buildsteplist.h" #include "deployconfiguration.h" +#include "gcctoolchain.h" +#include "msvctoolchain.h" #include "project.h" #include "projectexplorersettings.h" #include "target.h" #include "targetsettingspanel.h" +#include "toolchainmanager.h" +#include "toolchainoptionspage.h" #include "copytaskhandler.h" #include "showineditortaskhandler.h" #include "vcsannotatetaskhandler.h" @@ -211,13 +215,16 @@ struct ProjectExplorerPluginPrivate { Internal::ProjectWelcomePage *m_welcomePage; Core::IMode *m_projectsMode; + + ToolChainManager *m_toolChainManager; }; ProjectExplorerPluginPrivate::ProjectExplorerPluginPrivate() : m_currentProject(0), m_currentNode(0), m_delayedRunConfiguration(0), - m_projectsMode(0) + m_projectsMode(0), + m_toolChainManager(0) { } @@ -258,6 +265,7 @@ ProjectExplorerPlugin::~ProjectExplorerPlugin() { removeObject(d->m_welcomePage); delete d->m_welcomePage; + delete d->m_toolChainManager; removeObject(this); delete d; } @@ -279,6 +287,19 @@ bool ProjectExplorerPlugin::initialize(const QStringList &arguments, QString *er return false; addObject(this); + // Add ToolChainFactories: +#ifndef Q_OS_WIN + addAutoReleasedObject(new Internal::GccToolChainFactory); + addAutoReleasedObject(new Internal::LinuxIccToolChainFactory); +#else + addAutoReleasedObject(new Internal::MingwToolChainFactory); + addAutoReleasedObject(new Internal::MsvcToolChainFactory); +#endif + + d->m_toolChainManager = new ToolChainManager(this); + + addAutoReleasedObject(new Internal::ToolChainOptionsPage); + addAutoReleasedObject(new TaskHub); Core::ICore *core = Core::ICore::instance(); @@ -986,6 +1007,8 @@ void ProjectExplorerPlugin::clearSession() void ProjectExplorerPlugin::extensionsInitialized() { + d->m_toolChainManager->restoreToolChains(); + d->m_proWindow->extensionsInitialized(); d->m_fileFactories = ProjectFileFactory::createFactories(&d->m_projectFilterString); foreach (ProjectFileFactory *pf, d->m_fileFactories) { diff --git a/src/plugins/projectexplorer/projectexplorer.h b/src/plugins/projectexplorer/projectexplorer.h index aecfb0fcad..0d01e7babe 100644 --- a/src/plugins/projectexplorer/projectexplorer.h +++ b/src/plugins/projectexplorer/projectexplorer.h @@ -231,6 +231,9 @@ private slots: void testMsvcOutputParsers_data(); void testMsvcOutputParsers(); + + void testGccAbiGuessing_data(); + void testGccAbiGuessing(); #endif private: diff --git a/src/plugins/projectexplorer/projectexplorer.pro b/src/plugins/projectexplorer/projectexplorer.pro index c67aba3d9c..d293604f1d 100644 --- a/src/plugins/projectexplorer/projectexplorer.pro +++ b/src/plugins/projectexplorer/projectexplorer.pro @@ -10,6 +10,9 @@ include(../../libs/utils/utils.pri) include(customwizard/customwizard.pri) INCLUDEPATH += $$PWD/../../libs/utils HEADERS += projectexplorer.h \ + abi.h \ + gcctoolchain.h \ + msvctoolchain.h \ projectexplorer_export.h \ projectwindow.h \ buildmanager.h \ @@ -70,6 +73,9 @@ HEADERS += projectexplorer.h \ projectmodels.h \ currentprojectfind.h \ toolchain.h \ + toolchainconfigwidget.h \ + toolchainmanager.h \ + toolchainoptionspage.h \ userfileaccessor.h \ cesdkhandler.h \ gccparser.h \ @@ -98,11 +104,13 @@ HEADERS += projectexplorer.h \ customexecutableconfigurationwidget.h \ sessionnodeimpl.h \ metatypedeclarations.h \ - toolchaintype.h \ publishing/publishingwizardselectiondialog.h \ publishing/ipublishingwizardfactory.h SOURCES += projectexplorer.cpp \ + abi.cpp \ + gcctoolchain.cpp \ + msvctoolchain.cpp \ projectwindow.cpp \ buildmanager.cpp \ buildsteplist.cpp \ @@ -156,6 +164,9 @@ SOURCES += projectexplorer.cpp \ projectmodels.cpp \ currentprojectfind.cpp \ toolchain.cpp \ + toolchainconfigwidget.cpp \ + toolchainmanager.cpp \ + toolchainoptionspage.cpp \ cesdkhandler.cpp \ userfileaccessor.cpp \ gccparser.cpp \ @@ -185,6 +196,7 @@ SOURCES += projectexplorer.cpp \ publishing/publishingwizardselectiondialog.cpp FORMS += processstep.ui \ + toolchainoptionspage.ui \ editorsettingspropertiespage.ui \ runsettingspropertiespage.ui \ sessiondialog.ui \ @@ -212,4 +224,12 @@ win32 { macx:LIBS += -framework Carbon } RESOURCES += projectexplorer.qrc + +# Some way to override the architecture used in Abi: +!isEmpty($$(QTC_CPU)) { + DEFINES += QTC_CPU=$$(QTC_CPU) +} else { + DEFINES += QTC_CPU=x86 +} + DEFINES += PROJECTEXPLORER_LIBRARY diff --git a/src/plugins/projectexplorer/projectexplorerconstants.h b/src/plugins/projectexplorer/projectexplorerconstants.h index 005f029c24..4c87b694a0 100644 --- a/src/plugins/projectexplorer/projectexplorerconstants.h +++ b/src/plugins/projectexplorer/projectexplorerconstants.h @@ -184,6 +184,7 @@ const char * const ICON_DEBUG = ":/projectexplorer/images/debugger_sta const char * const ICON_DEBUG_SMALL = ":/projectexplorer/images/debugger_start_small.png"; const char * const ICON_CLOSETAB = ":/projectexplorer/images/closetab.png"; const char * const ICON_STOP = ":/projectexplorer/images/stop.png"; +const char * const ICON_TOOLCHAIN_SETTINGS_CATEGORY = ":projectexplorer/images/build.png"; // FIXME: Need an icon! // find filters const char * const FIND_CUR_PROJECT = "ProjectExplorer.FindFilter.CurrentProject"; @@ -206,6 +207,8 @@ const char * const PROJECTEXPLORER_SETTINGS_CATEGORY = "K.ProjectExplorer"; const char * const PROJECTEXPLORER_SETTINGS_TR_CATEGORY = QT_TRANSLATE_NOOP("ProjectExplorer", "Projects"); const char * const PROJECTEXPLORER_SETTINGS_CATEGORY_ICON = ":/core/images/category_project.png"; const char * const PROJECTEXPLORER_SETTINGS_ID = "ProjectExplorer.ProjectExplorer"; +const char * const TOOLCHAIN_SETTINGS_CATEGORY = "ProjectExplorer.Settings.ToolChains"; +const char * const TOOLCHAIN_SETTINGS_PAGE_ID = "M.ProjectExplorer.ToolChainOptions"; // task categories const char * const TASK_CATEGORY_COMPILE = "Task.Category.Compile"; @@ -224,6 +227,12 @@ const char * const BUILDSTEPS_DEPLOY = "ProjectExplorer.BuildSteps.Deploy"; // Deploy Configuration id: const char * const DEFAULT_DEPLOYCONFIGURATION_ID = "ProjectExplorer.DefaultDeployConfiguration"; +// ToolChain Ids +const char * const GCC_TOOLCHAIN_ID = "ProjectExplorer.ToolChain.Gcc"; +const char * const MINGW_TOOLCHAIN_ID = "ProjectExplorer.ToolChain.Mingw"; +const char * const LINUXICC_TOOLCHAIN_ID = "ProjectExplorer.ToolChain.LinuxIcc"; +const char * const MSVC_TOOLCHAIN_ID = "ProjectExplorer.ToolChain.Msvc"; + // Run Configuration defaults: const int QML_DEFAULT_DEBUG_SERVER_PORT = 3768; diff --git a/src/plugins/projectexplorer/runconfiguration.cpp b/src/plugins/projectexplorer/runconfiguration.cpp index 231f56a5cb..0b2a62266e 100644 --- a/src/plugins/projectexplorer/runconfiguration.cpp +++ b/src/plugins/projectexplorer/runconfiguration.cpp @@ -36,6 +36,7 @@ #include "outputformatter.h" #include "project.h" #include "target.h" +#include "toolchain.h" #include "buildconfiguration.h" #include "projectexplorerconstants.h" #include <extensionsystem/pluginmanager.h> @@ -241,6 +242,17 @@ QVariantMap RunConfiguration::toMap() const return map; } +ProjectExplorer::Abi RunConfiguration::abi() const +{ + BuildConfiguration *bc = target()->activeBuildConfiguration(); + if (!bc) + return Abi::hostAbi(); + ToolChain *tc = bc->toolChain(); + if (!tc) + return Abi::hostAbi(); + return tc->targetAbi(); +} + bool RunConfiguration::fromMap(const QVariantMap &map) { m_useCppDebugger = map.value(QLatin1String(USE_CPP_DEBUGGER_KEY), true).toBool(); diff --git a/src/plugins/projectexplorer/runconfiguration.h b/src/plugins/projectexplorer/runconfiguration.h index fa636b3a8d..b5458c36a5 100644 --- a/src/plugins/projectexplorer/runconfiguration.h +++ b/src/plugins/projectexplorer/runconfiguration.h @@ -34,6 +34,7 @@ #ifndef RUNCONFIGURATION_H #define RUNCONFIGURATION_H +#include "abi.h" #include "projectconfiguration.h" #include "projectexplorer_export.h" #include "outputformat.h" @@ -102,6 +103,8 @@ public: virtual QVariantMap toMap() const; + virtual ProjectExplorer::Abi abi() const; + signals: void isEnabledChanged(bool value); void debuggersChanged(); diff --git a/src/plugins/projectexplorer/target.cpp b/src/plugins/projectexplorer/target.cpp index 92b390306a..3f63cd5b02 100644 --- a/src/plugins/projectexplorer/target.cpp +++ b/src/plugins/projectexplorer/target.cpp @@ -38,6 +38,7 @@ #include "project.h" #include "projectexplorerconstants.h" #include "runconfiguration.h" +#include "toolchainmanager.h" #include <limits> #include <utils/qtcassert.h> @@ -354,6 +355,25 @@ void Target::setToolTip(const QString &text) emit toolTipChanged(); } +QList<ToolChain *> Target::possibleToolChains(BuildConfiguration *) const +{ + QList<ToolChain *> tcList = ToolChainManager::instance()->toolChains(); + QList<ToolChain *> result; + foreach (ToolChain *tc, tcList) { + if (!tc->restrictedToTargets().contains(id())) + result.append(tc); + } + return result; +} + +ToolChain *Target::preferredToolChain(BuildConfiguration *bc) const +{ + QList<ToolChain *> tcs = possibleToolChains(bc); + if (tcs.isEmpty()) + return 0; + return tcs.at(0); +} + QVariantMap Target::toMap() const { const QList<BuildConfiguration *> bcs = buildConfigurations(); diff --git a/src/plugins/projectexplorer/target.h b/src/plugins/projectexplorer/target.h index 9f741da05f..f42a4d82ad 100644 --- a/src/plugins/projectexplorer/target.h +++ b/src/plugins/projectexplorer/target.h @@ -45,6 +45,7 @@ class Environment; namespace ProjectExplorer { class RunConfiguration; +class ToolChain; class BuildConfiguration; class DeployConfiguration; class IBuildConfigurationFactory; @@ -108,6 +109,10 @@ public: QString toolTip() const; void setToolTip(const QString &text); + virtual QList<ToolChain *> possibleToolChains(BuildConfiguration *) const; + virtual ToolChain *preferredToolChain(BuildConfiguration *) const; + + virtual QVariantMap toMap() const; signals: diff --git a/src/plugins/projectexplorer/toolchain.cpp b/src/plugins/projectexplorer/toolchain.cpp index 54eabbed14..1713a08fa6 100644 --- a/src/plugins/projectexplorer/toolchain.cpp +++ b/src/plugins/projectexplorer/toolchain.cpp @@ -32,903 +32,160 @@ **************************************************************************/ #include "toolchain.h" -#include "project.h" -#include "cesdkhandler.h" -#include "projectexplorersettings.h" -#include "gccparser.h" -#include "msvcparser.h" -#include "linuxiccparser.h" - -#include <utils/synchronousprocess.h> -#include <utils/qtcprocess.h> - -#include <QtCore/QDebug> -#include <QtCore/QFileInfo> -#include <QtCore/QProcess> -#include <QtCore/QSettings> -#include <QtCore/QDir> -#include <QtCore/QTemporaryFile> -#include <QtCore/QString> -#include <QtCore/QCoreApplication> - -using namespace ProjectExplorer; -using namespace ProjectExplorer::Internal; - -enum { debug = 0 }; - -#ifdef Q_OS_WIN64 -static const char MSVC_RegKey[] = "HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\Microsoft\\VisualStudio\\SxS\\VC7"; -#else -static const char MSVC_RegKey[] = "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\SxS\\VC7"; -#endif - -bool ToolChain::equals(const ToolChain *a, const ToolChain *b) -{ - if (a == b) - return true; - if (a == 0 || b == 0) - return false; - if (a->type() == b->type()) - return a->equals(b); - return false; -} - -ToolChain::ToolChain() -{ -} - -ToolChain::~ToolChain() -{ -} - -ToolChain *ToolChain::createGccToolChain(const QString &gcc) -{ - return new GccToolChain(gcc); -} - -ToolChain *ToolChain::createMinGWToolChain(const QString &gcc, const QString &mingwPath) -{ - return new MinGWToolChain(gcc, mingwPath); -} - -ToolChain *ToolChain::createLinuxIccToolChain() -{ - return new LinuxIccToolChain(); -} - -ToolChain *ToolChain::createMSVCToolChain(const QString &name, bool amd64) -{ - return MSVCToolChain::create(name, amd64); -} - -ToolChain *ToolChain::createWinCEToolChain(const QString &name, const QString &platform) -{ - return WinCEToolChain::create(name, platform); -} - -QStringList ToolChain::availableMSVCVersions() -{ - QStringList rc; - foreach(const MSVCToolChain::Installation &i, MSVCToolChain::installations()) - rc.push_back(i.name); - return rc; -} - -QStringList ToolChain::availableMSVCVersions(bool amd64) -{ - QStringList rc; - foreach(const MSVCToolChain::Installation &i, MSVCToolChain::installations()) - if (i.is64bit() == amd64) - rc.push_back(i.name); - return rc; -} - -QList<ToolChainType> ToolChain::supportedToolChains() -{ - QList<ToolChainType> toolChains; - for (int i = 0; i < ToolChain_LAST_VALID; ++i) { - toolChains.append(ToolChainType(i)); - } - return toolChains; -} - -QString ToolChain::toolChainName(ToolChainType tc) -{ - switch (tc) { - case ToolChain_GCC: - return QCoreApplication::translate("ToolChain", "GCC"); - case ToolChain_LINUX_ICC: - return QCoreApplication::translate("ToolChain", "Intel C++ Compiler (Linux)"); - case ToolChain_MinGW: - return QString::fromLatin1("MinGW"); - case ToolChain_MSVC: - return QCoreApplication::translate("ToolChain", "Microsoft Visual C++"); - case ToolChain_WINCE: - return QCoreApplication::translate("ToolChain", "Windows CE"); - case ToolChain_WINSCW: - return QCoreApplication::translate("ToolChain", "WINSCW"); - case ToolChain_GCCE: - return QCoreApplication::translate("ToolChain", "GCCE"); - case ToolChain_GCCE_GNUPOC: - return QCoreApplication::translate("ToolChain", "GCCE/GnuPoc"); - case ToolChain_RVCT_ARMV5_GNUPOC: - return QCoreApplication::translate("ToolChain", "RVCT (ARMV6)/GnuPoc"); - case ToolChain_RVCT2_ARMV5: - return QCoreApplication::translate("ToolChain", "RVCT 2 (ARMV5)"); - case ToolChain_RVCT2_ARMV6: - return QCoreApplication::translate("ToolChain", "RVCT 2 (ARMV6)"); - case ToolChain_RVCT4_ARMV5: - return QCoreApplication::translate("ToolChain", "RVCT 4 (ARMV5)"); - case ToolChain_RVCT4_ARMV6: - return QCoreApplication::translate("ToolChain", "RVCT 4 (ARMV6)"); - case ToolChain_GCC_MAEMO5: - return QCoreApplication::translate("ToolChain", "GCC for Maemo5"); - case ToolChain_GCC_HARMATTAN: - return QCoreApplication::translate("ToolChain", "GCC for Harmattan"); - case ToolChain_GCC_MEEGO: - return QCoreApplication::translate("ToolChain", "GCC for Meego"); - case ToolChain_OTHER: - return QCoreApplication::translate("ToolChain", "Other"); - case ToolChain_INVALID: - return QCoreApplication::translate("ToolChain", "<Invalid>"); - case ToolChain_UNKNOWN: - break; - default: - Q_ASSERT("Missing name for Toolchaintype"); - }; - return QCoreApplication::translate("ToolChain", "<Unknown>"); -} - -GccToolChain::GccToolChain(const QString &gcc) - : m_gcc(gcc) -{ - -} - -ToolChainType GccToolChain::type() const -{ - return ToolChain_GCC; -} - -static QByteArray gccPredefinedMacros(const QString &gcc, const QStringList &env) -{ - QStringList arguments; - arguments << QLatin1String("-xc++") - << QLatin1String("-E") - << QLatin1String("-dM") - << QLatin1String("-"); - - QProcess cpp; - cpp.setEnvironment(env); - cpp.start(gcc, arguments); - if (!cpp.waitForStarted()) { - qWarning("%s: Cannot start '%s': %s", Q_FUNC_INFO, qPrintable(gcc), - qPrintable(cpp.errorString())); - return QByteArray(); - } - cpp.closeWriteChannel(); - if (!cpp.waitForFinished()) { - Utils::SynchronousProcess::stopProcess(cpp); - qWarning("%s: Timeout running '%s'.", Q_FUNC_INFO, qPrintable(gcc)); - return QByteArray(); - } - if (cpp.exitStatus() != QProcess::NormalExit) { - qWarning("%s: '%s' crashed.", Q_FUNC_INFO, qPrintable(gcc)); - return QByteArray(); - } - QByteArray predefinedMacros = cpp.readAllStandardOutput(); -#ifdef Q_OS_MAC - // Turn off flag indicating Apple's blocks support - const QByteArray blocksDefine("#define __BLOCKS__ 1"); - const QByteArray blocksUndefine("#undef __BLOCKS__"); - const int idx = predefinedMacros.indexOf(blocksDefine); - if (idx != -1) { - predefinedMacros.replace(idx, blocksDefine.length(), blocksUndefine); - } - - // Define __strong and __weak (used for Apple's GC extension of C) to be empty - predefinedMacros.append("#define __strong\n"); - predefinedMacros.append("#define __weak\n"); -#endif // Q_OS_MAC - return predefinedMacros; -} - -QByteArray GccToolChain::predefinedMacros() -{ - if (m_predefinedMacros.isEmpty()) { - Utils::Environment env = Utils::Environment::systemEnvironment(); - addToEnvironment(env); - m_predefinedMacros = gccPredefinedMacros(m_gcc, env.toStringList()); - } - return m_predefinedMacros; -} - -static QList<HeaderPath> gccSystemHeaderPaths(const QString &gcc, Utils::Environment env) -{ - QList<HeaderPath> systemHeaderPaths; - QStringList arguments; - arguments << QLatin1String("-xc++") - << QLatin1String("-E") - << QLatin1String("-v") - << QLatin1String("-"); - - QProcess cpp; - env.set(QLatin1String("LC_ALL"), QLatin1String("C")); //override current locale settings - cpp.setEnvironment(env.toStringList()); - cpp.setReadChannelMode(QProcess::MergedChannels); - cpp.start(gcc, arguments); - if (!cpp.waitForStarted()) { - qWarning("%s: Cannot start '%s': %s", Q_FUNC_INFO, qPrintable(gcc), - qPrintable(cpp.errorString())); - return systemHeaderPaths; - } - cpp.closeWriteChannel(); - if (!cpp.waitForFinished()) { - Utils::SynchronousProcess::stopProcess(cpp); - qWarning("%s: Timeout running '%s'.", Q_FUNC_INFO, qPrintable(gcc)); - return systemHeaderPaths; - } - if (cpp.exitStatus() != QProcess::NormalExit) { - qWarning("%s: '%s' crashed.", Q_FUNC_INFO, qPrintable(gcc)); - return systemHeaderPaths; - } - QByteArray line; - while (cpp.canReadLine()) { - line = cpp.readLine(); - if (line.startsWith("#include")) - break; - } - - if (! line.isEmpty() && line.startsWith("#include")) { - HeaderPath::Kind kind = HeaderPath::UserHeaderPath; - while (cpp.canReadLine()) { - line = cpp.readLine(); - if (line.startsWith("#include")) { - kind = HeaderPath::GlobalHeaderPath; - } else if (! line.isEmpty() && QChar(line.at(0)).isSpace()) { - HeaderPath::Kind thisHeaderKind = kind; - - line = line.trimmed(); - if (line.endsWith('\n')) - line.chop(1); - - const int index = line.indexOf(" (framework directory)"); - if (index != -1) { - line.truncate(index); - thisHeaderKind = HeaderPath::FrameworkHeaderPath; - } - - systemHeaderPaths.append(HeaderPath(QFile::decodeName(line), thisHeaderKind)); - } else if (line.startsWith("End of search list.")) { - break; - } else { - qWarning() << "ignore line:" << line; - } - } - } - return systemHeaderPaths; -} - -QList<HeaderPath> GccToolChain::systemHeaderPaths() -{ - if (m_systemHeaderPaths.isEmpty()) { - Utils::Environment env = Utils::Environment::systemEnvironment(); - addToEnvironment(env); - m_systemHeaderPaths = gccSystemHeaderPaths(m_gcc, env); - } - return m_systemHeaderPaths; -} - -void GccToolChain::addToEnvironment(Utils::Environment &env) -{ - Q_UNUSED(env) -} - -QString GccToolChain::makeCommand() const -{ - return QLatin1String("make"); -} - -IOutputParser *GccToolChain::outputParser() const -{ - return new GccParser; -} +#include <extensionsystem/pluginmanager.h> +#include <utils/environment.h> -bool GccToolChain::equals(const ToolChain *other) const -{ - return (m_gcc == static_cast<const GccToolChain *>(other)->m_gcc); -} +#include <QtCore/QCoreApplication> -MinGWToolChain::MinGWToolChain(const QString &gcc, const QString &mingwPath) - : GccToolChain(gcc), m_mingwPath(mingwPath) -{ +static const char *const ID_KEY = "ProjectExplorer.ToolChain.Id"; +static const char *const DISPLAY_NAME_KEY = "ProjectExplorer.ToolChain.DisplayName"; -} +namespace ProjectExplorer { +namespace Internal { -ToolChainType MinGWToolChain::type() const -{ - return ToolChain_MinGW; -} +// -------------------------------------------------------------------------- +// ToolChainPrivate +// -------------------------------------------------------------------------- -bool MinGWToolChain::equals(const ToolChain *other) const +class ToolChainPrivate { - const MinGWToolChain *o = static_cast<const MinGWToolChain *>(other); - return (m_mingwPath == o->m_mingwPath && this->GccToolChain::equals(other)); -} +public: + ToolChainPrivate(const QString &id, bool autodetect) : + m_id(id), + m_autodetect(autodetect) + { Q_ASSERT(!id.isEmpty()); } -void MinGWToolChain::addToEnvironment(Utils::Environment &env) -{ - if (debug) - qDebug() << "MinGWToolChain::addToEnvironment" << m_mingwPath; - if (m_mingwPath.isEmpty()) - return; - const QString binDir = m_mingwPath + "/bin"; - if (QFileInfo(binDir).exists()) - env.prependOrSetPath(binDir); -} + QString m_id; + bool m_autodetect; + mutable QString m_displayName; +}; -QString MinGWToolChain::makeCommand() const -{ - return QLatin1String("mingw32-make.exe"); -} +} // namespace Internal -IOutputParser *MinGWToolChain::outputParser() const -{ - return new GccParser; -} +// -------------------------------------------------------------------------- +// ToolChain +// -------------------------------------------------------------------------- -LinuxIccToolChain::LinuxIccToolChain() - : GccToolChain(QLatin1String("icpc")) -{ -} +ToolChain::ToolChain(const QString &id, bool autodetect) : + m_d(new Internal::ToolChainPrivate(id, autodetect)) +{ } -ToolChainType LinuxIccToolChain::type() const +ToolChain::ToolChain(const ToolChain &other) : + m_d(new Internal::ToolChainPrivate(other.id(), false)) { - return ToolChain_LINUX_ICC; + // leave the autodetection bit at false. + m_d->m_displayName = other.displayName(); } -IOutputParser *LinuxIccToolChain::outputParser() const +ToolChain::~ToolChain() { - return new LinuxIccParser; + delete m_d; } -// ---------------- MSVC installation location code - -// Format the name of an SDK or VC installation version with platform -static inline QString installationName(const QString &name, - MSVCToolChain::Installation::Type t, - MSVCToolChain::Installation::Platform p) +QString ToolChain::displayName() const { - if (t == MSVCToolChain::Installation::WindowsSDK) { - QString sdkName = name; - sdkName += QLatin1String(" ("); - sdkName += MSVCToolChain::Installation::platformName(p); - sdkName += QLatin1Char(')'); - return sdkName; - } - // Comes as "9.0" from the registry - QString vcName = QLatin1String("Microsoft Visual C++ Compilers "); - vcName += name; - vcName+= QLatin1String(" ("); - vcName += MSVCToolChain::Installation::platformName(p); - vcName += QLatin1Char(')'); - return vcName; + if (m_d->m_displayName.isEmpty()) + return typeName(); + return m_d->m_displayName; } -MSVCToolChain::Installation::Installation(Type t, const QString &n, Platform p, - const QString &v, const QString &a) : - type(t), name(installationName(n, t, p)), platform(p), varsBat(v), varsBatArg(a) +void ToolChain::setDisplayName(const QString &name) const { + m_d->m_displayName = name; } -MSVCToolChain::Installation::Installation() : platform(s32) +bool ToolChain::isAutoDetected() const { + return m_d->m_autodetect; } -QString MSVCToolChain::Installation::platformName(Platform t) +QString ToolChain::id() const { - switch (t) { - case s32: - return QLatin1String("x86"); - case s64: - return QLatin1String("x64"); - case ia64: - return QLatin1String("ia64"); - case amd64: - return QLatin1String("amd64"); - } - return QString(); + return m_d->m_id; } -bool MSVCToolChain::Installation::is64bit() const +QStringList ToolChain::restrictedToTargets() const { - return platform != s32; + return QStringList(); } -MSVCToolChain::InstallationList MSVCToolChain::installations() +bool ToolChain::canClone() const { - static InstallationList installs; - static bool firstTime = true; - if (firstTime) { - firstTime = false; - // 1) Installed SDKs preferred over standalone Visual studio - const char sdk_RegKeyC[] = "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Microsoft SDKs\\Windows"; - const QSettings sdkRegistry(sdk_RegKeyC, QSettings::NativeFormat); - const QString defaultSdkPath = sdkRegistry.value(QLatin1String("CurrentInstallFolder")).toString(); - if (!defaultSdkPath.isEmpty()) { - foreach(const QString &sdkKey, sdkRegistry.childGroups()) { - const QString name = sdkRegistry.value(sdkKey + QLatin1String("/ProductName")).toString(); - const QString folder = sdkRegistry.value(sdkKey + QLatin1String("/InstallationFolder")).toString(); - if (!folder.isEmpty()) { - const QString sdkVcVarsBat = folder + QLatin1String("bin\\SetEnv.cmd"); - if (QFileInfo(sdkVcVarsBat).exists()) { - // Add all platforms - InstallationList newInstalls; - newInstalls.push_back(Installation(Installation::WindowsSDK, name, Installation::s32, sdkVcVarsBat, QLatin1String("/x86"))); -#ifdef Q_OS_WIN64 - newInstalls.push_back(Installation(Installation::WindowsSDK, name, Installation::s64, sdkVcVarsBat, QLatin1String("/x64"))); - newInstalls.push_back(Installation(Installation::WindowsSDK, name, Installation::ia64, sdkVcVarsBat, QLatin1String("/ia64"))); -#endif - // Make sure the default is front. - if (folder == defaultSdkPath && !installs.empty()) { - const InstallationList old = installs; - installs = newInstalls + old; - } else { - installs.append(newInstalls); - } - } // bat exists - } // folder - } // foreach - } - // 2) Installed MSVCs - const QSettings vsRegistry(MSVC_RegKey, QSettings::NativeFormat); - foreach(const QString &vsName, vsRegistry.allKeys()) { - const int dotPos = vsName.indexOf(QLatin1Char('.')); - if (dotPos != -1) { // Scan for version major.minor - const QString path = vsRegistry.value(vsName).toString(); - const int version = vsName.left(dotPos).toInt(); - // Check existence of various install scripts - const QString vcvars32bat = path + QLatin1String("bin\\vcvars32.bat"); - if (QFileInfo(vcvars32bat).isFile()) - installs.push_back(Installation(Installation::VS, vsName, Installation::s32, vcvars32bat)); - if (version >= 10) { - // Just one common file - const QString vcvarsAllbat = path + QLatin1String("vcvarsall.bat"); - if (QFileInfo(vcvarsAllbat).isFile()) { - installs.push_back(Installation(Installation::VS, vsName, Installation::s32, vcvarsAllbat, QLatin1String("x86"))); - installs.push_back(Installation(Installation::VS, vsName, Installation::amd64, vcvarsAllbat, QLatin1String("amd64"))); - installs.push_back(Installation(Installation::VS, vsName, Installation::s64, vcvarsAllbat, QLatin1String("x64"))); - installs.push_back(Installation(Installation::VS, vsName, Installation::ia64, vcvarsAllbat, QLatin1String("ia64"))); - } else { - qWarning("Unable to find MSVC setup script %s in version %d", qPrintable(vcvarsAllbat), version); - } - } else { - // Amd 64 is the preferred 64bit platform - const QString vcvarsAmd64bat = path + QLatin1String("bin\\amd64\\vcvarsamd64.bat"); - if (QFileInfo(vcvarsAmd64bat).isFile()) - installs.push_back(Installation(Installation::VS, vsName, Installation::amd64, vcvarsAmd64bat)); - const QString vcvarsAmd64bat2 = path + QLatin1String("bin\\vcvarsx86_amd64.bat"); - if (QFileInfo(vcvarsAmd64bat2).isFile()) - installs.push_back(Installation(Installation::VS, vsName, Installation::amd64, vcvarsAmd64bat2)); - const QString vcvars64bat = path + QLatin1String("bin\\vcvars64.bat"); - if (QFileInfo(vcvars64bat).isFile()) - installs.push_back(Installation(Installation::VS, vsName, Installation::s64, vcvars64bat)); - const QString vcvarsIA64bat = path + QLatin1String("bin\\vcvarsx86_ia64.bat"); - if (QFileInfo(vcvarsIA64bat).isFile()) - installs.push_back(Installation(Installation::VS, vsName, Installation::ia64, vcvarsIA64bat)); - } - } - } - } - if (debug) - foreach(const Installation &i, installs) - qDebug() << i; - return installs; + return true; } -// Return a substring to match the MSVC official version against by mkSpec name. -static inline const QString msvcVersionStringFromMkSpec(const QString &mkSpec) +QString ToolChain::defaultMakeTarget() const { - if (mkSpec.isEmpty()) - return QString(); - if (mkSpec.endsWith(QLatin1String("msvc2002"))) - return QLatin1String(" 7.0"); - if (mkSpec.endsWith(QLatin1String("msvc2003"))) - return QLatin1String(" 7.1"); - if (mkSpec.endsWith(QLatin1String("msvc2005"))) - return QLatin1String(" 8.0"); - if (mkSpec.endsWith(QLatin1String("msvc2008"))) - return QLatin1String(" 9.0"); - if (mkSpec.endsWith(QLatin1String("msvc2010"))) - return QLatin1String(" 10.0"); return QString(); } -MSVCToolChain::Installation MSVCToolChain::findInstallationByMkSpec(bool is64Bit, - const QString &mkSpec, - bool excludeSDK) +bool ToolChain::operator == (const ToolChain &tc) const { - const QString mkSpecMatchString = msvcVersionStringFromMkSpec(mkSpec); - if (!mkSpecMatchString.isEmpty()) { - foreach(const Installation &i, installations()) { - if ((i.type == Installation::VS) && (i.is64bit() == is64Bit) - && (i.name.indexOf(mkSpecMatchString) != -1)) - return i; - } - } - return findInstallationByName(is64Bit, QString(), excludeSDK); -} - -MSVCToolChain::Installation MSVCToolChain::findInstallationByName(bool is64Bit, - const QString &name, - bool excludeSDK) -{ - if (debug) - qDebug() << "find" << (is64Bit ? 64 : 32) << name << excludeSDK; - foreach(const Installation &i, installations()) { - if (i.type != Installation::WindowsSDK || !excludeSDK) { - if ((i.is64bit() == is64Bit) && (name.isEmpty() || name == i.name)) - return i; - } - } - return Installation(); -} - -namespace ProjectExplorer { -PROJECTEXPLORER_EXPORT QDebug operator<<(QDebug in, const MSVCToolChain::Installation &i) -{ - QDebug nsp = in.nospace(); - nsp << "Type: " << i.type << " Platform: " << i.platform << " Name: " << i.name - << "\nSetup: " << i.varsBat; - if (!i.varsBatArg.isEmpty()) - nsp << "\nSetup argument: " << i.varsBatArg; - return in; -} -} - -MSVCToolChain *MSVCToolChain::create(const QString &name, bool amd64) -{ - return new MSVCToolChain(MSVCToolChain::findInstallationByName(amd64, name)); -} - -MSVCToolChain::MSVCToolChain(const Installation &in) : - m_installation(in), - m_valuesSet(false) -{ - if (debug) - qDebug() << "\nMSVCToolChain::CT\n" << m_installation; -} - -ToolChainType MSVCToolChain::type() const -{ - return ToolChain_MSVC; -} - -bool MSVCToolChain::equals(const ToolChain *other) const -{ - const MSVCToolChain *o = static_cast<const MSVCToolChain *>(other); - return (m_installation.name == o->m_installation.name); -} - -QByteArray msvcCompilationFile() { - static const char* macros[] = {"_ATL_VER", "_CHAR_UNSIGNED", "__CLR_VER", - "__cplusplus_cli", "__COUNTER__", "__cplusplus", - "_CPPLIB_VER", "_CPPRTTI", "_CPPUNWIND", - "_DEBUG", "_DLL", "__FUNCDNAME__", - "__FUNCSIG__","__FUNCTION__","_INTEGRAL_MAX_BITS", - "_M_ALPHA","_M_CEE","_M_CEE_PURE", - "_M_CEE_SAFE","_M_IX86","_M_IA64", - "_M_IX86_FP","_M_MPPC","_M_MRX000", - "_M_PPC","_M_X64","_MANAGED", - "_MFC_VER","_MSC_BUILD", /* "_MSC_EXTENSIONS", */ - "_MSC_FULL_VER","_MSC_VER","__MSVC_RUNTIME_CHECKS", - "_MT", "_NATIVE_WCHAR_T_DEFINED", "_OPENMP", - "_VC_NODEFAULTLIB", "_WCHAR_T_DEFINED", "_WIN32", - "_WIN32_WCE", "_WIN64", "_Wp64", "__DATE__", - "__DATE__", "__TIME__", "__TIMESTAMP__", - 0}; - QByteArray file = "#define __PPOUT__(x) V##x=x\n\n"; - int i =0; - while (macros[i] != 0) { - const QByteArray macro(macros[i]); - file += "#if defined(" + macro + ")\n__PPOUT__(" - + macro + ")\n#endif\n"; - ++i; - } - file += "\nvoid main(){}\n\n"; - return file; -} - -// Run MSVC 'cl' compiler to obtain #defines. -static QByteArray msvcPredefinedMacros(const QStringList &env) -{ - QByteArray predefinedMacros = "#define __MSVCRT__\n" - "#define __w64\n" - "#define __int64 long long\n" - "#define __int32 long\n" - "#define __int16 short\n" - "#define __int8 char\n" - "#define __ptr32\n" - "#define __ptr64\n"; - - QString tmpFilePath; - { - // QTemporaryFile is buggy and will not unlock the file for cl.exe - QTemporaryFile tmpFile(QDir::tempPath()+"/envtestXXXXXX.cpp"); - tmpFile.setAutoRemove(false); - if (!tmpFile.open()) - return predefinedMacros; - tmpFilePath = QFileInfo(tmpFile).canonicalFilePath(); - tmpFile.write(msvcCompilationFile()); - tmpFile.close(); - } - QProcess cpp; - cpp.setEnvironment(env); - cpp.setWorkingDirectory(QDir::tempPath()); - QStringList arguments; - const QString binary = QLatin1String("cl.exe"); - arguments << QLatin1String("/EP") << QDir::toNativeSeparators(tmpFilePath); - cpp.start(QLatin1String("cl.exe"), arguments); - if (!cpp.waitForStarted()) { - qWarning("%s: Cannot start '%s': %s", Q_FUNC_INFO, qPrintable(binary), - qPrintable(cpp.errorString())); - return predefinedMacros; - } - cpp.closeWriteChannel(); - if (!cpp.waitForFinished()) { - Utils::SynchronousProcess::stopProcess(cpp); - qWarning("%s: Timeout running '%s'.", Q_FUNC_INFO, qPrintable(binary)); - return predefinedMacros; - } - if (cpp.exitStatus() != QProcess::NormalExit) { - qWarning("%s: '%s' crashed.", Q_FUNC_INFO, qPrintable(binary)); - return predefinedMacros; - } - - const QList<QByteArray> output = cpp.readAllStandardOutput().split('\n'); - foreach (const QByteArray& line, output) { - if (line.startsWith('V')) { - QList<QByteArray> split = line.split('='); - const QByteArray key = split.at(0).mid(1); - QByteArray value = split.at(1); - if (!value.isEmpty()) { - value.chop(1); //remove '\n' - } - predefinedMacros += "#define "; - predefinedMacros += key; - predefinedMacros += ' '; - predefinedMacros += value; - predefinedMacros += '\n'; - } - } - QFile::remove(tmpFilePath); - return predefinedMacros; -} + if (this == &tc) + return true; -QByteArray MSVCToolChain::predefinedMacros() -{ - if (m_predefinedMacros.isEmpty()) { - Utils::Environment env = Utils::Environment::systemEnvironment(); - addToEnvironment(env); - m_predefinedMacros = msvcPredefinedMacros(env.toStringList()); - } - return m_predefinedMacros; + return id() == tc.id(); } -QList<HeaderPath> MSVCToolChain::systemHeaderPaths() +QVariantMap ToolChain::toMap() const { - //TODO fix this code - Utils::Environment env = Utils::Environment::systemEnvironment(); - addToEnvironment(env); - QList<HeaderPath> headerPaths; - foreach(const QString &path, env.value("INCLUDE").split(QLatin1Char(';'))) { - headerPaths.append(HeaderPath(path, HeaderPath::GlobalHeaderPath)); - } - return headerPaths; -} + QVariantMap result; + if (isAutoDetected()) + return result; -MSVCToolChain::StringStringPairList MSVCToolChain::readEnvironmentSetting(const QString &varsBat, - const QStringList &args, - const Utils::Environment &env) -{ - const StringStringPairList rc = readEnvironmentSettingI(varsBat, args, env); - if (debug) { - qDebug() << "Running: " << varsBat << args; - if (debug > 1) { - qDebug() << "Incoming: " << env.toStringList(); - foreach(const StringStringPair &e, rc) - qDebug() << e.first << e.second; - } else { - qDebug() << "Read: " << rc.size() << " variables."; - } - } - return rc; -} + result.insert(QLatin1String(ID_KEY), id()); + result.insert(QLatin1String(DISPLAY_NAME_KEY), displayName()); -// Windows: Expand the delayed evaluation references returned by the -// SDK setup scripts: "PATH=!Path!;foo". Some values might expand -// to empty and should not be added -static inline QString winExpandDelayedEnvReferences(QString in, const Utils::Environment &env) -{ - const QChar exclamationMark = QLatin1Char('!'); - for (int pos = 0; pos < in.size(); ) { - // Replace "!REF!" by its value in process environment - pos = in.indexOf(exclamationMark, pos); - if (pos == -1) - break; - const int nextPos = in.indexOf(exclamationMark, pos + 1); - if (nextPos == -1) - break; - const QString var = in.mid(pos + 1, nextPos - pos - 1); - const QString replacement = env.value(var.toUpper()); - in.replace(pos, nextPos + 1 - pos, replacement); - pos += replacement.size(); - } - return in; + return result; } -MSVCToolChain::StringStringPairList MSVCToolChain::readEnvironmentSettingI(const QString &varsBat, - const QStringList &args, - const Utils::Environment &env) +void ToolChain::setId(const QString &id) { - // Run the setup script and extract the variables - if (!QFileInfo(varsBat).exists()) - return StringStringPairList(); - const QString tempOutputFileName = QDir::tempPath() + QLatin1String("\\qtcreator-msvc-environment.txt"); - QTemporaryFile tf(QDir::tempPath() + "\\XXXXXX.bat"); - tf.setAutoRemove(true); - if (!tf.open()) - return StringStringPairList(); - const QString filename = tf.fileName(); - QByteArray call = "call "; - call += Utils::QtcProcess::quoteArg(varsBat).toLocal8Bit(); - if (!args.isEmpty()) { - call += ' '; - call += Utils::QtcProcess::joinArgs(args).toLocal8Bit(); - } - call += "\r\n"; - tf.write(call); - const QByteArray redirect = "set > " + Utils::QtcProcess::quoteArg( - QDir::toNativeSeparators(tempOutputFileName)).toLocal8Bit() + "\r\n"; - tf.write(redirect); - tf.flush(); - tf.waitForBytesWritten(30000); - - QProcess run; - run.setEnvironment(env.toStringList()); - const QString cmdPath = QString::fromLocal8Bit(qgetenv("COMSPEC")); - run.start(cmdPath, QStringList()<< QLatin1String("/c")<<QDir::toNativeSeparators(filename)); - if (!run.waitForStarted()) { - qWarning("%s: Unable to run '%s': %s", Q_FUNC_INFO, qPrintable(varsBat), - qPrintable(run.errorString())); - return StringStringPairList(); - } - if (!run.waitForFinished()) { - qWarning("%s: Timeout running '%s'", Q_FUNC_INFO, qPrintable(varsBat)); - Utils::SynchronousProcess::stopProcess(run); - return StringStringPairList(); - } - tf.close(); - - QFile varsFile(tempOutputFileName); - if (!varsFile.open(QIODevice::ReadOnly|QIODevice::Text)) - return StringStringPairList(); - - QRegExp regexp(QLatin1String("(\\w*)=(.*)")); - StringStringPairList rc; - while (!varsFile.atEnd()) { - const QString line = QString::fromLocal8Bit(varsFile.readLine()).trimmed(); - if (regexp.exactMatch(line)) { - const QString varName = regexp.cap(1); - const QString expandedValue = winExpandDelayedEnvReferences(regexp.cap(2), env); - if (!expandedValue.isEmpty()) - rc.append(StringStringPair(varName, expandedValue)); - } - } - varsFile.close(); - varsFile.remove(); - return rc; + Q_ASSERT(!id.isEmpty()); + m_d->m_id = id; } -void MSVCToolChain::addToEnvironment(Utils::Environment &env) +bool ToolChain::fromMap(const QVariantMap &data) { - if (debug) - qDebug() << "MSVCToolChain::addToEnvironment" << m_installation.name; - if (m_installation.name.isEmpty() || m_installation.varsBat.isEmpty()) { - qWarning("%s: Attempt to set up invalid MSVC Toolchain.", Q_FUNC_INFO); - return; - } - // We cache the full environment (incoming + modifications by setup script). - if (!m_valuesSet || env != m_lastEnvironment) { - m_lastEnvironment = env; - const QStringList args = m_installation.varsBatArg.isEmpty() ? - QStringList() : QStringList(m_installation.varsBatArg); - m_values = readEnvironmentSetting(m_installation.varsBat, args, env); - m_valuesSet = true; - } - - const StringStringPairList::const_iterator end = m_values.constEnd(); - for (StringStringPairList::const_iterator it = m_values.constBegin(); it != end; ++it) - env.set((*it).first, (*it).second); -} + Q_ASSERT(!isAutoDetected()); + // do not read the id: That is already set anyway. + m_d->m_displayName = data.value(QLatin1String(DISPLAY_NAME_KEY)).toString(); -QString MSVCToolChain::makeCommand() const -{ - if (ProjectExplorerPlugin::instance()->projectExplorerSettings().useJom) { - // We want jom! Try to find it. - QString jom = QCoreApplication::applicationDirPath() + QLatin1String("/jom.exe"); - if (QFileInfo(jom).exists()) - return jom; - else - return QLatin1String("jom.exe"); - } - return QLatin1String("nmake.exe"); + return true; } -IOutputParser *MSVCToolChain::outputParser() const -{ - return new MsvcParser; -} +// -------------------------------------------------------------------------- +// ToolChainFactory +// -------------------------------------------------------------------------- -WinCEToolChain *WinCEToolChain::create(const QString &name, const QString &platform) +QList<ToolChain *> ToolChainFactory::autoDetect() { - const bool excludeSDK = true; - return new WinCEToolChain(findInstallationByName(false, name, excludeSDK), platform); + return QList<ToolChain *>(); } -WinCEToolChain::WinCEToolChain(const Installation &in, const QString &platform) : - MSVCToolChain(in), - m_platform(platform) +bool ToolChainFactory::canCreate() { + return false; } -ToolChainType WinCEToolChain::type() const +ToolChain *ToolChainFactory::create() { - return ToolChain_WINCE; + return 0; } -bool WinCEToolChain::equals(const ToolChain *other) const +bool ToolChainFactory::canRestore(const QVariantMap &) { - const WinCEToolChain *o = static_cast<const WinCEToolChain *>(other); - return (m_platform == o->m_platform && this->MSVCToolChain::equals(other)); + return false; } -QByteArray WinCEToolChain::predefinedMacros() +ToolChain *ToolChainFactory::restore(const QVariantMap &) { - //TODO - return MSVCToolChain::predefinedMacros(); + return 0; } -QList<HeaderPath> WinCEToolChain::systemHeaderPaths() +QString ToolChainFactory::idFromMap(const QVariantMap &data) { - //TODO fix this code - Utils::Environment env = Utils::Environment::systemEnvironment(); - addToEnvironment(env); - - QList<HeaderPath> headerPaths; - - const QStringList includes = env.value("INCLUDE").split(QLatin1Char(';')); - - foreach (const QString &path, includes) { - const HeaderPath headerPath(path, HeaderPath::GlobalHeaderPath); - headerPaths.append(headerPath); - } - - return headerPaths; + return data.value(QLatin1String(ID_KEY)).toString(); } -void WinCEToolChain::addToEnvironment(Utils::Environment &env) -{ - MSVCToolChain::addToEnvironment(env); - QSettings registry(MSVC_RegKey, QSettings::NativeFormat); - QString path = registry.value(m_installation.name).toString(); - - // Find MSVC path - - path += QLatin1Char('/'); - - // Find Platform name - CeSdkHandler cesdkhandler; - cesdkhandler.parse(path); - cesdkhandler.find(m_platform).addToEnvironment(env); -} +} // namespace ProjectExplorer diff --git a/src/plugins/projectexplorer/toolchain.h b/src/plugins/projectexplorer/toolchain.h index 1c9b166962..5a97e9a7b0 100644 --- a/src/plugins/projectexplorer/toolchain.h +++ b/src/plugins/projectexplorer/toolchain.h @@ -35,18 +35,32 @@ #define TOOLCHAIN_H #include "projectexplorer_export.h" -#include "toolchaintype.h" -#include <utils/environment.h> +#include "abi.h" +#include <QtCore/QObject> #include <QtCore/QString> #include <QtCore/QPair> #include <QtCore/QMetaType> +#include <QtCore/QVariantMap> + +namespace Utils { +class Environment; +} namespace ProjectExplorer { +namespace Internal { +class ToolChainPrivate; +} + class IOutputParser; -class Project; +class ToolChainConfigWidget; +class ToolChainFactory; + +// -------------------------------------------------------------------------- +// HeaderPath +// -------------------------------------------------------------------------- class PROJECTEXPLORER_EXPORT HeaderPath { @@ -58,191 +72,103 @@ public: }; HeaderPath() - : _kind(GlobalHeaderPath) + : m_kind(GlobalHeaderPath) { } HeaderPath(const QString &path, Kind kind) - : _path(path), _kind(kind) + : m_path(path), m_kind(kind) { } - QString path() const { return _path; } - Kind kind() const { return _kind; } + QString path() const { return m_path; } + Kind kind() const { return m_kind; } private: - QString _path; - Kind _kind; + QString m_path; + Kind m_kind; }; - +// -------------------------------------------------------------------------- +// ToolChain +// -------------------------------------------------------------------------- class PROJECTEXPLORER_EXPORT ToolChain { public: - virtual QByteArray predefinedMacros() = 0; - virtual QList<HeaderPath> systemHeaderPaths() = 0; - virtual void addToEnvironment(Utils::Environment &env) = 0; - virtual ToolChainType type() const = 0; - virtual QString makeCommand() const = 0; - virtual IOutputParser *outputParser() const = 0; - virtual QString sysroot() const { return QString(); } - - ToolChain(); virtual ~ToolChain(); - static bool equals(const ToolChain *, const ToolChain *); - // Factory methods - static ToolChain *createGccToolChain(const QString &gcc); - static ToolChain *createMinGWToolChain(const QString &gcc, const QString &mingwPath); - static ToolChain *createLinuxIccToolChain(); - static ToolChain *createMSVCToolChain(const QString &name, bool amd64); - static ToolChain *createWinCEToolChain(const QString &name, const QString &platform); - static QStringList availableMSVCVersions(); - static QStringList availableMSVCVersions(bool amd64); // filter 32/64bit apart - static QList<ToolChainType> supportedToolChains(); - - static QString toolChainName(ToolChainType tc); + QString displayName() const; + void setDisplayName(const QString &name) const; -protected: - virtual bool equals(const ToolChain *other) const = 0; -}; - -class PROJECTEXPLORER_EXPORT GccToolChain : public ToolChain -{ -public: - GccToolChain(const QString &gcc); - virtual QByteArray predefinedMacros(); - virtual QList<HeaderPath> systemHeaderPaths(); - virtual void addToEnvironment(Utils::Environment &env); - virtual ToolChainType type() const; - virtual QString makeCommand() const; - virtual IOutputParser *outputParser() const; + bool isAutoDetected() const; + QString id() const; -protected: - virtual bool equals(const ToolChain *other) const; - QByteArray m_predefinedMacros; - QList<HeaderPath> m_systemHeaderPaths; - QString gcc() const { return m_gcc; } + virtual QString typeName() const = 0; + virtual Abi targetAbi() const = 0; -private: - QString m_gcc; -}; - -// TODO this class needs to fleshed out more -class PROJECTEXPLORER_EXPORT MinGWToolChain : public GccToolChain -{ -public: - MinGWToolChain(const QString &gcc, const QString &mingwPath); - virtual void addToEnvironment(Utils::Environment &env); - virtual ToolChainType type() const; - virtual QString makeCommand() const; - virtual IOutputParser *outputParser() const; + virtual bool isValid() const = 0; -protected: - virtual bool equals(const ToolChain *other) const; + /// Returns a list of target ids that this ToolChain is restricted to. + /// An empty list is shows that the toolchain is compatible with all targets. + virtual QStringList restrictedToTargets() const; -private: - QString m_mingwPath; -}; + virtual QByteArray predefinedMacros() const = 0; + virtual QList<HeaderPath> systemHeaderPaths() const = 0; + virtual void addToEnvironment(Utils::Environment &env) const = 0; + virtual QString makeCommand() const = 0; + virtual QString defaultMakeTarget() const; + virtual IOutputParser *outputParser() const = 0; -class PROJECTEXPLORER_EXPORT LinuxIccToolChain : public GccToolChain -{ -public: - LinuxIccToolChain(); - virtual ToolChainType type() const; + virtual bool operator ==(const ToolChain &) const; - virtual IOutputParser *outputParser() const; -}; + virtual ToolChainConfigWidget *configurationWidget() = 0; + virtual bool canClone() const; + virtual ToolChain *clone() const = 0; -// TODO some stuff needs to be moved into this -class PROJECTEXPLORER_EXPORT MSVCToolChain : public ToolChain -{ - Q_DISABLE_COPY(MSVCToolChain) -public: - // A MSVC installation (SDK or VS) with name and setup script with args - struct Installation { - enum Type { WindowsSDK, VS }; - enum Platform { s32, s64, ia64, amd64 }; - - explicit Installation(Type t, const QString &name, Platform p, - const QString &varsBat, - const QString &varBatArg = QString()); - Installation(); - static QString platformName(Platform t); - bool is64bit() const; - - Type type; - QString name; - Platform platform; - QString varsBat; // Script to setup environment - QString varsBatArg; // Argument - }; - // Find all installations - typedef QList<Installation> InstallationList; - static InstallationList installations(); - // Return matching installation or empty one - static Installation findInstallationByName(bool is64Bit, - const QString &name = QString(), - bool excludeSDK = false); - static Installation findInstallationByMkSpec(bool is64Bit, - const QString &mkSpec, - bool excludeSDK = false); - - static MSVCToolChain *create(const QString &name, - bool amd64 = false); - virtual QByteArray predefinedMacros(); - virtual QList<HeaderPath> systemHeaderPaths(); - virtual void addToEnvironment(Utils::Environment &env); - virtual ToolChainType type() const; - virtual QString makeCommand() const; - virtual IOutputParser *outputParser() const; + // Used by the toolchainmanager to save user-generated ToolChains. + // Make sure to call this method when deriving! + virtual QVariantMap toMap() const; protected: - explicit MSVCToolChain(const Installation &in); - - typedef QPair<QString, QString> StringStringPair; - typedef QList<StringStringPair> StringStringPairList; + ToolChain(const QString &id, bool autoDetect); + explicit ToolChain(const ToolChain &); - virtual bool equals(const ToolChain *other) const; - static StringStringPairList readEnvironmentSetting(const QString &varsBat, - const QStringList &args, - const Utils::Environment &env); + void setId(const QString &id); - QByteArray m_predefinedMacros; - const Installation m_installation; + // Make sure to call this method when deriving! + virtual bool fromMap(const QVariantMap &data); private: - static StringStringPairList readEnvironmentSettingI(const QString &varsBat, - const QStringList &args, - const Utils::Environment &env); + Internal::ToolChainPrivate *const m_d; - mutable StringStringPairList m_values; - mutable bool m_valuesSet; - mutable Utils::Environment m_lastEnvironment; + friend class ToolChainFactory; }; -PROJECTEXPLORER_EXPORT QDebug operator<<(QDebug in, const MSVCToolChain::Installation &i); +// -------------------------------------------------------------------------- +// ToolChainFactory +// -------------------------------------------------------------------------- -// TODO some stuff needs to be moved into here -class PROJECTEXPLORER_EXPORT WinCEToolChain : public MSVCToolChain +class PROJECTEXPLORER_EXPORT ToolChainFactory : public QObject { + Q_OBJECT + public: - static WinCEToolChain *create(const QString &name, const QString &platform); + // Name used to display the name of the toolchain that will be created. + virtual QString displayName() const = 0; + virtual QString id() const = 0; - virtual QByteArray predefinedMacros(); - virtual QList<HeaderPath> systemHeaderPaths(); - virtual void addToEnvironment(Utils::Environment &env); - virtual ToolChainType type() const; + virtual QList<ToolChain *> autoDetect(); -protected: - explicit WinCEToolChain(const Installation &in, const QString &platform); - virtual bool equals(const ToolChain *other) const; + virtual bool canCreate(); + virtual ToolChain *create(); -private: - const QString m_platform; -}; + // Used by the ToolChainManager to restore user-generated ToolChains + virtual bool canRestore(const QVariantMap &data); + virtual ToolChain *restore(const QVariantMap &data); -} +protected: + static QString idFromMap(const QVariantMap &data); +}; -Q_DECLARE_METATYPE(ProjectExplorer::ToolChainType) +} // namespace ProjectExplorer #endif // TOOLCHAIN_H diff --git a/src/plugins/projectexplorer/toolchainconfigwidget.cpp b/src/plugins/projectexplorer/toolchainconfigwidget.cpp new file mode 100644 index 0000000000..3bb6240655 --- /dev/null +++ b/src/plugins/projectexplorer/toolchainconfigwidget.cpp @@ -0,0 +1,77 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** No Commercial Usage +** +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +**************************************************************************/ + +#include "toolchainconfigwidget.h" + +#include "toolchain.h" + +namespace ProjectExplorer { +namespace Internal { + +// -------------------------------------------------------------------------- +// ToolChainConfigWidgetPrivate +// -------------------------------------------------------------------------- + +class ToolChainConfigWidgetPrivate +{ +public: + ToolChainConfigWidgetPrivate(ToolChain *tc) : + m_toolChain(tc) + { + Q_ASSERT(tc); + } + + ToolChain *m_toolChain; +}; + +} // namespace Internal + +// -------------------------------------------------------------------------- +// ToolChainConfigWidget +// -------------------------------------------------------------------------- + +ToolChainConfigWidget::ToolChainConfigWidget(ToolChain *tc) : + m_d(new Internal::ToolChainConfigWidgetPrivate(tc)) +{ } + +void ToolChainConfigWidget::setDisplayName(const QString &name) +{ + m_d->m_toolChain->setDisplayName(name); +} + +ToolChain *ToolChainConfigWidget::toolChain() const +{ + return m_d->m_toolChain; +} + +} // namespace ProjectExplorer diff --git a/src/plugins/projectexplorer/toolchaintype.h b/src/plugins/projectexplorer/toolchainconfigwidget.h index 353c4d0e8a..8f7a7238e4 100644 --- a/src/plugins/projectexplorer/toolchaintype.h +++ b/src/plugins/projectexplorer/toolchainconfigwidget.h @@ -31,35 +31,47 @@ ** **************************************************************************/ -#ifndef TOOLCHAINTYPE_H -#define TOOLCHAINTYPE_H +#ifndef TOOLCHAINCONFIGWIDGET_H +#define TOOLCHAINCONFIGWIDGET_H + +#include "projectexplorer_export.h" + +#include <QtGui/QWidget> namespace ProjectExplorer { -enum ToolChainType +namespace Internal { +class ToolChainConfigWidgetPrivate; +} // namespace Internal + +class ToolChain; + +// -------------------------------------------------------------------------- +// ToolChainConfigWidget +// -------------------------------------------------------------------------- + +class PROJECTEXPLORER_EXPORT ToolChainConfigWidget : public QWidget { - ToolChain_GCC = 0, - ToolChain_LINUX_ICC = 1, - ToolChain_MinGW = 2, - ToolChain_MSVC = 3, - ToolChain_WINCE = 4, - ToolChain_WINSCW = 5, - ToolChain_GCCE = 6, - ToolChain_RVCT2_ARMV5 = 7, - ToolChain_RVCT2_ARMV6 = 8, - ToolChain_GCC_MAEMO5 = 9, - ToolChain_GCCE_GNUPOC = 10, - ToolChain_RVCT_ARMV5_GNUPOC = 11, - ToolChain_RVCT4_ARMV5 = 12, - ToolChain_RVCT4_ARMV6 = 13, - ToolChain_GCC_HARMATTAN = 14, - ToolChain_GCC_MEEGO = 15, - ToolChain_LAST_VALID = 15, - ToolChain_OTHER = 200, - ToolChain_UNKNOWN = 201, - ToolChain_INVALID = 202 + Q_OBJECT + +public: + ToolChainConfigWidget(ProjectExplorer::ToolChain *); + + void setDisplayName(const QString &); + virtual void apply() = 0; + virtual void discard() = 0; + + ProjectExplorer::ToolChain *toolChain() const; + + virtual bool isDirty() const = 0; + +signals: + void dirty(ProjectExplorer::ToolChain *); + +private: + Internal::ToolChainConfigWidgetPrivate *m_d; }; } // namespace ProjectExplorer -#endif // TOOLCHAINTYPE_H +#endif // TOOLCHAINCONFIGWIDGET_H diff --git a/src/plugins/projectexplorer/toolchainmanager.cpp b/src/plugins/projectexplorer/toolchainmanager.cpp new file mode 100644 index 0000000000..7e091ed3da --- /dev/null +++ b/src/plugins/projectexplorer/toolchainmanager.cpp @@ -0,0 +1,191 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** No Commercial Usage +** +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +**************************************************************************/ + +#include "toolchainmanager.h" + +#include "toolchain.h" + +#include <extensionsystem/pluginmanager.h> + +#include <QtCore/QCoreApplication> +#include <QtCore/QSettings> + + +static const char *const ORGANIZATION_NAME = "Nokia"; +static const char *const APPLICATION_NAME = "toolChains"; +static const char *const ARRAY_NAME = "ToolChain"; +static const char *const TOOLCHAIN_DATA_KEY = "Data"; + +namespace ProjectExplorer { + +ToolChainManager *ToolChainManager::m_instance = 0; + +namespace Internal { + +// -------------------------------------------------------------------------- +// ToolChainManagerPrivate +// -------------------------------------------------------------------------- + +class ToolChainManagerPrivate +{ +public: + QList<ToolChain *> m_toolChains; +}; + +} // namespace Internal + +// -------------------------------------------------------------------------- +// ToolChainManager +// -------------------------------------------------------------------------- + +ToolChainManager *ToolChainManager::instance() +{ + Q_ASSERT(m_instance); + return m_instance; +} + +ToolChainManager::ToolChainManager(QObject *parent) : + QObject(parent), + m_d(new Internal::ToolChainManagerPrivate) +{ + Q_ASSERT(!m_instance); + m_instance = this; +} + +void ToolChainManager::restoreToolChains() +{ + QList<ToolChainFactory *> factories = + ExtensionSystem::PluginManager::instance()->getObjects<ToolChainFactory>(); + // Autodetect ToolChains: + foreach (ToolChainFactory *f, factories) { + QList<ToolChain *> tcs = f->autoDetect(); + foreach (ToolChain *tc, tcs) + registerToolChain(tc); + } + + // Restore user generated ToolChains: + QSettings settings(QSettings::IniFormat, QSettings::UserScope, + ORGANIZATION_NAME, APPLICATION_NAME); + int size = settings.beginReadArray(QLatin1String(ARRAY_NAME)); + if (size <= 0) + return; + + for (int i = 0; i < size; ++i) { + settings.setArrayIndex(i); + QVariantMap tmp = settings.value(QLatin1String(TOOLCHAIN_DATA_KEY)).toMap(); + foreach (ToolChainFactory *f, factories) { + if (!f->canRestore(tmp)) + continue; + ToolChain *tc = f->restore(tmp); + if (!tc) + continue; + registerToolChain(tc); + } + } +} + +ToolChainManager::~ToolChainManager() +{ + QSettings settings(QSettings::IniFormat, QSettings::UserScope, + ORGANIZATION_NAME, APPLICATION_NAME); + settings.beginWriteArray(QLatin1String(ARRAY_NAME)); + int count = 0; + foreach (ToolChain *tc, m_d->m_toolChains) { + if (!tc->isAutoDetected() && tc->isValid()) { + settings.setArrayIndex(count); + ++count; + + QVariantMap tmp = tc->toMap(); + if (tmp.isEmpty()) + continue; + settings.setValue(QLatin1String(TOOLCHAIN_DATA_KEY), tmp); + } + } + settings.endArray(); + + QList<ToolChain *> copy = m_d->m_toolChains; + foreach (ToolChain *tc, copy) + deregisterToolChain(tc); + + delete m_d; + m_instance = 0; +} + +QList<ToolChain *> ToolChainManager::toolChains() const +{ + return m_d->m_toolChains; +} + +QList<ToolChain *> ToolChainManager::findToolChains(const Abi &abi) const +{ + QList<ToolChain *> result; + foreach (ToolChain *tc, m_d->m_toolChains) { + Abi targetAbi = tc->targetAbi(); + if (targetAbi.isCompatibleWith(abi)) + result.append(tc); + } + return result; +} + +ToolChain *ToolChainManager::findToolChain(const QString &id) const +{ + foreach (ToolChain *tc, m_d->m_toolChains) { + if (tc->id() == id) + return tc; + } + return 0; +} + +void ToolChainManager::registerToolChain(ToolChain *tc) +{ + if (!tc || m_d->m_toolChains.contains(tc)) + return; + foreach (ToolChain *current, m_d->m_toolChains) { + if (*tc == *current) + return; + } + + m_d->m_toolChains.append(tc); + emit toolChainAdded(tc); +} + +void ToolChainManager::deregisterToolChain(ToolChain *tc) +{ + if (!tc || !m_d->m_toolChains.contains(tc)) + return; + m_d->m_toolChains.removeOne(tc); + emit toolChainRemoved(tc); + delete tc; +} + +} // namespace ProjectExplorer diff --git a/src/plugins/projectexplorer/toolchainmanager.h b/src/plugins/projectexplorer/toolchainmanager.h new file mode 100644 index 0000000000..c8ed740549 --- /dev/null +++ b/src/plugins/projectexplorer/toolchainmanager.h @@ -0,0 +1,96 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** No Commercial Usage +** +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +**************************************************************************/ + +#ifndef TOOLCHAINMANAGER_H +#define TOOLCHAINMANAGER_H + +#include "projectexplorer_export.h" + +#include "abi.h" +#include "toolchain.h" + +#include <QtCore/QList> +#include <QtCore/QObject> +#include <QtCore/QString> + +namespace ProjectExplorer { +class ProjectExplorerPlugin; +class ToolChain; +class ToolChainFactory; + +namespace Internal { +class ToolChainManagerPrivate; +} + +// -------------------------------------------------------------------------- +// ToolChainManager +// -------------------------------------------------------------------------- + +class PROJECTEXPLORER_EXPORT ToolChainManager : public QObject +{ + Q_OBJECT + +public: + static ToolChainManager *instance(); + ~ToolChainManager(); + + QList<ToolChain *> toolChains() const; + QList<ToolChain *> findToolChains(const Abi &abi) const; + ToolChain *findToolChain(const QString &id) const; + +public slots: + void registerToolChain(ProjectExplorer::ToolChain *tc); + void deregisterToolChain(ProjectExplorer::ToolChain *tc); + +signals: + void toolChainAdded(ProjectExplorer::ToolChain *); + // ToolChain is still valid when this call happens! + void toolChainRemoved(ProjectExplorer::ToolChain *); + +private: + explicit ToolChainManager(QObject *parent = 0); + + // Make sure the ToolChain Manager is only created after all + // ToolChain Factories are registered! + void restoreToolChains(); + + Internal::ToolChainManagerPrivate *const m_d; + + static ToolChainManager *m_instance; + + friend class ProjectExplorerPlugin; +}; + +} // namespace ProjectExplorer + +#endif // TOOLCHAINMANAGER_H diff --git a/src/plugins/projectexplorer/toolchainoptionspage.cpp b/src/plugins/projectexplorer/toolchainoptionspage.cpp new file mode 100644 index 0000000000..e3665c39d1 --- /dev/null +++ b/src/plugins/projectexplorer/toolchainoptionspage.cpp @@ -0,0 +1,608 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** No Commercial Usage +** +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +**************************************************************************/ + +#include "toolchainoptionspage.h" + +#include "projectexplorerconstants.h" +#include "toolchainconfigwidget.h" +#include "toolchainmanager.h" + +#include <coreplugin/icore.h> +#include <extensionsystem/pluginmanager.h> + +#include <QtCore/QSignalMapper> +#include <QtCore/QTextStream> +#include <QtGui/QAction> +#include <QtGui/QItemSelectionModel> +#include <QtGui/QLabel> +#include <QtGui/QMenu> +#include <QtGui/QMessageBox> + +namespace ProjectExplorer { +namespace Internal { + +class ToolChainNode +{ +public: + explicit ToolChainNode(ToolChainNode *p, ToolChain *tc = 0, bool c = false) : + parent(p), toolChain(tc), changed(c) + { + if (p) + p->childNodes.append(this); + widget = tc ? tc->configurationWidget() : 0; + if (widget) { + widget->setEnabled(tc ? !tc->isAutoDetected() : false); + widget->setVisible(false); + } + } + + ~ToolChainNode() + { + qDeleteAll(childNodes); + // Do not delete toolchain, we do not own it. + delete widget; + } + + ToolChainNode *parent; + QString newName; + QList<ToolChainNode *> childNodes; + ToolChain *toolChain; + ToolChainConfigWidget *widget; + bool changed; +}; + +// -------------------------------------------------------------------------- +// ToolChainModel +// -------------------------------------------------------------------------- + +ToolChainModel::ToolChainModel(QObject *parent) : + QAbstractItemModel(parent) +{ + connect(ToolChainManager::instance(), SIGNAL(toolChainAdded(ProjectExplorer::ToolChain*)), + this, SLOT(addToolChain(ProjectExplorer::ToolChain*))); + connect(ToolChainManager::instance(), SIGNAL(toolChainRemoved(ProjectExplorer::ToolChain*)), + this, SLOT(removeToolChain(ProjectExplorer::ToolChain*))); + + m_autoRoot = new ToolChainNode(0); + m_manualRoot = new ToolChainNode(0); + + foreach (ToolChain *tc, ToolChainManager::instance()->toolChains()) { + if (tc->isAutoDetected()) + new ToolChainNode(m_autoRoot, tc); + else { + ToolChainNode *node = new ToolChainNode(m_manualRoot, tc); + if (node->widget) + connect(node->widget, SIGNAL(dirty(ProjectExplorer::ToolChain*)), + this, SLOT(setDirty(ProjectExplorer::ToolChain*))); + } + } +} + +ToolChainModel::~ToolChainModel() +{ + delete m_autoRoot; + delete m_manualRoot; +} + +QModelIndex ToolChainModel::index(int row, int column, const QModelIndex &parent) const +{ + if (!parent.isValid()) { + if (row == 0) + return createIndex(0, 0, static_cast<void *>(m_autoRoot)); + else + return createIndex(1, 0, static_cast<void *>(m_manualRoot)); + } + ToolChainNode *node = static_cast<ToolChainNode *>(parent.internalPointer()); + if (row < node->childNodes.count() && column < 2) + return createIndex(row, column, static_cast<void *>(node->childNodes.at(row))); + else + return QModelIndex(); +} + +QModelIndex ToolChainModel::parent(const QModelIndex &idx) const +{ + ToolChainNode *node = static_cast<ToolChainNode *>(idx.internalPointer()); + if (node->parent == 0) + return QModelIndex(); + return index(node->parent); +} + +int ToolChainModel::rowCount(const QModelIndex &parent) const +{ + if (!parent.isValid()) + return 2; + ToolChainNode *node = static_cast<ToolChainNode *>(parent.internalPointer()); + return node->childNodes.count(); +} + +int ToolChainModel::columnCount(const QModelIndex &parent) const +{ + Q_UNUSED(parent); + return 2; +} + +QVariant ToolChainModel::data(const QModelIndex &index, int role) const +{ + if (!index.isValid()) + return QVariant(); + + ToolChainNode *node = static_cast<ToolChainNode *>(index.internalPointer()); + Q_ASSERT(node); + if (node == m_autoRoot && index.column() == 0 && role == Qt::DisplayRole) + return tr("Auto-detected"); + if (node == m_manualRoot && index.column() == 0 && role == Qt::DisplayRole) + return tr("Manual"); + if (node->toolChain) { + if (role == Qt::FontRole) { + QFont f = QApplication::font(); + if (node->changed) { + f.setBold(true); + } + return f; + } + if (role == Qt::DisplayRole || role == Qt::EditRole) { + if (index.column() == 0) { + return node->newName.isEmpty() ? + node->toolChain->displayName() : node->newName; + } + return node->toolChain->typeName(); + } + if (role == Qt::ToolTipRole) { + return tr("<nobr><b>ABI:</b> %1") + .arg(node->changed ? tr("not up-to-date") : node->toolChain->targetAbi().toString()); + } + } + return QVariant(); +} + +bool ToolChainModel::setData(const QModelIndex &index, const QVariant &value, int role) +{ + if (!index.isValid()) + return false; + + ToolChainNode *node = static_cast<ToolChainNode *>(index.internalPointer()); + Q_ASSERT(node); + if (index.column() != 0 || !node->toolChain || role != Qt::EditRole) + return false; + node->newName = value.toString(); + if (!node->newName.isEmpty() && node->newName != node->toolChain->displayName()) + node->changed = true; + return true; +} + +Qt::ItemFlags ToolChainModel::flags(const QModelIndex &index) const +{ + if (!index.isValid()) + return 0; + + ToolChainNode *node = static_cast<ToolChainNode *>(index.internalPointer()); + Q_ASSERT(node); + if (!node->toolChain) + return Qt::ItemIsEnabled; + + if (node->toolChain->isAutoDetected()) + return Qt::ItemIsEnabled | Qt::ItemIsSelectable; + else if (index.column() == 0) + return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsEditable; + else + return Qt::ItemIsEnabled | Qt::ItemIsSelectable; +} + +QVariant ToolChainModel::headerData(int section, Qt::Orientation orientation, int role) const +{ + if (orientation == Qt::Horizontal && role == Qt::DisplayRole) + return section == 0 ? tr("Name") : tr("Type"); + return QVariant(); +} + +ToolChain *ToolChainModel::toolChain(const QModelIndex &index) +{ + if (!index.isValid()) + return 0; + ToolChainNode *node = static_cast<ToolChainNode *>(index.internalPointer()); + Q_ASSERT(node); + return node->toolChain; +} + +int ToolChainModel::manualToolChains() const +{ + return m_manualRoot->childNodes.count(); +} + +ToolChainConfigWidget *ToolChainModel::widget(const QModelIndex &index) +{ + if (!index.isValid()) + return 0; + ToolChainNode *node = static_cast<ToolChainNode *>(index.internalPointer()); + Q_ASSERT(node); + return node->widget; +} + +bool ToolChainModel::isDirty() const +{ + foreach (ToolChainNode *n, m_manualRoot->childNodes) { + if (n->changed) + return true; + } + return false; +} + +bool ToolChainModel::isDirty(ToolChain *tc) const +{ + foreach (ToolChainNode *n, m_manualRoot->childNodes) { + if (n->toolChain == tc && n->changed) + return true; + } + return false; +} + +void ToolChainModel::setDirty(ToolChain *tc) +{ + foreach (ToolChainNode *n, m_manualRoot->childNodes) { + if (n->toolChain == tc) { + n->changed = true; + emit dataChanged(index(n, 0), index(n, columnCount(QModelIndex()))); + } + } +} + +void ToolChainModel::apply() +{ + // Remove unused ToolChains: + QList<ToolChainNode *> nodes = m_toRemoveList; + foreach (ToolChainNode *n, nodes) { + ToolChainManager::instance()->deregisterToolChain(n->toolChain); + } + Q_ASSERT(m_toRemoveList.isEmpty()); + + // Update toolchains: + foreach (ToolChainNode *n, m_manualRoot->childNodes) { + Q_ASSERT(n); + if (n->changed) { + Q_ASSERT(n->toolChain); + if (!n->newName.isEmpty()) + n->toolChain->setDisplayName(n->newName); + if (n->widget) + n->widget->apply(); + n->changed = false; + + emit dataChanged(index(n, 0), index(n, columnCount(QModelIndex()))); + } + } + + // Add new (and already updated) toolchains + nodes = m_toAddList; + foreach (ToolChainNode *n, nodes) { + ToolChainManager::instance()->registerToolChain(n->toolChain); + } + Q_ASSERT(m_toAddList.isEmpty()); +} + +void ToolChainModel::discard() +{ + // Remove newly "added" toolchains: + foreach (ToolChainNode *n, m_toAddList) { + int pos = m_manualRoot->childNodes.indexOf(n); + Q_ASSERT(pos >= 0); + m_manualRoot->childNodes.removeAt(pos); + + // Clean up Node: We still own the toolchain! + delete n->toolChain; + n->toolChain = 0; + } + qDeleteAll(m_toAddList); + m_toAddList.clear(); + + // Add "removed" toolchains again: + foreach (ToolChainNode *n, m_toRemoveList) { + m_manualRoot->childNodes.append(n); + } + m_toRemoveList.clear(); + + // Reset toolchains: + foreach (ToolChainNode *n, m_manualRoot->childNodes) { + Q_ASSERT(n); + n->newName.clear(); + if (n->widget) + n->widget->discard(); + n->changed = false; + } +} + +void ToolChainModel::markForRemoval(ToolChain *tc) +{ + ToolChainNode *node = 0; + foreach (ToolChainNode *n, m_manualRoot->childNodes) { + if (n->toolChain == tc) { + node = n; + break; + } + } + if (node) { + m_toRemoveList.append(node); + emit beginRemoveRows(index(m_manualRoot), m_manualRoot->childNodes.indexOf(node), m_manualRoot->childNodes.indexOf(node)); + m_manualRoot->childNodes.removeOne(node); + emit endRemoveRows(); + } +} + +void ToolChainModel::markForAddition(ToolChain *tc) +{ + int pos = m_manualRoot->childNodes.size(); + emit beginInsertRows(index(m_manualRoot), pos, pos); + + ToolChainNode *node = new ToolChainNode(m_manualRoot, tc); + node->changed = true; + m_toAddList.append(node); + + emit endInsertRows(); +} + +QModelIndex ToolChainModel::index(ToolChainNode *node, int column) const +{ + if (!node->parent) + return index(node == m_autoRoot ? 0 : 1, column, QModelIndex()); + else + return index(node->parent->childNodes.indexOf(node), column, index(node->parent)); +} + +void ToolChainModel::addToolChain(ToolChain *tc) +{ + QList<ToolChainNode *> nodes = m_toAddList; + foreach (ToolChainNode *n, nodes) { + if (n->toolChain == tc) { + m_toAddList.removeOne(n); + // do not delete n: Still used elsewhere! + return; + } + } + + ToolChainNode *parent = m_manualRoot; + if (tc->isAutoDetected()) + parent = m_autoRoot; + int row = parent->childNodes.count(); + + beginInsertRows(index(parent), row, row); + new ToolChainNode(parent, tc, true); + endInsertRows(); + + emit toolChainStateChanged(); +} + +void ToolChainModel::removeToolChain(ToolChain *tc) +{ + QList<ToolChainNode *> nodes = m_toRemoveList; + foreach (ToolChainNode *n, nodes) { + if (n->toolChain == tc) { + m_toRemoveList.removeOne(n); + delete n; + return; + } + } + + ToolChainNode *parent = m_manualRoot; + if (tc->isAutoDetected()) + parent = m_autoRoot; + int row = 0; + ToolChainNode *node = 0; + foreach (ToolChainNode *current, parent->childNodes) { + if (current->toolChain == tc) { + node = current; + break; + } + ++row; + } + + beginRemoveRows(index(parent), row, row); + parent->childNodes.removeAt(row); + delete node; + endRemoveRows(); + + emit toolChainStateChanged(); +} + +// -------------------------------------------------------------------------- +// ToolChainOptionsPage +// -------------------------------------------------------------------------- + +ToolChainOptionsPage::ToolChainOptionsPage() : + m_ui(0), m_cloneAction(0), m_model(0), m_selectionModel(0), m_currentTcWidget(0) +{ } + +QString ToolChainOptionsPage::id() const +{ + return QLatin1String(Constants::TOOLCHAIN_SETTINGS_PAGE_ID); +} + +QString ToolChainOptionsPage::displayName() const +{ + return tr("Toolchains"); +} + +QString ToolChainOptionsPage::category() const +{ + return QLatin1String(Constants::TOOLCHAIN_SETTINGS_CATEGORY); +} + +QString ToolChainOptionsPage::displayCategory() const +{ + return tr("Toolchains"); +} + +QIcon ToolChainOptionsPage::categoryIcon() const +{ + return QIcon(QLatin1String(Constants::ICON_TOOLCHAIN_SETTINGS_CATEGORY)); +} + +QWidget *ToolChainOptionsPage::createPage(QWidget *parent) +{ + // Actual page setup: + m_configWidget = new QWidget(parent); + + m_currentTcWidget = 0; + + m_ui = new Ui::ToolChainOptionsPage; + m_ui->setupUi(m_configWidget); + + m_model = new ToolChainModel(m_ui->toolChainView); + connect(m_model, SIGNAL(toolChainStateChanged()), this, SLOT(updateState())); + + m_ui->toolChainView->setModel(m_model); + m_ui->toolChainView->header()->setResizeMode(0, QHeaderView::ResizeToContents); + m_ui->toolChainView->header()->setResizeMode(1, QHeaderView::ResizeToContents); + m_ui->toolChainView->expandAll(); + + m_selectionModel = m_ui->toolChainView->selectionModel(); + connect(m_selectionModel, SIGNAL(currentChanged(QModelIndex,QModelIndex)), + this, SLOT(toolChainSelectionChanged(QModelIndex,QModelIndex))); + + // Get toolchainfactories: + m_factories = ExtensionSystem::PluginManager::instance()->getObjects<ToolChainFactory>(); + + // Set up add menu: + QMenu *addMenu = new QMenu(m_ui->addButton); + QSignalMapper *mapper = new QSignalMapper(addMenu); + connect(mapper, SIGNAL(mapped(QObject*)), this, SLOT(createToolChain(QObject*))); + + foreach (ToolChainFactory *factory, m_factories) { + if (factory->canCreate()) { + QAction *action = new QAction(addMenu); + action->setText(factory->displayName()); + connect(action, SIGNAL(triggered()), mapper, SLOT(map())); + mapper->setMapping(action, static_cast<QObject *>(factory)); + + addMenu->addAction(action); + } + } + m_cloneAction = new QAction(addMenu); + m_cloneAction->setText(tr("Clone ...")); + connect(m_cloneAction, SIGNAL(triggered()), mapper, SLOT(map())); + mapper->setMapping(m_cloneAction, static_cast<QObject *>(0)); + + if (!addMenu->isEmpty()) + addMenu->addSeparator(); + addMenu->addAction(m_cloneAction); + m_ui->addButton->setMenu(addMenu); + + connect(m_ui->delButton, SIGNAL(clicked()), this, SLOT(removeToolChain())); + + // setup keywords: + if (m_searchKeywords.isEmpty()) { + QLatin1Char sep(' '); + QTextStream stream(&m_searchKeywords); + stream << tr("Toolchains"); + foreach (ToolChainFactory *f, m_factories) + stream << sep << f->displayName(); + + m_searchKeywords.remove(QLatin1Char('&')); + } + + return m_configWidget; +} + +void ToolChainOptionsPage::apply() +{ + m_model->apply(); +} + +void ToolChainOptionsPage::finish() +{ + m_model->discard(); +} + +bool ToolChainOptionsPage::matches(const QString &s) const +{ + return m_searchKeywords.contains(s, Qt::CaseInsensitive); +} + +void ToolChainOptionsPage::toolChainSelectionChanged(const QModelIndex ¤t, + const QModelIndex &previous) +{ + Q_UNUSED(previous); + if (m_currentTcWidget) { + m_configWidget->layout()->removeWidget(m_currentTcWidget); + m_currentTcWidget->setVisible(false); + } + + m_currentTcWidget = m_model->widget(current); + + if (m_currentTcWidget) { + m_configWidget->layout()->addWidget(m_currentTcWidget); + m_currentTcWidget->setVisible(true); + } + + updateState(); +} + +void ToolChainOptionsPage::createToolChain(QObject *factoryObject) +{ + ToolChain *tc = 0; + + ToolChainFactory *factory = static_cast<ToolChainFactory *>(factoryObject); + if (!factory) { + // Copy current item! + ToolChain *oldTc = m_model->toolChain(m_selectionModel->currentIndex()); + Q_ASSERT(oldTc); + tc = oldTc->clone(); + } else { + Q_ASSERT(factory->canCreate()); + tc = factory->create(); + } if (!tc) + return; + m_model->markForAddition(tc); +} + +void ToolChainOptionsPage::removeToolChain() +{ + ToolChain *tc = m_model->toolChain(m_selectionModel->currentIndex()); + Q_ASSERT(tc && !tc->isAutoDetected()); + m_model->markForRemoval(tc); +} + +void ToolChainOptionsPage::updateState() +{ + + bool canCopy = false; + bool canDelete = false; + ToolChain *tc = m_model->toolChain(m_selectionModel->currentIndex()); + if (tc) { + canCopy = tc->isValid() && tc->canClone(); + canDelete = !tc->isAutoDetected(); + } + + m_cloneAction->setEnabled(canCopy); + m_ui->delButton->setEnabled(canDelete); +} + +} // namespace Internal +} // namespace ProjectExplorer diff --git a/src/plugins/projectexplorer/toolchainoptionspage.h b/src/plugins/projectexplorer/toolchainoptionspage.h new file mode 100644 index 0000000000..ad620addd7 --- /dev/null +++ b/src/plugins/projectexplorer/toolchainoptionspage.h @@ -0,0 +1,155 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** No Commercial Usage +** +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +**************************************************************************/ + +#ifndef TOOLCHAINOPTIONSPAGE_H +#define TOOLCHAINOPTIONSPAGE_H + +#include "ui_toolchainoptionspage.h" + +#include <coreplugin/dialogs/ioptionspage.h> + +#include <QtCore/QAbstractItemModel> + +QT_BEGIN_NAMESPACE +class QTreeWidgetItem; +QT_END_NAMESPACE + +namespace ProjectExplorer { + +class ToolChain; +class ToolChainConfigWidget; +class ToolChainFactory; +class ToolChainManager; + +namespace Internal { + +class ToolChainNode; +// -------------------------------------------------------------------------- +// ToolChainModel +// -------------------------------------------------------------------------- + +class ToolChainModel : public QAbstractItemModel +{ + Q_OBJECT + +public: + explicit ToolChainModel(QObject *parent = 0); + ~ToolChainModel(); + + QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const; + QModelIndex parent(const QModelIndex &index) const; + int rowCount(const QModelIndex &parent = QModelIndex()) const; + int columnCount(const QModelIndex &parent = QModelIndex()) const; + + QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; + bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole); + Qt::ItemFlags flags(const QModelIndex &index) const; + QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; + + ToolChain *toolChain(const QModelIndex &); + int manualToolChains() const; + + ToolChainConfigWidget *widget(const QModelIndex &); + + bool isDirty() const; + bool isDirty(ToolChain *) const; + + void apply(); + void discard(); + + void markForRemoval(ToolChain *); + void markForAddition(ToolChain *); + +signals: + void toolChainStateChanged(); + +private slots: + void addToolChain(ProjectExplorer::ToolChain *); + void removeToolChain(ProjectExplorer::ToolChain *); + void setDirty(ProjectExplorer::ToolChain *); + +private: + QModelIndex index(ToolChainNode *, int column = 0) const; + + ToolChainNode * m_root; + ToolChainNode * m_autoRoot; + ToolChainNode * m_manualRoot; + + QList<ToolChainNode *> m_toAddList; + QList<ToolChainNode *> m_toRemoveList; +}; + +// -------------------------------------------------------------------------- +// ToolChainOptionsPage +// -------------------------------------------------------------------------- + +class ToolChainOptionsPage : public Core::IOptionsPage +{ + Q_OBJECT + +public: + ToolChainOptionsPage(); + + virtual QString id() const; + virtual QString displayName() const; + virtual QString category() const; + virtual QString displayCategory() const; + virtual QIcon categoryIcon() const; + + virtual QWidget *createPage(QWidget *parent); + virtual void apply(); + virtual void finish(); + virtual bool matches(const QString &) const; + +private slots: + void toolChainSelectionChanged(const QModelIndex &, const QModelIndex &); + void createToolChain(QObject *); + void removeToolChain(); + void updateState(); + +private: + Ui::ToolChainOptionsPage *m_ui; + QWidget *m_configWidget; + QString m_searchKeywords; + QAction *m_cloneAction; + + ToolChainModel *m_model; + QList<ToolChainFactory *> m_factories; + QItemSelectionModel * m_selectionModel; + ToolChainConfigWidget *m_currentTcWidget; +}; + +} // namespace Internal +} // namespace ProjectExplorer + +#endif // TOOLCHAINOPTIONSPAGE_H diff --git a/src/plugins/projectexplorer/toolchainoptionspage.ui b/src/plugins/projectexplorer/toolchainoptionspage.ui new file mode 100644 index 0000000000..3243954052 --- /dev/null +++ b/src/plugins/projectexplorer/toolchainoptionspage.ui @@ -0,0 +1,93 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>ToolChainOptionsPage</class> + <widget class="QWidget" name="ToolChainOptionsPage"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>398</width> + <height>296</height> + </rect> + </property> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <layout class="QHBoxLayout" name="horizontalLayout"> + <item> + <widget class="QTreeView" name="toolChainView"> + <property name="uniformRowHeights"> + <bool>true</bool> + </property> + <attribute name="headerStretchLastSection"> + <bool>false</bool> + </attribute> + </widget> + </item> + <item> + <layout class="QVBoxLayout" name="_2"> + <property name="spacing"> + <number>6</number> + </property> + <property name="margin"> + <number>0</number> + </property> + <item> + <widget class="QToolButton" name="addButton"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>21</width> + <height>23</height> + </size> + </property> + <property name="text"> + <string>+</string> + </property> + </widget> + </item> + <item> + <widget class="QToolButton" name="delButton"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>21</width> + <height>23</height> + </size> + </property> + <property name="text"> + <string>-</string> + </property> + </widget> + </item> + <item> + <spacer> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>10</width> + <height>40</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + </layout> + </item> + </layout> + </widget> + <resources/> + <connections/> +</ui> diff --git a/src/plugins/projectexplorer/userfileaccessor.cpp b/src/plugins/projectexplorer/userfileaccessor.cpp index 26b927c849..43fb4f789a 100644 --- a/src/plugins/projectexplorer/userfileaccessor.cpp +++ b/src/plugins/projectexplorer/userfileaccessor.cpp @@ -40,7 +40,6 @@ #include "projectexplorersettings.h" #include "projectexplorerconstants.h" #include "target.h" -#include "toolchaintype.h" #include <coreplugin/icore.h> #include <coreplugin/ifile.h> @@ -976,13 +975,13 @@ QVariantMap Version0Handler::update(Project *project, const QVariantMap &map) if (!ok) { QString toolChainName(toolchain.toString()); if (toolChainName == QLatin1String("gcc")) - type = ProjectExplorer::ToolChain_GCC; + type = 0; else if (toolChainName == QLatin1String("mingw")) - type = ProjectExplorer::ToolChain_MinGW; + type = 2; else if (toolChainName == QLatin1String("msvc")) - type = ProjectExplorer::ToolChain_MSVC; + type = 3; else if (toolChainName == QLatin1String("wince")) - type = ProjectExplorer::ToolChain_WINCE; + type = 4; } result.insert(QLatin1String("GenericProjectManager.GenericProject.Toolchain"), type); } diff --git a/src/plugins/qmlprojectmanager/qmlprojectrunconfiguration.cpp b/src/plugins/qmlprojectmanager/qmlprojectrunconfiguration.cpp index 06e95fe195..8a2f4bc36c 100644 --- a/src/plugins/qmlprojectmanager/qmlprojectrunconfiguration.cpp +++ b/src/plugins/qmlprojectmanager/qmlprojectrunconfiguration.cpp @@ -287,6 +287,13 @@ Utils::Environment QmlProjectRunConfiguration::environment() const return env; } +ProjectExplorer::Abi QmlProjectRunConfiguration::abi() const +{ + ProjectExplorer::Abi hostAbi = ProjectExplorer::Abi::hostAbi(); + return ProjectExplorer::Abi(hostAbi.architecture(), hostAbi.os(), hostAbi.osFlavor(), + ProjectExplorer::Abi::Format_Runtime_QML, hostAbi.wordWidth()); +} + QVariantMap QmlProjectRunConfiguration::toMap() const { QVariantMap map(ProjectExplorer::RunConfiguration::toMap()); diff --git a/src/plugins/qmlprojectmanager/qmlprojectrunconfiguration.h b/src/plugins/qmlprojectmanager/qmlprojectrunconfiguration.h index 9ac9c0cce1..7e0af9f298 100644 --- a/src/plugins/qmlprojectmanager/qmlprojectrunconfiguration.h +++ b/src/plugins/qmlprojectmanager/qmlprojectrunconfiguration.h @@ -103,6 +103,8 @@ public: ProjectExplorer::OutputFormatter *createOutputFormatter() const; QVariantMap toMap() const; + ProjectExplorer::Abi abi() const; + public slots: void changeCurrentFile(Core::IEditor*); diff --git a/src/plugins/qmlprojectmanager/qmlprojectrunconfigurationwidget.cpp b/src/plugins/qmlprojectmanager/qmlprojectrunconfigurationwidget.cpp index cf843ab5ed..dfd66b6483 100644 --- a/src/plugins/qmlprojectmanager/qmlprojectrunconfigurationwidget.cpp +++ b/src/plugins/qmlprojectmanager/qmlprojectrunconfigurationwidget.cpp @@ -41,6 +41,7 @@ #include <projectexplorer/projectexplorer.h> #include <utils/debuggerlanguagechooser.h> #include <utils/detailswidget.h> +#include <utils/environment.h> #include <utils/qtcassert.h> #include <qt4projectmanager/qt4projectmanagerconstants.h> #include <qt4projectmanager/qtversionmanager.h> diff --git a/src/plugins/qt4projectmanager/debugginghelperbuildtask.cpp b/src/plugins/qt4projectmanager/debugginghelperbuildtask.cpp index fcb99b6421..411e3210f8 100644 --- a/src/plugins/qt4projectmanager/debugginghelperbuildtask.cpp +++ b/src/plugins/qt4projectmanager/debugginghelperbuildtask.cpp @@ -35,6 +35,9 @@ #include "qmldumptool.h" #include "qmlobservertool.h" #include "qmldebugginglibrary.h" +#include "qt4projectmanager/qt4projectmanagerconstants.h" + +#include <projectexplorer/toolchainmanager.h> #include <projectexplorer/debugginghelper.h> #include <QtCore/QCoreApplication> @@ -46,6 +49,8 @@ using ProjectExplorer::DebuggingHelperLibrary; DebuggingHelperBuildTask::DebuggingHelperBuildTask(QtVersion *version, Tools tools) { + if (!version || !version->isValid()) + return; // allow type to be used in queued connections. qRegisterMetaType<DebuggingHelperBuildTask::Tools>("DebuggingHelperBuildTask::Tools"); @@ -68,29 +73,20 @@ DebuggingHelperBuildTask::DebuggingHelperBuildTask(QtVersion *version, Tools too version->addToEnvironment(m_environment); // TODO: the debugging helper doesn't comply to actual tool chain yet - ProjectExplorer::ToolChain *tc = 0; - foreach (ProjectExplorer::ToolChainType toolChainType, version->possibleToolChainTypes()) { - tc = version->toolChain(toolChainType); - if (tc) - break; - } - - if (!tc) { + QList<ProjectExplorer::ToolChain *> tcList = ProjectExplorer::ToolChainManager::instance()->findToolChains(version->qtAbis().at(0)); + if (tcList.isEmpty()) { m_errorMessage = QCoreApplication::translate( "QtVersion", "The Qt Version has no toolchain."); return; } - + ProjectExplorer::ToolChain *tc = tcList.at(0); tc->addToEnvironment(m_environment); - if (tc->type() == ProjectExplorer::ToolChain_GCC_MAEMO5 - || tc->type() == ProjectExplorer::ToolChain_GCC_HARMATTAN - || tc->type() == ProjectExplorer::ToolChain_GCC_MEEGO) { + if (tc->targetAbi().os() == ProjectExplorer::Abi::Linux + && ProjectExplorer::Abi::hostAbi().os() == ProjectExplorer::Abi::Windows) m_target = QLatin1String("-unix"); - } - m_qmakeCommand = version->qmakeCommand(); m_makeCommand = tc->makeCommand(); m_mkspec = version->mkspec(); diff --git a/src/plugins/qt4projectmanager/librarydetailscontroller.cpp b/src/plugins/qt4projectmanager/librarydetailscontroller.cpp index 23634d1785..8aafd1d5da 100644 --- a/src/plugins/qt4projectmanager/librarydetailscontroller.cpp +++ b/src/plugins/qt4projectmanager/librarydetailscontroller.cpp @@ -40,6 +40,7 @@ #include <projectexplorer/projectexplorer.h> #include <projectexplorer/session.h> #include <projectexplorer/target.h> +#include <projectexplorer/toolchain.h> #include <projectexplorer/buildconfiguration.h> #include <QtCore/QFileInfo> @@ -86,8 +87,10 @@ LibraryDetailsController::LibraryDetailsController( Qt4BuildConfiguration *qt4BuildConfiguration = qobject_cast<Qt4BuildConfiguration *>(project->activeTarget()->activeBuildConfiguration()); // if its toolchain is maemo behave the same as we would be on linux - if (qt4BuildConfiguration && (qt4BuildConfiguration->toolChainType() == ProjectExplorer::ToolChain_GCC_MAEMO5 - || qt4BuildConfiguration->toolChainType() == ProjectExplorer::ToolChain_GCC_HARMATTAN)) + if (qt4BuildConfiguration + && qt4BuildConfiguration->toolChain() + && (qt4BuildConfiguration->toolChain()->targetAbi().osFlavor() == ProjectExplorer::Abi::Linux_harmattan + || qt4BuildConfiguration->toolChain()->targetAbi().osFlavor() == ProjectExplorer::Abi::Linux_maemo)) m_creatorPlatform = CreatorLinux; #endif diff --git a/src/plugins/qt4projectmanager/makestep.cpp b/src/plugins/qt4projectmanager/makestep.cpp index 6d5ca85112..ddf478c8ea 100644 --- a/src/plugins/qt4projectmanager/makestep.cpp +++ b/src/plugins/qt4projectmanager/makestep.cpp @@ -173,13 +173,10 @@ bool MakeStep::init() // so we only do it for unix and if the user didn't override the make command // but for now this is the least invasive change - if (toolchain) { - if (toolchain->type() != ProjectExplorer::ToolChain_MSVC && - toolchain->type() != ProjectExplorer::ToolChain_WINCE) { - if (m_makeCmd.isEmpty()) - Utils::QtcProcess::addArg(&args, QLatin1String("-w")); - } - } + if (toolchain + && toolchain->targetAbi().binaryFormat() != ProjectExplorer::Abi::Format_PE + && m_makeCmd.isEmpty()) + Utils::QtcProcess::addArg(&args, QLatin1String("-w")); setEnabled(true); pp->setArguments(args); @@ -304,14 +301,11 @@ void MakeStepConfigWidget::updateDetails() // so we only do it for unix and if the user didn't override the make command // but for now this is the least invasive change QString args = m_makeStep->userArguments(); - ProjectExplorer::ToolChainType t = ProjectExplorer::ToolChain_UNKNOWN; ProjectExplorer::ToolChain *toolChain = bc->toolChain(); - if (toolChain) - t = toolChain->type(); - if (t != ProjectExplorer::ToolChain_MSVC && t != ProjectExplorer::ToolChain_WINCE) { - if (m_makeStep->m_makeCmd.isEmpty()) - Utils::QtcProcess::addArg(&args, QLatin1String("-w")); - } + if (toolChain + && toolChain->targetAbi().binaryFormat() != ProjectExplorer::Abi::Format_PE + && m_makeStep->m_makeCmd.isEmpty()) + Utils::QtcProcess::addArg(&args, QLatin1String("-w")); param.setArguments(args); m_summaryText = param.summaryInWorkdir(displayName()); emit updateSummary(); diff --git a/src/plugins/qt4projectmanager/qmakestep.cpp b/src/plugins/qt4projectmanager/qmakestep.cpp index e6afac8183..bb8c94ebc7 100644 --- a/src/plugins/qt4projectmanager/qmakestep.cpp +++ b/src/plugins/qt4projectmanager/qmakestep.cpp @@ -33,7 +33,7 @@ #include "qmakestep.h" -#include "projectexplorer/projectexplorerconstants.h" +#include <projectexplorer/projectexplorerconstants.h> #include <proparser/profileevaluator.h> #include "qmakeparser.h" #include "qt4buildconfiguration.h" @@ -45,6 +45,7 @@ #include "debugginghelperbuildtask.h" #include <projectexplorer/buildsteplist.h> +#include <projectexplorer/toolchain.h> #include <coreplugin/icore.h> #include <coreplugin/progressmanager/progressmanager.h> @@ -155,11 +156,10 @@ QStringList QMakeStep::moreArguments() Qt4BuildConfiguration *bc = qt4BuildConfiguration(); QStringList arguments; #if defined(Q_OS_WIN) || defined(Q_OS_MAC) - const ProjectExplorer::ToolChainType type = bc->toolChainType(); - if (type == ProjectExplorer::ToolChain_GCC_MAEMO5 - || type == ProjectExplorer::ToolChain_GCC_HARMATTAN) { + ProjectExplorer::ToolChain *tc = bc->toolChain(); + if (tc && (tc->targetAbi().osFlavor() == ProjectExplorer::Abi::Linux_harmattan + || tc->targetAbi().osFlavor() == ProjectExplorer::Abi::Linux_maemo)) arguments << QLatin1String("-unix"); - } #endif if (!bc->qtVersion()->supportsShadowBuilds()) { // We have a target which does not allow shadow building. diff --git a/src/plugins/qt4projectmanager/qt-desktop/qt4runconfiguration.cpp b/src/plugins/qt4projectmanager/qt-desktop/qt4runconfiguration.cpp index 0c9f05d892..b35db1ae31 100644 --- a/src/plugins/qt4projectmanager/qt-desktop/qt4runconfiguration.cpp +++ b/src/plugins/qt4projectmanager/qt-desktop/qt4runconfiguration.cpp @@ -52,6 +52,7 @@ #include <projectexplorer/buildstep.h> #include <projectexplorer/environmentwidget.h> #include <projectexplorer/persistentsettings.h> +#include <projectexplorer/toolchain.h> #include <utils/qtcassert.h> #include <utils/qtcprocess.h> #include <utils/pathchooser.h> @@ -694,11 +695,6 @@ Qt4RunConfiguration::BaseEnvironmentBase Qt4RunConfiguration::baseEnvironmentBas { return m_baseEnvironmentBase; } -ProjectExplorer::ToolChainType Qt4RunConfiguration::toolChainType() const -{ - Qt4BuildConfiguration *qt4bc = qt4Target()->activeBuildConfiguration(); - return qt4bc->toolChainType(); -} ProjectExplorer::OutputFormatter *Qt4RunConfiguration::createOutputFormatter() const { diff --git a/src/plugins/qt4projectmanager/qt-desktop/qt4runconfiguration.h b/src/plugins/qt4projectmanager/qt-desktop/qt4runconfiguration.h index 1d4afd4841..8222f5fed3 100644 --- a/src/plugins/qt4projectmanager/qt-desktop/qt4runconfiguration.h +++ b/src/plugins/qt4projectmanager/qt-desktop/qt4runconfiguration.h @@ -94,7 +94,6 @@ public: virtual Utils::Environment environment() const; virtual QString dumperLibrary() const; virtual QStringList dumperLibraryLocations() const; - virtual ProjectExplorer::ToolChainType toolChainType() const; bool isUsingDyldImageSuffix() const; void setUsingDyldImageSuffix(bool state); diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemodebugsupport.cpp b/src/plugins/qt4projectmanager/qt-maemo/maemodebugsupport.cpp index 0a25f67923..d042add87f 100644 --- a/src/plugins/qt4projectmanager/qt-maemo/maemodebugsupport.cpp +++ b/src/plugins/qt4projectmanager/qt-maemo/maemodebugsupport.cpp @@ -46,8 +46,7 @@ #include <debugger/debuggerstartparameters.h> #include <debugger/debuggerrunner.h> #include <debugger/debuggerengine.h> -#include <projectexplorer/toolchaintype.h> -#include <qt4projectmanager/qt4buildconfiguration.h> +#include <projectexplorer/toolchain.h> #include <QtCore/QDir> #include <QtCore/QFileInfo> @@ -75,8 +74,7 @@ RunControl *MaemoDebugSupport::createDebugRunControl(MaemoRunConfiguration *runC if (debuggingType != MaemoRunConfiguration::DebugQmlOnly) { params.processArgs = runConfig->arguments(); params.sysRoot = runConfig->sysRoot(); - params.toolChainType - = runConfig->activeQt4BuildConfiguration()->toolChainType(); + params.toolChainAbi = runConfig->abi(); params.dumperLibrary = runConfig->dumperLib(); params.remoteDumperLib = uploadDir(devConf).toUtf8() + '/' + QFileInfo(runConfig->dumperLib()).fileName().toUtf8(); diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemodeploystep.cpp b/src/plugins/qt4projectmanager/qt-maemo/maemodeploystep.cpp index 2f02d58a37..424d624d21 100644 --- a/src/plugins/qt4projectmanager/qt-maemo/maemodeploystep.cpp +++ b/src/plugins/qt4projectmanager/qt-maemo/maemodeploystep.cpp @@ -839,9 +839,9 @@ QString MaemoDeployStep::deployMountPoint() const + QLatin1String("/deployMountPoint_") + packagingStep()->projectName(); } -const AbstractMaemoToolChain *MaemoDeployStep::toolChain() const +const MaemoToolChain *MaemoDeployStep::toolChain() const { - return static_cast<AbstractMaemoToolChain *>(qt4BuildConfiguration()->toolChain()); + return static_cast<MaemoToolChain *>(qt4BuildConfiguration()->toolChain()); } const AbstractQt4MaemoTarget *MaemoDeployStep::maemotarget() const diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemodeploystep.h b/src/plugins/qt4projectmanager/qt-maemo/maemodeploystep.h index c0a1112634..0861cc2cfb 100644 --- a/src/plugins/qt4projectmanager/qt-maemo/maemodeploystep.h +++ b/src/plugins/qt4projectmanager/qt-maemo/maemodeploystep.h @@ -66,7 +66,7 @@ namespace Internal { class MaemoRemoteMounter; class MaemoDeviceConfig; class MaemoPackageCreationStep; -class AbstractMaemoToolChain; +class MaemoToolChain; class MaemoUsedPortsGatherer; class MaemoDeployStep : public ProjectExplorer::BuildStep @@ -145,7 +145,7 @@ private: void getDeployTimesFromMap(const QVariantMap &map); const MaemoPackageCreationStep *packagingStep() const; QString deployMountPoint() const; - const AbstractMaemoToolChain *toolChain() const; + const MaemoToolChain *toolChain() const; void copyNextFileToDevice(); void installToSysroot(); QString uploadDir() const; diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemoglobal.h b/src/plugins/qt4projectmanager/qt-maemo/maemoglobal.h index 72afdc52d1..3fb2cac002 100644 --- a/src/plugins/qt4projectmanager/qt-maemo/maemoglobal.h +++ b/src/plugins/qt4projectmanager/qt-maemo/maemoglobal.h @@ -91,6 +91,7 @@ public: static QString targetName(const QtVersion *qtVersion); static QString madCommand(const QtVersion *qtVersion); static MaemoVersion version(const QtVersion *qtVersion); + // TODO: IS this still needed with Qt Version having an Abi? static QString architecture(const QtVersion *version); static bool callMad(QProcess &proc, const QStringList &args, diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemomanager.cpp b/src/plugins/qt4projectmanager/qt-maemo/maemomanager.cpp index e8e16fd686..0fbd115f19 100644 --- a/src/plugins/qt4projectmanager/qt-maemo/maemomanager.cpp +++ b/src/plugins/qt4projectmanager/qt-maemo/maemomanager.cpp @@ -36,6 +36,7 @@ #include "maemoconstants.h" #include "maemodeploystepfactory.h" #include "maemodeviceconfigurations.h" +#include "maemoglobal.h" #include "maemopackagecreationfactory.h" #include "maemopublishingwizardfactories.h" #include "maemoqemumanager.h" @@ -43,9 +44,10 @@ #include "maemosettingspages.h" #include "maemotoolchain.h" #include "qt4maemotargetfactory.h" +#include "qt4projectmanager/qtversionmanager.h" +#include "qt4projectmanager/qt4projectmanagerconstants.h" #include <extensionsystem/pluginmanager.h> -#include <qt4projectmanager/qtversionmanager.h> #include <QtCore/QDir> #include <QtCore/QFile> @@ -69,6 +71,7 @@ MaemoManager::MaemoManager() , m_qemuSettingsPage(new MaemoQemuSettingsPage(this)) , m_publishingFactoryFremantleFree(new MaemoPublishingWizardFactoryFremantleFree(this)) , m_maemoTargetFactory(new Qt4MaemoTargetFactory(this)) + , m_toolChainFactory(new MaemoToolChainFactory) { Q_ASSERT(!m_instance); @@ -77,6 +80,7 @@ MaemoManager::MaemoManager() MaemoDeviceConfigurations::instance(this); PluginManager *pluginManager = PluginManager::instance(); + pluginManager->addObject(m_toolChainFactory); pluginManager->addObject(m_runControlFactory); pluginManager->addObject(m_runConfigurationFactory); pluginManager->addObject(m_packageCreationFactory); @@ -98,6 +102,8 @@ MaemoManager::~MaemoManager() pluginManager->removeObject(m_packageCreationFactory); pluginManager->removeObject(m_runConfigurationFactory); pluginManager->removeObject(m_runControlFactory); + pluginManager->removeObject(m_toolChainFactory); + delete m_toolChainFactory; m_instance = 0; } @@ -108,20 +114,5 @@ MaemoManager &MaemoManager::instance() return *m_instance; } -ToolChain* MaemoManager::maemo5ToolChain(const QtVersion *version) const -{ - return new Maemo5ToolChain(version); -} - -ToolChain* MaemoManager::harmattanToolChain(const QtVersion *version) const -{ - return new HarmattanToolChain(version); -} - -ToolChain* MaemoManager::meegoToolChain(const QtVersion *version) const -{ - return new MeegoToolChain(version); -} - } // namespace Internal } // namespace Qt4ProjectManager diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemomanager.h b/src/plugins/qt4projectmanager/qt-maemo/maemomanager.h index 641f4f28d6..acacf34452 100644 --- a/src/plugins/qt4projectmanager/qt-maemo/maemomanager.h +++ b/src/plugins/qt4projectmanager/qt-maemo/maemomanager.h @@ -36,11 +36,6 @@ #include <QtCore/QObject> -namespace ProjectExplorer { - class ToolChain; -} -using ProjectExplorer::ToolChain; - namespace Qt4ProjectManager { class QtVersion; namespace Internal { @@ -54,6 +49,7 @@ class MaemoDeviceConfigurationsSettingsPage; class MaemoQemuManager; class MaemoQemuSettingsPage; class Qt4MaemoTargetFactory; +class MaemoToolChainFactory; class MaemoManager : public QObject { @@ -64,10 +60,6 @@ public: ~MaemoManager(); static MaemoManager &instance(); - ToolChain *maemo5ToolChain(const Qt4ProjectManager::QtVersion *version) const; - ToolChain *harmattanToolChain(const Qt4ProjectManager::QtVersion *version) const; - ToolChain *meegoToolChain(const Qt4ProjectManager::QtVersion *version) const; - MaemoDeviceConfigurationsSettingsPage *deviceConfigurationsSettingsPage() const { return m_deviceConfigurationsSettingsPage; } MaemoQemuSettingsPage *qemuSettingsPage() const { return m_qemuSettingsPage; } @@ -83,6 +75,7 @@ private: MaemoQemuManager *m_qemuRuntimeManager; MaemoPublishingWizardFactoryFremantleFree *m_publishingFactoryFremantleFree; Qt4MaemoTargetFactory *m_maemoTargetFactory; + MaemoToolChainFactory *m_toolChainFactory; }; } // namespace Internal diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemorunconfiguration.cpp b/src/plugins/qt4projectmanager/qt-maemo/maemorunconfiguration.cpp index aa38e8e93c..a5c99dde59 100644 --- a/src/plugins/qt4projectmanager/qt-maemo/maemorunconfiguration.cpp +++ b/src/plugins/qt4projectmanager/qt-maemo/maemorunconfiguration.cpp @@ -217,11 +217,11 @@ MaemoDeviceConfig::ConstPtr MaemoRunConfiguration::deviceConfig() const return step ? step->deviceConfig() : MaemoDeviceConfig::ConstPtr(); } -const AbstractMaemoToolChain *MaemoRunConfiguration::toolchain() const +const MaemoToolChain *MaemoRunConfiguration::toolchain() const { Qt4BuildConfiguration *qt4bc(activeQt4BuildConfiguration()); QTC_ASSERT(qt4bc, return 0); - AbstractMaemoToolChain *tc = dynamic_cast<AbstractMaemoToolChain *>(qt4bc->toolChain()); + MaemoToolChain *tc = dynamic_cast<MaemoToolChain *>(qt4bc->toolChain()); QTC_ASSERT(tc != 0, return 0); return tc; } @@ -238,7 +238,7 @@ MaemoDeployStep *MaemoRunConfiguration::deployStep() const const QString MaemoRunConfiguration::sysRoot() const { - if (const AbstractMaemoToolChain *tc = toolchain()) + if (const MaemoToolChain *tc = toolchain()) return tc->sysroot(); return QString(); } diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemorunconfiguration.h b/src/plugins/qt4projectmanager/qt-maemo/maemorunconfiguration.h index ff368db43f..62b9d539cf 100644 --- a/src/plugins/qt4projectmanager/qt-maemo/maemorunconfiguration.h +++ b/src/plugins/qt4projectmanager/qt-maemo/maemorunconfiguration.h @@ -63,7 +63,7 @@ class MaemoDeployStep; class MaemoManager; class MaemoRemoteMountsModel; class MaemoRunConfigurationFactory; -class AbstractMaemoToolChain; +class MaemoToolChain; class MaemoRunConfiguration : public ProjectExplorer::RunConfiguration { @@ -91,7 +91,7 @@ public: MaemoDeployStep *deployStep() const; MaemoRemoteMountsModel *remoteMounts() const { return m_remoteMounts; } - const AbstractMaemoToolChain *toolchain() const; + const MaemoToolChain *toolchain() const; QString localExecutableFilePath() const; QString remoteExecutableFilePath() const; const QString sysRoot() const; diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemotoolchain.cpp b/src/plugins/qt4projectmanager/qt-maemo/maemotoolchain.cpp index 8109d41d1c..f671e710e1 100644 --- a/src/plugins/qt4projectmanager/qt-maemo/maemotoolchain.cpp +++ b/src/plugins/qt4projectmanager/qt-maemo/maemotoolchain.cpp @@ -33,41 +33,69 @@ #include "maemotoolchain.h" -#include "maemoconstants.h" #include "maemoglobal.h" +#include "maemomanager.h" +#include "qt4projectmanagerconstants.h" #include "qtversionmanager.h" -#include <QtCore/QDir> -#include <QtCore/QStringBuilder> -#include <QtCore/QTextStream> +#include <projectexplorer/gccparser.h> +#include <projectexplorer/toolchainmanager.h> +#include <utils/environment.h> -using namespace ProjectExplorer; +#include <QtCore/QDir> +#include <QtCore/QFileInfo> +#include <QtGui/QLabel> +#include <QtGui/QVBoxLayout> namespace Qt4ProjectManager { namespace Internal { -AbstractMaemoToolChain::AbstractMaemoToolChain(const QtVersion *qtVersion) - : GccToolChain(MaemoGlobal::targetRoot(qtVersion) % QLatin1String("/bin/gcc")) - , m_sysrootInitialized(false) - , m_qtVersionId(qtVersion->uniqueId()) +static const char *const MAEMO_QT_VERSION_KEY = "Qt4ProjectManager.Maemo.QtVersion"; + +// -------------------------------------------------------------------------- +// MaemoToolChain +// -------------------------------------------------------------------------- + +MaemoToolChain::MaemoToolChain(bool autodetected) : + ProjectExplorer::GccToolChain(QLatin1String(Constants::MAEMO_TOOLCHAIN_ID), autodetected), + m_qtVersionId(-1) { + updateId(); } -AbstractMaemoToolChain::~AbstractMaemoToolChain() +MaemoToolChain::MaemoToolChain(const MaemoToolChain &tc) : + ProjectExplorer::GccToolChain(tc), + m_qtVersionId(tc.m_qtVersionId) +{ } + +MaemoToolChain::~MaemoToolChain() +{ } + +QString MaemoToolChain::typeName() const { + return MaemoToolChainFactory::tr("Maemo GCC"); } -void AbstractMaemoToolChain::addToEnvironment(Utils::Environment &env) +ProjectExplorer::Abi MaemoToolChain::targetAbi() const { - QtVersion *version = QtVersionManager::instance()->version(m_qtVersionId); - const QString maddeRoot = MaemoGlobal::maddeRoot(version); - env.prependOrSetPath(QDir::toNativeSeparators(QString("%1/bin") - .arg(maddeRoot))); + return m_targetAbi; +} + +bool MaemoToolChain::isValid() const +{ + return GccToolChain::isValid() && m_qtVersionId >= 0 && m_targetAbi.isValid(); +} + +void MaemoToolChain::addToEnvironment(Utils::Environment &env) const +{ + QtVersion *v = QtVersionManager::instance()->version(m_qtVersionId); + const QString maddeRoot = MaemoGlobal::maddeRoot(v); + env.prependOrSetPath(QDir::toNativeSeparators(QString("%1/bin").arg(maddeRoot))); env.prependOrSetPath(QDir::toNativeSeparators(QString("%1/bin") - .arg(MaemoGlobal::targetRoot(version)))); + .arg(MaemoGlobal::targetRoot(v)))); // put this into environment to make pkg-config stuff work - env.prependOrSet(QLatin1String("SYSROOT_DIR"), sysroot()); + env.prependOrSet(QLatin1String("SYSROOT_DIR"), QDir::toNativeSeparators(sysroot())); env.prependOrSetPath(QDir::toNativeSeparators(QString("%1/madbin") .arg(maddeRoot))); env.prependOrSetPath(QDir::toNativeSeparators(QString("%1/madlib") @@ -76,82 +104,208 @@ void AbstractMaemoToolChain::addToEnvironment(Utils::Environment &env) QDir::toNativeSeparators(QString("%1/madlib/perl5").arg(maddeRoot))); } -QString AbstractMaemoToolChain::makeCommand() const +QString MaemoToolChain::sysroot() const { - return QLatin1String("make" EXEC_SUFFIX); + QtVersion *v = QtVersionManager::instance()->version(m_qtVersionId); + if (!v) + return QString(); + + if (m_sysroot.isEmpty()) { + QFile file(QDir::cleanPath(MaemoGlobal::targetRoot(v)) + QLatin1String("/information")); + if (file.exists() && file.open(QIODevice::ReadOnly | QIODevice::Text)) { + QTextStream stream(&file); + while (!stream.atEnd()) { + const QString &line = stream.readLine().trimmed(); + const QStringList &list = line.split(QLatin1Char(' ')); + if (list.count() > 1 && list.at(0) == QLatin1String("sysroot")) + m_sysroot = MaemoGlobal::maddeRoot(v) + QLatin1String("/sysroots/") + list.at(1); + } + } + } + return m_sysroot; } -bool AbstractMaemoToolChain::equals(const ToolChain *other) const +bool MaemoToolChain::operator ==(const ProjectExplorer::ToolChain &tc) const { - const AbstractMaemoToolChain *toolChain = static_cast<const AbstractMaemoToolChain*> (other); - return other->type() == type() && toolChain->m_qtVersionId == m_qtVersionId; + if (!ToolChain::operator ==(tc)) + return false; + + const MaemoToolChain *tcPtr = static_cast<const MaemoToolChain *>(&tc); + return m_qtVersionId == tcPtr->m_qtVersionId; } -QString AbstractMaemoToolChain::sysroot() const +ProjectExplorer::ToolChainConfigWidget *MaemoToolChain::configurationWidget() { - if (!m_sysrootInitialized) - setSysroot(); - return m_sysrootRoot; + return new MaemoToolChainConfigWidget(this); } -void AbstractMaemoToolChain::setSysroot() const +QVariantMap MaemoToolChain::toMap() const { - QtVersion *version = QtVersionManager::instance()->version(m_qtVersionId); - QFile file(QDir::cleanPath(MaemoGlobal::targetRoot(version)) - + QLatin1String("/information")); - if (file.exists() && file.open(QIODevice::ReadOnly | QIODevice::Text)) { - QTextStream stream(&file); - while (!stream.atEnd()) { - const QString &line = stream.readLine().trimmed(); - const QStringList &list = line.split(QLatin1Char(' ')); - if (list.count() <= 1) - continue; - if (list.at(0) == QLatin1String("sysroot")) { - m_sysrootRoot = MaemoGlobal::maddeRoot(version) - + QLatin1String("/sysroots/") + list.at(1); - } - } + QVariantMap result = GccToolChain::toMap(); + result.insert(QLatin1String(MAEMO_QT_VERSION_KEY), m_qtVersionId); + return result; +} + +bool MaemoToolChain::fromMap(const QVariantMap &data) +{ + if (!GccToolChain::fromMap(data)) + return false; + + m_qtVersionId = data.value(QLatin1String(MAEMO_QT_VERSION_KEY), -1).toInt(); + + return isValid(); +} + +void MaemoToolChain::setQtVersionId(int id) +{ + if (id < 0) { + m_targetAbi = ProjectExplorer::Abi(); + m_qtVersionId = -1; + updateId(); + return; } - m_sysrootInitialized = true; + QtVersion *version = QtVersionManager::instance()->version(id); + Q_ASSERT(version); + ProjectExplorer::Abi::OSFlavour flavour = ProjectExplorer::Abi::Linux_harmattan; + if (MaemoGlobal::isValidMaemo5QtVersion(version)) + flavour = ProjectExplorer::Abi::Linux_maemo; + else if (MaemoGlobal::isValidHarmattanQtVersion(version)) + flavour = ProjectExplorer::Abi::Linux_harmattan; + else if (MaemoGlobal::isValidMeegoQtVersion(version)) + flavour = ProjectExplorer::Abi::Linux_meego; + else + return; + + m_qtVersionId = id; + + Q_ASSERT(version->qtAbis().count() == 1); + m_targetAbi = version->qtAbis().at(0); + + updateId(); + setDisplayName(MaemoToolChainFactory::tr("Maemo Gcc for %1").arg(version->displayName())); } +int MaemoToolChain::qtVersionId() const +{ + return m_qtVersionId; +} + +void MaemoToolChain::updateId() +{ + setId(QString::fromLatin1("%1:%2").arg(Constants::MAEMO_TOOLCHAIN_ID).arg(m_qtVersionId)); +} + +// -------------------------------------------------------------------------- +// ToolChainConfigWidget +// -------------------------------------------------------------------------- -Maemo5ToolChain::Maemo5ToolChain(const QtVersion *qtVersion) - : AbstractMaemoToolChain(qtVersion) +MaemoToolChainConfigWidget::MaemoToolChainConfigWidget(MaemoToolChain *tc) : + ProjectExplorer::ToolChainConfigWidget(tc) { + QVBoxLayout *layout = new QVBoxLayout(this); + QLabel *label = new QLabel; + QtVersion *v = QtVersionManager::instance()->version(tc->qtVersionId()); + Q_ASSERT(v); + label->setText(tr("MADDE Root: %1<br>Target Root: %2") + .arg(MaemoGlobal::maddeRoot(v)) + .arg(MaemoGlobal::targetRoot(v))); + layout->addWidget(label); } -Maemo5ToolChain::~Maemo5ToolChain() {} +void MaemoToolChainConfigWidget::apply() +{ + // nothing to do! +} -ProjectExplorer::ToolChainType Maemo5ToolChain::type() const +void MaemoToolChainConfigWidget::discard() { - return ProjectExplorer::ToolChain_GCC_MAEMO5; + // nothing to do! } -HarmattanToolChain::HarmattanToolChain(const QtVersion *qtVersion) - : AbstractMaemoToolChain(qtVersion) +bool MaemoToolChainConfigWidget::isDirty() const { + return false; } -HarmattanToolChain::~HarmattanToolChain() {} +// -------------------------------------------------------------------------- +// ToolChainFactory +// -------------------------------------------------------------------------- + +MaemoToolChainFactory::MaemoToolChainFactory() : + ProjectExplorer::ToolChainFactory() +{ } -ProjectExplorer::ToolChainType HarmattanToolChain::type() const +QString MaemoToolChainFactory::displayName() const { - return ProjectExplorer::ToolChain_GCC_HARMATTAN; + return tr("Maemo GCC"); } +QString MaemoToolChainFactory::id() const +{ + return QLatin1String(Constants::MAEMO_TOOLCHAIN_ID); +} -MeegoToolChain::MeegoToolChain(const QtVersion *qtVersion) - : AbstractMaemoToolChain(qtVersion) +QList<ProjectExplorer::ToolChain *> MaemoToolChainFactory::autoDetect() { + QList<ProjectExplorer::ToolChain *> result; + + QtVersionManager *vm = QtVersionManager::instance(); + connect(vm, SIGNAL(qtVersionsChanged(QList<int>)), + this, SLOT(handleQtVersionChanges(QList<int>))); + + QList<int> versionList; + foreach (QtVersion *v, vm->versions()) + versionList.append(v->uniqueId()); + + return createToolChainList(versionList); } -MeegoToolChain::~MeegoToolChain() {} +void MaemoToolChainFactory::handleQtVersionChanges(const QList<int> &changes) +{ + ProjectExplorer::ToolChainManager *tcm = ProjectExplorer::ToolChainManager::instance(); + QList<ProjectExplorer::ToolChain *> tcList = createToolChainList(changes); + foreach (ProjectExplorer::ToolChain *tc, tcList) + tcm->registerToolChain(tc); +} -ProjectExplorer::ToolChainType MeegoToolChain::type() const +QList<ProjectExplorer::ToolChain *> MaemoToolChainFactory::createToolChainList(const QList<int> &changes) { - return ProjectExplorer::ToolChain_GCC_MEEGO; + ProjectExplorer::ToolChainManager *tcm = ProjectExplorer::ToolChainManager::instance(); + QtVersionManager *vm = QtVersionManager::instance(); + QList<ProjectExplorer::ToolChain *> result; + + foreach (int i, changes) { + QtVersion *v = vm->version(i); + if (!v) { + // remove ToolChain: + QList<ProjectExplorer::ToolChain *> toRemove; + foreach (ProjectExplorer::ToolChain *tc, tcm->toolChains()) { + if (!tc->id().startsWith(QLatin1String(Constants::MAEMO_TOOLCHAIN_ID))) + continue; + MaemoToolChain *mTc = static_cast<MaemoToolChain *>(tc); + if (mTc->qtVersionId() == i) + toRemove.append(mTc); + } + foreach (ProjectExplorer::ToolChain *tc, toRemove) + tcm->deregisterToolChain(tc); + } else if (v->supportsTargetId(Constants::MAEMO5_DEVICE_TARGET_ID) + || v->supportsTargetId(Constants::HARMATTAN_DEVICE_TARGET_ID) + || v->supportsTargetId(Constants::MEEGO_DEVICE_TARGET_ID)) { + // add ToolChain: + MaemoToolChain *mTc = new MaemoToolChain(true); + mTc->setQtVersionId(i); + QString target = "Maemo 5"; + if (v->supportsTargetId(Constants::HARMATTAN_DEVICE_TARGET_ID)) + target = "Maemo 6"; + else if (v->supportsTargetId(Constants::MEEGO_DEVICE_TARGET_ID)) + target = "Meego"; + mTc->setDisplayName(tr("%1 GCC (%2)").arg(target).arg(MaemoGlobal::maddeRoot(v))); + mTc->setCompilerPath(MaemoGlobal::targetRoot(v) + QLatin1String("/bin/gcc")); + result.append(mTc); + } + } + return result; } } // namespace Internal diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemotoolchain.h b/src/plugins/qt4projectmanager/qt-maemo/maemotoolchain.h index 8b33d4053a..3dd1aa2683 100644 --- a/src/plugins/qt4projectmanager/qt-maemo/maemotoolchain.h +++ b/src/plugins/qt4projectmanager/qt-maemo/maemotoolchain.h @@ -34,59 +34,90 @@ #ifndef MAEMOTOOLCHAIN_H #define MAEMOTOOLCHAIN_H -#include <projectexplorer/toolchain.h> +#include <projectexplorer/gcctoolchain.h> +#include <projectexplorer/toolchainconfigwidget.h> namespace Qt4ProjectManager { class QtVersion; + namespace Internal { -class AbstractMaemoToolChain : public ProjectExplorer::GccToolChain +// -------------------------------------------------------------------------- +// MaemoToolChain +// -------------------------------------------------------------------------- + +class MaemoToolChain : public ProjectExplorer::GccToolChain { public: - AbstractMaemoToolChain(const QtVersion *qtVersion); - virtual ~AbstractMaemoToolChain(); + ~MaemoToolChain(); + + QString typeName() const; + ProjectExplorer::Abi targetAbi() const; - void addToEnvironment(Utils::Environment &env); - QString makeCommand() const; + bool isValid() const; + + void addToEnvironment(Utils::Environment &env) const; QString sysroot() const; -protected: - bool equals(const ToolChain *other) const; + bool operator ==(const ProjectExplorer::ToolChain &) const; -private: - void setSysroot() const; + ProjectExplorer::ToolChainConfigWidget *configurationWidget(); + + + QVariantMap toMap() const; + bool fromMap(const QVariantMap &data); + + void setQtVersionId(int); + int qtVersionId() const; private: - mutable QString m_sysrootRoot; - mutable bool m_sysrootInitialized; + void updateId(); + + explicit MaemoToolChain(bool); + MaemoToolChain(const MaemoToolChain &); + int m_qtVersionId; + mutable QString m_sysroot; + ProjectExplorer::Abi m_targetAbi; + + friend class MaemoToolChainFactory; }; -class Maemo5ToolChain : public AbstractMaemoToolChain +// -------------------------------------------------------------------------- +// MaemoToolChainConfigWidget +// -------------------------------------------------------------------------- + +class MaemoToolChainConfigWidget : public ProjectExplorer::ToolChainConfigWidget { + Q_OBJECT + public: - Maemo5ToolChain(const QtVersion *qtVersion); - ~Maemo5ToolChain(); + MaemoToolChainConfigWidget(MaemoToolChain *); - ProjectExplorer::ToolChainType type() const; + void apply(); + void discard(); + bool isDirty() const; }; -class HarmattanToolChain : public AbstractMaemoToolChain +// -------------------------------------------------------------------------- +// MaemoToolChainFactory +// -------------------------------------------------------------------------- + +class MaemoToolChainFactory : public ProjectExplorer::ToolChainFactory { + Q_OBJECT + public: - HarmattanToolChain(const QtVersion *qtVersion); - ~HarmattanToolChain(); + MaemoToolChainFactory(); - ProjectExplorer::ToolChainType type() const; -}; + QString displayName() const; + QString id() const; -class MeegoToolChain : public AbstractMaemoToolChain -{ -public: - MeegoToolChain(const QtVersion *qtVersion); - ~MeegoToolChain(); + QList<ProjectExplorer::ToolChain *> autoDetect(); - ProjectExplorer::ToolChainType type() const; +private slots: + void handleQtVersionChanges(const QList<int> &); + QList<ProjectExplorer::ToolChain *> createToolChainList(const QList<int> &); }; } // namespace Internal diff --git a/src/plugins/qt4projectmanager/qt-maemo/qt4maemotarget.cpp b/src/plugins/qt4projectmanager/qt-maemo/qt4maemotarget.cpp index 788af72f74..61454d1fa5 100644 --- a/src/plugins/qt4projectmanager/qt-maemo/qt4maemotarget.cpp +++ b/src/plugins/qt4projectmanager/qt-maemo/qt4maemotarget.cpp @@ -37,6 +37,7 @@ #include "maemopackagecreationstep.h" #include "maemopertargetdeviceconfigurationlistmodel.h" #include "maemorunconfiguration.h" +#include "maemotoolchain.h" #include "qt4maemodeployconfiguration.h" #include <coreplugin/icore.h> @@ -120,10 +121,45 @@ AbstractQt4MaemoTarget::AbstractQt4MaemoTarget(Qt4Project *parent, const QString } AbstractQt4MaemoTarget::~AbstractQt4MaemoTarget() +{ } + +AbstractQt4MaemoTarget::DebugArchitecture AbstractQt4MaemoTarget::debugArchitecture() const +{ + const QString arch + = MaemoGlobal::architecture(activeBuildConfiguration()->qtVersion()); + if (arch.startsWith(QLatin1String("arm"))) { + return DebugArchitecture(QLatin1String("arm"), + QLatin1String("arm-none-linux-gnueabi")); + } else if (arch.startsWith(QLatin1String("x86_64"))) { + return DebugArchitecture(QLatin1String("i386:x86-64"), + QLatin1String("x86_64-unknown-linux-gnu ")); + } else { + return DebugArchitecture(QLatin1String("x86"), + QLatin1String("i386-unknown-linux-gnu ")); + } +} + +QList<ProjectExplorer::ToolChain *> AbstractQt4MaemoTarget::possibleToolChains(ProjectExplorer::BuildConfiguration *bc) const { + QList<ProjectExplorer::ToolChain *> result; + + Qt4BuildConfiguration *qt4Bc = qobject_cast<Qt4BuildConfiguration *>(bc); + if (!qt4Bc) + return result; + + QList<ProjectExplorer::ToolChain *> candidates = Qt4BaseTarget::possibleToolChains(bc); + foreach (ProjectExplorer::ToolChain *i, candidates) { + MaemoToolChain *tc = dynamic_cast<MaemoToolChain *>(i); + if (!tc) + continue; + if (tc->qtVersionId() == qt4Bc->qtVersion()->uniqueId()) + result.append(tc); + } + return result; } + Qt4BuildConfigurationFactory *AbstractQt4MaemoTarget::buildConfigurationFactory() const { return m_buildConfigurationFactory; @@ -346,23 +382,6 @@ void AbstractQt4MaemoTarget::raiseError(const QString &reason) QMessageBox::critical(0, tr("Error creating Maemo templates"), reason); } -AbstractQt4MaemoTarget::DebugArchitecture AbstractQt4MaemoTarget::debugArchitecture() const -{ - const QString arch - = MaemoGlobal::architecture(activeBuildConfiguration()->qtVersion()); - if (arch.startsWith(QLatin1String("arm"))) { - return DebugArchitecture(QLatin1String("arm"), - QLatin1String("arm-none-linux-gnueabi")); - } else if (arch.startsWith(QLatin1String("x86_64"))) { - return DebugArchitecture(QLatin1String("i386:x86-64"), - QLatin1String("x86_64-unknown-linux-gnu ")); - } else { - return DebugArchitecture(QLatin1String("x86"), - QLatin1String("i386-unknown-linux-gnu ")); - } -} - - AbstractDebBasedQt4MaemoTarget::AbstractDebBasedQt4MaemoTarget(Qt4Project *parent, const QString &id) : AbstractQt4MaemoTarget(parent, id) { diff --git a/src/plugins/qt4projectmanager/qt-maemo/qt4maemotarget.h b/src/plugins/qt4projectmanager/qt-maemo/qt4maemotarget.h index 1dbaf6025d..e5ebb545f6 100644 --- a/src/plugins/qt4projectmanager/qt-maemo/qt4maemotarget.h +++ b/src/plugins/qt4projectmanager/qt-maemo/qt4maemotarget.h @@ -77,16 +77,20 @@ public: bool setShortDescription(const QString &description); struct DebugArchitecture { - DebugArchitecture(const QString &a, const QString &t) : - architecture(a), gnuTarget(t) {} + explicit DebugArchitecture(const QString &a = QString(), const QString &t = QString()) : + architecture(a), gnuTarget(t) + { } + QString architecture; QString gnuTarget; }; + // TODO: Is this needed with the ABI info we have? DebugArchitecture debugArchitecture() const; MaemoPerTargetDeviceConfigurationListModel *deviceConfigurationsModel() const { return m_deviceConfigurationsListModel; } + QList<ProjectExplorer::ToolChain *> possibleToolChains(ProjectExplorer::BuildConfiguration *bc) const; protected: enum ActionStatus { NoActionRequired, ActionSuccessful, ActionFailed }; diff --git a/src/plugins/qt4projectmanager/qt-s60/gccetoolchain.cpp b/src/plugins/qt4projectmanager/qt-s60/gccetoolchain.cpp index fd4558ded8..186887de15 100644 --- a/src/plugins/qt4projectmanager/qt-s60/gccetoolchain.cpp +++ b/src/plugins/qt4projectmanager/qt-s60/gccetoolchain.cpp @@ -32,73 +32,68 @@ **************************************************************************/ #include "gccetoolchain.h" -#include "qt4project.h" +#include "qt4projectmanagerconstants.h" -#include <utils/qtcassert.h> +#include <utils/environment.h> #include <utils/synchronousprocess.h> #include <QtCore/QDir> -#include <QtCore/QProcess> -#include <QtCore/QtDebug> -enum { debug = 0 }; +namespace Qt4ProjectManager { +namespace Internal { -using namespace ProjectExplorer; -using namespace Qt4ProjectManager::Internal; - -// Locate the compiler via path. -static QString gcceCommand(const QString &dir) +static QString gcceVersion(const QString &command) { + if (command.isEmpty()) + return QString(); + + QProcess gxx; + QStringList arguments; + arguments << QLatin1String("-dumpversion"); Utils::Environment env = Utils::Environment::systemEnvironment(); - if (!dir.isEmpty()) { - env.prependOrSetPath(dir + QLatin1String("/bin")); - env.prependOrSetPath(dir); + env.set(QLatin1String("LC_ALL"), QLatin1String("C")); //override current locale settings + gxx.setEnvironment(env.toStringList()); + gxx.setReadChannelMode(QProcess::MergedChannels); + gxx.start(command, arguments); + if (!gxx.waitForStarted()) { + qWarning("Cannot start '%s': %s", qPrintable(command), qPrintable(gxx.errorString())); + return QString(); } - QString gcce = QLatin1String("arm-none-symbianelf-gcc"); -#ifdef Q_OS_WIN - gcce += QLatin1String(".exe"); -#endif - const QString rc = env.searchInPath(gcce); - if (debug && rc.isEmpty()) { - const QString msg = QString::fromLatin1("GCCEToolChain: Unable to locate '%1' in '%2' (GCCE root: '%3')") - .arg(gcce, env.value(QLatin1String("PATH")), dir); - qWarning("%s", qPrintable(msg)); - return gcce; + gxx.closeWriteChannel(); + if (!gxx.waitForFinished()) { + Utils::SynchronousProcess::stopProcess(gxx); + qWarning("Timeout running '%s'.", qPrintable(command)); + return QString(); + } + if (gxx.exitStatus() != QProcess::NormalExit) { + qWarning("'%s' crashed.", qPrintable(command)); + return QString(); } - return rc; -} -// The GccToolChain base class constructor wants to know the gcc command -GCCEToolChain *GCCEToolChain::create(const S60Devices::Device &device, - const QString &gcceRoot, - ProjectExplorer::ToolChainType type) -{ - const QString gccCommand = gcceCommand(gcceRoot); - const QFileInfo gccCommandFi(gccCommand); - const QString binPath = gccCommandFi.isRelative() ? QString() : gccCommandFi.absolutePath(); - return new GCCEToolChain(device, binPath, gccCommand, type); + if (gxx.canReadLine()) + return gxx.readLine().trimmed(); + + return QString(); } -GCCEToolChain::GCCEToolChain(const S60Devices::Device &device, - const QString &gcceBinPath, - const QString &gcceCommand, - ProjectExplorer::ToolChainType type) : - GccToolChain(gcceCommand), - m_mixin(device), - m_type(type), - m_gcceBinPath(gcceBinPath) + +// ========================================================================== +// GcceToolChain +// ========================================================================== + +QString GcceToolChain::typeName() const { - QTC_ASSERT(m_type == ProjectExplorer::ToolChain_GCCE || m_type == ProjectExplorer::ToolChain_GCCE_GNUPOC, return) - if (debug) - qDebug() << "GCCEToolChain on" << m_type << gcceCommand << gcceBinPath << m_mixin.device(); + return GcceToolChainFactory::tr("GCCE"); } -ProjectExplorer::ToolChainType GCCEToolChain::type() const +ProjectExplorer::Abi GcceToolChain::targetAbi() const { - return m_type; + return ProjectExplorer::Abi(ProjectExplorer::Abi::ARM, ProjectExplorer::Abi::Symbian, + ProjectExplorer::Abi::Symbian_device, + ProjectExplorer::Abi::Format_ELF, false); } -QByteArray GCCEToolChain::predefinedMacros() +QByteArray GcceToolChain::predefinedMacros() const { if (m_predefinedMacros.isEmpty()) { ProjectExplorer::GccToolChain::predefinedMacros(); @@ -109,97 +104,90 @@ QByteArray GCCEToolChain::predefinedMacros() return m_predefinedMacros; } -QList<HeaderPath> GCCEToolChain::systemHeaderPaths() +void GcceToolChain::addToEnvironment(Utils::Environment &env) const { - if (m_systemHeaderPaths.isEmpty()) { - GccToolChain::systemHeaderPaths(); - switch (m_type) { - case ProjectExplorer::ToolChain_GCCE: - m_systemHeaderPaths += m_mixin.epocHeaderPaths(); - break; - case ProjectExplorer::ToolChain_GCCE_GNUPOC: - m_systemHeaderPaths += m_mixin.gnuPocHeaderPaths(); - break; - default: - break; - } - } - return m_systemHeaderPaths; + GccToolChain::addToEnvironment(env); + + if (m_gcceVersion.isEmpty()) + m_gcceVersion = gcceVersion(compilerPath()); + if (m_gcceVersion.isEmpty()) + return; + + env.set(QLatin1String("QT_GCCE_VERSION"), m_gcceVersion); + QString version = m_gcceVersion; + env.set(QString::fromLatin1("SBS_GCCE") + version.remove(QLatin1Char('.')) + + QLatin1String("BIN"), + QDir::toNativeSeparators(QFileInfo(compilerPath()).absolutePath())); } -void GCCEToolChain::addToEnvironment(Utils::Environment &env) +QString GcceToolChain::defaultMakeTarget() const { - if (debug) - qDebug() << "GCCEToolChain::addToEnvironment" << m_type << gcc() << m_gcceBinPath<< m_mixin.device(); - - if (!m_gcceBinPath.isEmpty()) - env.prependOrSetPath(m_gcceBinPath); - switch (m_type) { - case ProjectExplorer::ToolChain_GCCE: - m_mixin.addEpocToEnvironment(&env); - break; - case ProjectExplorer::ToolChain_GCCE_GNUPOC: - m_mixin.addGnuPocToEnvironment(&env); - break; - default: - break; - } - QString version = gcceVersion(); - env.set(QLatin1String("QT_GCCE_VERSION"), version); - version = version.remove(QLatin1Char('.')); - env.set(QString::fromLatin1("SBS_GCCE") + version + QLatin1String("BIN"), QDir::toNativeSeparators(m_gcceBinPath)); + return QLatin1String("gcce"); } -QString GCCEToolChain::makeCommand() const +ProjectExplorer::ToolChain *GcceToolChain::clone() const +{ + return new GcceToolChain(*this); +} + +GcceToolChain::GcceToolChain(bool autodetected) : + GccToolChain(QLatin1String(Constants::GCCE_TOOLCHAIN_ID), autodetected) +{ } + +// ========================================================================== +// GcceToolChainFactory +// ========================================================================== + +QString GcceToolChainFactory::displayName() const { -#if defined (Q_OS_WIN) - return QLatin1String("make.exe"); -#else - return QLatin1String("make"); -#endif + return tr("GCCE"); } -bool GCCEToolChain::equals(const ToolChain *otherIn) const +QString GcceToolChainFactory::id() const { - if (otherIn->type() != type()) - return false; - const GCCEToolChain *other = static_cast<const GCCEToolChain *>(otherIn); - return m_mixin == other->m_mixin - && m_gcceBinPath == other->m_gcceBinPath - && gcc() == other->gcc(); + return QLatin1String(Constants::GCCE_TOOLCHAIN_ID); } -QString GCCEToolChain::gcceVersion() const +QList<ProjectExplorer::ToolChain *> GcceToolChainFactory::autoDetect() { - if (m_gcceVersion.isEmpty()) { - QString command = gcceCommand(m_gcceBinPath); - if (command.isEmpty()) - return QString(); - QProcess gxx; - QStringList arguments; - arguments << QLatin1String("-dumpversion"); - Utils::Environment env = Utils::Environment::systemEnvironment(); - env.set(QLatin1String("LC_ALL"), QLatin1String("C")); //override current locale settings - gxx.setEnvironment(env.toStringList()); - gxx.setReadChannelMode(QProcess::MergedChannels); - gxx.start(command, arguments); - if (!gxx.waitForStarted()) { - qWarning("Cannot start '%s': %s", qPrintable(command), qPrintable(gxx.errorString())); - return QString(); - } - gxx.closeWriteChannel(); - if (!gxx.waitForFinished()) { - Utils::SynchronousProcess::stopProcess(gxx); - qWarning("Timeout running '%s'.", qPrintable(command)); - return QString(); - } - if (gxx.exitStatus() != QProcess::NormalExit) { - qWarning("'%s' crashed.", qPrintable(command)); - return QString(); - } - - if (gxx.canReadLine()) - m_gcceVersion = gxx.readLine().trimmed(); + QList<ProjectExplorer::ToolChain *> result; + + QString fullPath = Utils::Environment::systemEnvironment().searchInPath(QLatin1String("arm-none-symbianelf-gcc")); + if (!fullPath.isEmpty()) { + GcceToolChain *tc = new GcceToolChain(true); + tc->setCompilerPath(fullPath); + tc->setDisplayName(tr("GCCE (%1)").arg(gcceVersion(fullPath))); + result.append(tc); } - return m_gcceVersion; + return result; } + +bool GcceToolChainFactory::canCreate() +{ + return true; +} + +ProjectExplorer::ToolChain *GcceToolChainFactory::create() +{ + GcceToolChain *tc = new GcceToolChain(false); + tc->setDisplayName(tr("GCCE")); + return tc; +} + +bool GcceToolChainFactory::canRestore(const QVariantMap &data) +{ + return idFromMap(data).startsWith(QLatin1String(Constants::GCCE_TOOLCHAIN_ID)); +} + +ProjectExplorer::ToolChain *GcceToolChainFactory::restore(const QVariantMap &data) +{ + GcceToolChain *tc = new GcceToolChain(false); + if (tc->fromMap(data)) + return tc; + + delete tc; + return 0; +} + +} // namespace Internal +} // namespace Qt4ProjectManager diff --git a/src/plugins/qt4projectmanager/qt-s60/gccetoolchain.h b/src/plugins/qt4projectmanager/qt-s60/gccetoolchain.h index 31c63882d5..eed230c922 100644 --- a/src/plugins/qt4projectmanager/qt-s60/gccetoolchain.h +++ b/src/plugins/qt4projectmanager/qt-s60/gccetoolchain.h @@ -36,37 +36,54 @@ #include "s60devices.h" -#include <projectexplorer/toolchain.h> +#include <projectexplorer/gcctoolchain.h> namespace Qt4ProjectManager { namespace Internal { -class GCCEToolChain : public ProjectExplorer::GccToolChain +// ========================================================================== +// GcceToolChain +// ========================================================================== + +class GcceToolChain : public ProjectExplorer::GccToolChain { - explicit GCCEToolChain(const S60Devices::Device &device, - const QString &gcceBinPath, - const QString &gcceCommand, - ProjectExplorer::ToolChainType type); public: - static GCCEToolChain *create(const S60Devices::Device &device, - const QString &gcceRoot, - ProjectExplorer::ToolChainType type); + QString typeName() const; + ProjectExplorer::Abi targetAbi() const; - QByteArray predefinedMacros(); - virtual QList<ProjectExplorer::HeaderPath> systemHeaderPaths(); - virtual void addToEnvironment(Utils::Environment &env); - virtual ProjectExplorer::ToolChainType type() const; - virtual QString makeCommand() const; + QByteArray predefinedMacros() const; + void addToEnvironment(Utils::Environment &env) const; + QString defaultMakeTarget() const; -protected: - virtual bool equals(const ToolChain *other) const; + ProjectExplorer::ToolChain *clone() const; private: - QString gcceVersion() const; - const S60ToolChainMixin m_mixin; - const ProjectExplorer::ToolChainType m_type; - const QString m_gcceBinPath; + explicit GcceToolChain(bool autodetected); + mutable QString m_gcceVersion; + + friend class GcceToolChainFactory; +}; + +// ========================================================================== +// GcceToolChainFactory +// ========================================================================== + +class GcceToolChainFactory : public ProjectExplorer::ToolChainFactory +{ + Q_OBJECT + +public: + QString displayName() const; + QString id() const; + + QList<ProjectExplorer::ToolChain *> autoDetect(); + + bool canCreate(); + ProjectExplorer::ToolChain *create(); + + bool canRestore(const QVariantMap &data); + ProjectExplorer::ToolChain *restore(const QVariantMap &data); }; } // namespace Internal diff --git a/src/plugins/qt4projectmanager/qt-s60/qt-s60-todo.txt b/src/plugins/qt4projectmanager/qt-s60/qt-s60-todo.txt index ba0a022f7c..cbb483b58c 100644 --- a/src/plugins/qt4projectmanager/qt-s60/qt-s60-todo.txt +++ b/src/plugins/qt4projectmanager/qt-s60/qt-s60-todo.txt @@ -6,19 +6,13 @@ * QtVersion: * gui for overriding the default make target if necessary, make arguments --> make options - * build parser should be defined/created by toolchain, not make step * Tool chains - * Qt4Project::setQtVersion should think about tool chains, - might be better to remove the magic in toolChainType method * should the default make target be defined by the project instead of tool chain, or perhaps by the QtVersion dependent on a tool chain? - * seems that the make for building for device doesn't return useful exit code, - so a run is started even if the build has errors * Run on device - * passphrase for signing * time stamp of copied sisx is ridiculous * don't copy the sisx all the time * don't hardcode copy destination diff --git a/src/plugins/qt4projectmanager/qt-s60/qt-s60.pri b/src/plugins/qt4projectmanager/qt-s60/qt-s60.pri index 33fd9b04d6..a693c71e6e 100644 --- a/src/plugins/qt4projectmanager/qt-s60/qt-s60.pri +++ b/src/plugins/qt4projectmanager/qt-s60/qt-s60.pri @@ -67,4 +67,6 @@ HEADERS += $$PWD/s60devices.h \ FORMS += $$PWD/s60devicespreferencepane.ui \ $$PWD/s60createpackagestep.ui \ - $$PWD/s60certificatedetailsdialog.ui + $$PWD/s60certificatedetailsdialog.ui \ + qt-s60/rvcttoolchainconfigwidget.ui \ + qt-s60/winscwtoolchainconfigwidget.ui diff --git a/src/plugins/qt4projectmanager/qt-s60/qt4symbiantarget.cpp b/src/plugins/qt4projectmanager/qt-s60/qt4symbiantarget.cpp index 2d378f8847..1c5a7254bd 100644 --- a/src/plugins/qt4projectmanager/qt-s60/qt4symbiantarget.cpp +++ b/src/plugins/qt4projectmanager/qt-s60/qt4symbiantarget.cpp @@ -39,8 +39,9 @@ #include "qt-s60/s60devicerunconfiguration.h" #include <coreplugin/coreconstants.h> -#include <projectexplorer/project.h> #include <projectexplorer/customexecutablerunconfiguration.h> +#include <projectexplorer/project.h> +#include <projectexplorer/toolchainmanager.h> #include <symbianutils/symbiandevicemanager.h> #include <QtGui/QPainter> #include <QtGui/QApplication> @@ -96,30 +97,24 @@ ProjectExplorer::DeployConfigurationFactory *Qt4SymbianTarget::deployConfigurati return m_deployConfigurationFactory; } -QList<ProjectExplorer::ToolChainType> Qt4SymbianTarget::filterToolChainTypes(const QList<ProjectExplorer::ToolChainType> &candidates) const +QList<ProjectExplorer::ToolChain *> Qt4SymbianTarget::possibleToolChains(ProjectExplorer::BuildConfiguration *bc) const { - QList<ProjectExplorer::ToolChainType> tmp(candidates); + QList<ProjectExplorer::ToolChain *> candidates = Qt4BaseTarget::possibleToolChains(bc); + + QList<ProjectExplorer::ToolChain *> tmp; if (id() == QLatin1String(Constants::S60_EMULATOR_TARGET_ID)) { - if (tmp.contains(ProjectExplorer::ToolChain_WINSCW)) - return QList<ProjectExplorer::ToolChainType>() << ProjectExplorer::ToolChain_WINSCW; - else - return QList<ProjectExplorer::ToolChainType>(); + foreach (ProjectExplorer::ToolChain *tc, candidates) { + if (tc->id().startsWith(QLatin1String(Constants::WINSCW_TOOLCHAIN_ID))) + tmp.append(tc); + } } else if (id() == QLatin1String(Constants::S60_DEVICE_TARGET_ID)) { - tmp.removeAll(ProjectExplorer::ToolChain_WINSCW); - return tmp; + foreach (ProjectExplorer::ToolChain *tc, candidates) { + if (!tc->id().startsWith(Qt4ProjectManager::Constants::WINSCW_TOOLCHAIN_ID)) + tmp.append(tc); + } } - return tmp; -} -ProjectExplorer::ToolChainType Qt4SymbianTarget::preferredToolChainType(const QList<ProjectExplorer::ToolChainType> &candidates) const -{ - ProjectExplorer::ToolChainType preferredType = ProjectExplorer::ToolChain_INVALID; - if (id() == QLatin1String(Constants::S60_EMULATOR_TARGET_ID) && - candidates.contains(ProjectExplorer::ToolChain_WINSCW)) - preferredType = ProjectExplorer::ToolChain_WINSCW; - if (!candidates.isEmpty()) - preferredType = candidates.at(0); - return preferredType; + return tmp; } QString Qt4SymbianTarget::defaultBuildDirectory() const diff --git a/src/plugins/qt4projectmanager/qt-s60/qt4symbiantarget.h b/src/plugins/qt4projectmanager/qt-s60/qt4symbiantarget.h index cbfc3aebcd..110aba55ab 100644 --- a/src/plugins/qt4projectmanager/qt-s60/qt4symbiantarget.h +++ b/src/plugins/qt4projectmanager/qt-s60/qt4symbiantarget.h @@ -54,8 +54,7 @@ public: Internal::Qt4BuildConfigurationFactory *buildConfigurationFactory() const; ProjectExplorer::DeployConfigurationFactory *deployConfigurationFactory() const; - QList<ProjectExplorer::ToolChainType> filterToolChainTypes(const QList<ProjectExplorer::ToolChainType> &candidates) const; - ProjectExplorer::ToolChainType preferredToolChainType(const QList<ProjectExplorer::ToolChainType> &candidates) const; + QList<ProjectExplorer::ToolChain *> possibleToolChains(ProjectExplorer::BuildConfiguration *bc) const; QString defaultBuildDirectory() const; diff --git a/src/plugins/qt4projectmanager/qt-s60/rvcttoolchain.cpp b/src/plugins/qt4projectmanager/qt-s60/rvcttoolchain.cpp index fe681c802f..370807e295 100644 --- a/src/plugins/qt4projectmanager/qt-s60/rvcttoolchain.cpp +++ b/src/plugins/qt4projectmanager/qt-s60/rvcttoolchain.cpp @@ -33,178 +33,133 @@ #include "rvcttoolchain.h" #include "rvctparser.h" +#include "ui_rvcttoolchainconfigwidget.h" +#include "qt4projectmanager/qt4projectmanagerconstants.h" -#include <utils/qtcassert.h> +#include <utils/environment.h> +#include <utils/environmentmodel.h> #include <utils/synchronousprocess.h> -#include <QtCore/QProcess> -#include <QtCore/QProcessEnvironment> -#include <QtCore/QDebug> -#include <QtCore/QFileInfo> #include <QtCore/QDir> +#include <QtCore/QFileInfo> +#include <QtCore/QProcess> +#include <QtGui/QGridLayout> +#include <QtGui/QLabel> -using namespace ProjectExplorer; -using namespace Qt4ProjectManager::Internal; - -static const char rvctBinaryC[] = "armcc"; +namespace Qt4ProjectManager { +namespace Internal { -static inline QStringList headerPathToStringList(const QList<ProjectExplorer::HeaderPath> &hl) -{ - QStringList rc; - foreach (const ProjectExplorer::HeaderPath &hp, hl) - rc.push_back(hp.path()); - return rc; -} +#if defined Q_OS_WIN +static const char *const RVCT_BINARY = "armcc.exe"; +#else +static const char *const RVCT_BINARY = "armcc"; +#endif -// ========================================================================== -// RVCTToolChain -// ========================================================================== +static const char *const RVCT_LICENSE_KEY = "ARMLMD_LICENSE_FILE"; -RVCTToolChain::RVCTToolChain(const S60Devices::Device &device, ProjectExplorer::ToolChainType type) : - m_mixin(device), - m_type(type), - m_versionUpToDate(false), - m_major(0), - m_minor(0), - m_build(0) -{ -} +static const char *const RVCT_PATH_KEY = "Qt4ProjectManager.RvctToolChain.CompilerPath"; +static const char *const RVCT_ENVIRONMENT_KEY = "Qt4ProjectManager.RvctToolChain.Environment"; +static const char *const RVCT_ARM_VERSION_KEY = "Qt4ProjectManager.RvctToolChain.ArmVersion"; -QSet<QPair<int, int> > RVCTToolChain::configuredRvctVersions() +static QString valueOf(const QList<Utils::EnvironmentItem> &items, const QString &suffix) { - static QSet<QPair<int, int> > result; - - if (result.isEmpty()) { - QRegExp regex(QLatin1String("^RVCT(\\d)(\\d)BIN=.*$")); - Q_ASSERT(regex.isValid()); - QStringList environment = QProcessEnvironment::systemEnvironment().toStringList(); - foreach (const QString &v, environment) { - if (regex.exactMatch(v)) { - int major = regex.cap(1).toInt(); - int minor = regex.cap(2).toInt(); - result.insert(qMakePair(major, minor)); - } - } + foreach (const Utils::EnvironmentItem &i, items) { + if (i.name.mid(6) == suffix && !i.unset) + return i.value; } - return result; + return QString(); } -QStringList RVCTToolChain::configuredEnvironment() +static QString armVersionString(RvctToolChain::ArmVersion av) { - updateVersion(); - - if (m_additionalEnvironment.isEmpty()) { - const QString binVarName = QString::fromLocal8Bit(rvctBinEnvironmentVariable()); - const QString varName = binVarName.left(binVarName.count() - 3 /* BIN */); - QStringList environment = QProcessEnvironment::systemEnvironment().toStringList(); - foreach (const QString &v, environment) { - if ((v.startsWith(varName) && !v.startsWith(binVarName)) - || v.startsWith(QLatin1String("ARMLMD_LICENSE_FILE="))) { - m_additionalEnvironment.append(v); - } - } - } - return m_additionalEnvironment; + switch (av) { + case RvctToolChain::ARMv5: + return RvctToolChainFactory::tr("ARMv5"); + case RvctToolChain::ARMv6: + return RvctToolChainFactory::tr("ARMv6"); + }; + return QString(); } -// Return the environment variable indicating the RVCT version -// 'RVCT<major><minor>BIN' -QByteArray RVCTToolChain::rvctBinEnvironmentVariableForVersion(int major) +static Utils::Environment baseEnvironment(RvctToolChain *tc) { - QSet<QPair<int, int> > versions = configuredRvctVersions(); - - for (QSet<QPair<int, int> >::const_iterator it = versions.constBegin(); - it != versions.constEnd(); ++it) { - if (it->first == major) { - if (it->first < 0 || it->first > 9) continue; - if (it->second < 0 || it->second > 9) continue; - QByteArray result = "RVCT..BIN"; - result[4] = '0' + it->first; - result[5] = '0' + it->second; - return result; - } - } - return QByteArray(); + Utils::Environment result; + tc->addToEnvironment(result); + return result; } -QString RVCTToolChain::rvctBinPath() -{ - if (m_binPath.isEmpty()) { - const QByteArray binVar = rvctBinEnvironmentVariable(); - if (!binVar.isEmpty()) { - const QByteArray binPathB = qgetenv(binVar); - if (!binPathB.isEmpty()) { - const QFileInfo fi(QString::fromLocal8Bit(binPathB)); - if (fi.isDir()) - m_binPath = fi.absoluteFilePath(); - } - } - } - return m_binPath; -} +// ========================================================================== +// RvctToolChain +// ========================================================================== -// Return binary expanded by path or resort to PATH -QString RVCTToolChain::rvctBinary() -{ - QString executable = QLatin1String(rvctBinaryC); -#ifdef Q_OS_WIN - executable += QLatin1String(".exe"); -#endif - const QString binPath = rvctBinPath(); - return binPath.isEmpty() ? executable : (binPath + QLatin1Char('/') + executable); -} +RvctToolChain::RvctToolChain(bool autodetected) : + ToolChain(QLatin1String(Constants::RVCT_TOOLCHAIN_ID), autodetected), + m_armVersion(ARMv5) +{ } -ProjectExplorer::ToolChainType RVCTToolChain::type() const -{ - return m_type; -} +RvctToolChain::RvctToolChain(const RvctToolChain &tc) : + ToolChain(tc), + m_compilerPath(tc.m_compilerPath), + m_environmentChanges(tc.m_environmentChanges), + m_armVersion(tc.m_armVersion) +{ } -void RVCTToolChain::updateVersion() +RvctToolChain::RvctVersion RvctToolChain::version(const QString &rvctPath) { - if (m_versionUpToDate) - return; + RvctToolChain::RvctVersion v; - m_versionUpToDate = true; - m_major = 0; - m_minor = 0; - m_build = 0; QProcess armcc; - Utils::Environment env = Utils::Environment::systemEnvironment(); - addToEnvironment(env); - armcc.setEnvironment(env.toStringList()); - const QString binary = rvctBinary(); + const QString binary = rvctPath; armcc.start(binary, QStringList()); if (!armcc.waitForStarted()) { qWarning("Unable to run rvct binary '%s' when trying to determine version.", qPrintable(binary)); - return; + return v; } armcc.closeWriteChannel(); if (!armcc.waitForFinished()) { Utils::SynchronousProcess::stopProcess(armcc); qWarning("Timeout running rvct binary '%s' trying to determine version.", qPrintable(binary)); - return; + return v; } if (armcc.exitStatus() != QProcess::NormalExit) { qWarning("A crash occurred when running rvct binary '%s' trying to determine version.", qPrintable(binary)); - return; + return v; } QString versionLine = QString::fromLocal8Bit(armcc.readAllStandardOutput()); versionLine += QString::fromLocal8Bit(armcc.readAllStandardError()); const QRegExp versionRegExp(QLatin1String("RVCT(\\d*)\\.(\\d*).*\\[Build.(\\d*)\\]"), Qt::CaseInsensitive); - QTC_ASSERT(versionRegExp.isValid(), return); + Q_ASSERT(versionRegExp.isValid()); + if (versionRegExp.indexIn(versionLine) != -1) { - m_major = versionRegExp.cap(1).toInt(); - m_minor = versionRegExp.cap(2).toInt(); - m_build = versionRegExp.cap(3).toInt(); + v.majorVersion = versionRegExp.cap(1).toInt(); + v.minorVersion = versionRegExp.cap(2).toInt(); + v.build = versionRegExp.cap(3).toInt(); } + return v; +} + +QString RvctToolChain::typeName() const +{ + return RvctToolChainFactory::tr("RVCT"); +} + +ProjectExplorer::Abi RvctToolChain::targetAbi() const +{ + return ProjectExplorer::Abi(ProjectExplorer::Abi::ARM, ProjectExplorer::Abi::Symbian, + ProjectExplorer::Abi::Symbian_device, ProjectExplorer::Abi::Format_ELF, + 32); } -QByteArray RVCTToolChain::predefinedMacros() +bool RvctToolChain::isValid() const +{ + return !m_compilerPath.isEmpty(); +} + +QByteArray RvctToolChain::predefinedMacros() const { // see http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0205f/Babbacdb.html (version 2.2) // and http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0491b/BABJFEFG.html (version 4.0) - updateVersion(); QByteArray ba("#define __ARRAY_OPERATORS\n" "#define _BOOL\n" "#define __cplusplus\n" @@ -224,101 +179,36 @@ QByteArray RVCTToolChain::predefinedMacros() return ba; } -QList<HeaderPath> RVCTToolChain::systemHeaderPaths() -{ - if (m_systemHeaderPaths.isEmpty()) { - updateVersion(); - QString rvctInclude = qgetenv(QString::fromLatin1("RVCT%1%2INC").arg(m_major).arg(m_minor).toLatin1()); - if (!rvctInclude.isEmpty()) - m_systemHeaderPaths.append(HeaderPath(rvctInclude, HeaderPath::GlobalHeaderPath)); - switch (m_type) { - case ProjectExplorer::ToolChain_RVCT_ARMV5_GNUPOC: - m_systemHeaderPaths += m_mixin.gnuPocRvctHeaderPaths(m_major, m_minor); - break; - default: - m_systemHeaderPaths += m_mixin.epocHeaderPaths(); - break; - } - } - return m_systemHeaderPaths; -} - -// Expand an RVCT variable, such as RVCT22BIN, by some new values -void RVCTToolChain::addToRVCTPathVariable(const QString &postfix, const QStringList &values, - Utils::Environment &env) const -{ - // get old values - const QChar separator = QLatin1Char(','); - const QString variable = QString::fromLatin1("RVCT%1%2%3").arg(m_major).arg(m_minor).arg(postfix); - const QString oldValueS = env.value(variable); - const QStringList oldValue = oldValueS.isEmpty() ? QStringList() : oldValueS.split(separator); - // merge new values - QStringList newValue = oldValue; - foreach(const QString &v, values) { - const QString normalized = QDir::toNativeSeparators(v); - if (!newValue.contains(normalized)) - newValue.push_back(normalized); - } - if (newValue != oldValue) - env.set(variable, newValue.join(QString(separator))); -} - -// Figure out lib path via -QStringList RVCTToolChain::libPaths() +QList<ProjectExplorer::HeaderPath> RvctToolChain::systemHeaderPaths() const { - const QByteArray binLocation = qgetenv(rvctBinEnvironmentVariable()); - if (binLocation.isEmpty()) - return QStringList(); - const QString pathRoot = QFileInfo(QString::fromLocal8Bit(binLocation)).path(); - QStringList rc; - rc.push_back(pathRoot + QLatin1String("/lib")); - rc.push_back(pathRoot + QLatin1String("/lib/armlib")); - return rc; + return QList<ProjectExplorer::HeaderPath>() + << ProjectExplorer::HeaderPath(valueOf(m_environmentChanges, QLatin1String("INC")), + ProjectExplorer::HeaderPath::GlobalHeaderPath); } -void RVCTToolChain::addToEnvironment(Utils::Environment &env) +void RvctToolChain::addToEnvironment(Utils::Environment &env) const { - updateVersion(); + if (m_compilerPath.isEmpty()) + return; - // Push additional configuration variables for the compiler through: - QStringList additionalVariables = configuredEnvironment(); - foreach (const QString &var, additionalVariables) { - int pos = var.indexOf(QLatin1Char('=')); - Q_ASSERT(pos >= 0); - const QString key = var.left(pos); - const QString value = var.mid(pos + 1); - env.set(key, value); - } + if (m_version.isNull()) + setVersion(version(m_compilerPath)); + if (m_version.isNull()) + return; - switch (m_type) { - case ProjectExplorer::ToolChain_RVCT_ARMV5_GNUPOC: { - m_mixin.addGnuPocToEnvironment(&env); - // setup RVCT22INC, LIB - addToRVCTPathVariable(QLatin1String("INC"), - headerPathToStringList(m_mixin.gnuPocRvctHeaderPaths(m_major, m_minor)), - env); - addToRVCTPathVariable(QLatin1String("LIB"), - libPaths() + m_mixin.gnuPocRvctLibPaths(5, true), - env); - } - break; - default: - m_mixin.addEpocToEnvironment(&env); - break; - } + env.modify(m_environmentChanges); - const QString binPath = rvctBinPath(); - env.set(rvctBinEnvironmentVariable(), QDir::toNativeSeparators(binPath)); + env.set(QLatin1String("QT_RVCT_VERSION"), QString::fromLatin1("%1.%2") + .arg(m_version.majorVersion).arg(m_version.minorVersion)); + env.set(varName(QLatin1String("BIN")), QDir::toNativeSeparators(QFileInfo(m_compilerPath).absolutePath())); // Add rvct to path and set locale to 'C' - if (!binPath.isEmpty()) - env.prependOrSetPath(binPath); + if (!m_compilerPath.isEmpty()) + env.prependOrSetPath(QFileInfo(m_compilerPath).absolutePath()); env.set(QLatin1String("LANG"), QString(QLatin1Char('C'))); - - env.set(QLatin1String("QT_RVCT_VERSION"), QString::fromLatin1("%1.%2").arg(m_major).arg(m_minor)); } -QString RVCTToolChain::makeCommand() const +QString RvctToolChain::makeCommand() const { #if defined(Q_OS_WIN) return QLatin1String("make.exe"); @@ -327,76 +217,304 @@ QString RVCTToolChain::makeCommand() const #endif } -ProjectExplorer::IOutputParser *RVCTToolChain::outputParser() const +QString RvctToolChain::defaultMakeTarget() const +{ + if (!isValid()) + return QString(); + if (m_armVersion == ARMv6) + return QLatin1String("armv6"); + return QLatin1String("armv5"); + +} + +ProjectExplorer::IOutputParser *RvctToolChain::outputParser() const { return new RvctParser; } -// ========================================================================== -// RVCT2ToolChain -// ========================================================================== +bool RvctToolChain::operator ==(const ToolChain &other) const +{ + if (!ToolChain::operator ==(other)) + return false; + const RvctToolChain *otherPtr = dynamic_cast<const RvctToolChain *>(&other); + return m_compilerPath == otherPtr->m_compilerPath + && m_environmentChanges == otherPtr->m_environmentChanges + && m_armVersion == otherPtr->m_armVersion; +} -RVCT2ToolChain::RVCT2ToolChain(const S60Devices::Device &device, ProjectExplorer::ToolChainType type) : - RVCTToolChain(device, type) -{ } +void RvctToolChain::setEnvironmentChanges(const QList<Utils::EnvironmentItem> &changes) +{ + m_environmentChanges = changes; +} + +QList<Utils::EnvironmentItem> RvctToolChain::environmentChanges() const +{ + return m_environmentChanges; +} + +void RvctToolChain::setCompilerPath(const QString &path) +{ + if (m_compilerPath == path) + return; + + m_compilerPath = path; + m_version.reset(); + updateId(); +} + +QString RvctToolChain::compilerPath() const +{ + return m_compilerPath; +} + +void RvctToolChain::setArmVersion(RvctToolChain::ArmVersion av) +{ + m_armVersion = av; +} + +RvctToolChain::ArmVersion RvctToolChain::armVersion() const +{ + return m_armVersion; +} + +void RvctToolChain::setVersion(const RvctVersion &v) const +{ + m_version = v; +} -QByteArray RVCT2ToolChain::rvctBinEnvironmentVariable() +ProjectExplorer::ToolChainConfigWidget *RvctToolChain::configurationWidget() { - return rvctBinEnvironmentVariableForVersion(2); + return new RvctToolChainConfigWidget(this); } -QByteArray RVCT2ToolChain::predefinedMacros() +ProjectExplorer::ToolChain *RvctToolChain::clone() const { - QByteArray result = RVCTToolChain::predefinedMacros(); - result.append(QString::fromLatin1("#define __arm__arm__\n" - "#define __ARMCC_VERSION %1%2%3%4\n" - "#define c_plusplus\n" - ) - .arg(m_major, 1, 10, QLatin1Char('0')) - .arg(m_minor, 1, 10, QLatin1Char('0')) - .arg("0") - .arg(m_build, 3, 10, QLatin1Char('0')).toLatin1()); + return new RvctToolChain(*this); +} + + +QVariantMap RvctToolChain::toMap() const +{ + QVariantMap result = ToolChain::toMap(); + result.insert(QLatin1String(RVCT_PATH_KEY), m_compilerPath); + QVariantMap tmp; + foreach (const Utils::EnvironmentItem &i, m_environmentChanges) + tmp.insert(i.name, i.value); + result.insert(QLatin1String(RVCT_ENVIRONMENT_KEY), tmp); + result.insert(QLatin1String(RVCT_ARM_VERSION_KEY), static_cast<int>(m_armVersion)); return result; } -bool RVCT2ToolChain::equals(const ToolChain *otherIn) const +bool RvctToolChain::fromMap(const QVariantMap &data) { - if (otherIn->type() != type()) + if (!ToolChain::fromMap(data)) return false; - const RVCT2ToolChain *other = static_cast<const RVCT2ToolChain *>(otherIn); - return other->m_mixin == m_mixin; + m_compilerPath = data.value(QLatin1String(RVCT_PATH_KEY)).toString(); + + m_environmentChanges.clear(); + QVariantMap tmp = data.value(QLatin1String(RVCT_ENVIRONMENT_KEY)).toMap(); + for (QVariantMap::const_iterator i = tmp.constBegin(); i != tmp.constEnd(); ++i) + m_environmentChanges.append(Utils::EnvironmentItem(i.key(), i.value().toString())); + m_armVersion = static_cast<ArmVersion>(data.value(QLatin1String(RVCT_ARM_VERSION_KEY), 0).toInt()); + + return isValid(); +} + +void RvctToolChain::updateId() +{ + setId(QString::fromLatin1("%1:%2").arg(Constants::RVCT_TOOLCHAIN_ID).arg(m_compilerPath)); +} + +QString RvctToolChain::varName(const QString &postFix) const +{ + return QString::fromLatin1("RVCT%1%2%3") + .arg(m_version.majorVersion).arg(m_version.minorVersion).arg(postFix); } // ========================================================================== -// RVCT4ToolChain +// RvctToolChainConfigWidget // ========================================================================== -RVCT4ToolChain::RVCT4ToolChain(const S60Devices::Device &device, - ProjectExplorer::ToolChainType type) : - RVCT2ToolChain(device, type) -{ } +RvctToolChainConfigWidget::RvctToolChainConfigWidget(RvctToolChain *tc) : + ProjectExplorer::ToolChainConfigWidget(tc), + m_ui(new Ui::RvctToolChainConfigWidget()), + m_model(new Utils::EnvironmentModel(this)) +{ + m_ui->setupUi(this); + + m_ui->environmentView->setModel(m_model); + m_ui->environmentView->horizontalHeader()->setResizeMode(QHeaderView::ResizeToContents); + m_ui->environmentView->horizontalHeader()->setStretchLastSection(true); + connect(m_model, SIGNAL(userChangesChanged()), this, SLOT(makeDirty())); + + m_ui->compilerPath->setExpectedKind(Utils::PathChooser::ExistingCommand); + m_ui->compilerPath->setPath(tc->compilerPath()); + connect(m_ui->compilerPath, SIGNAL(changed(QString)), this, SLOT(makeDirty())); + m_ui->versionComboBox->setCurrentIndex(static_cast<int>(tc->armVersion())); + connect(m_ui->versionComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(makeDirty())); + + discard(); +} + +void RvctToolChainConfigWidget::apply() +{ + RvctToolChain *tc = static_cast<RvctToolChain *>(toolChain()); + Q_ASSERT(tc); + + QList<Utils::EnvironmentItem> changes = environmentChanges(); + tc->setCompilerPath(m_ui->compilerPath->path()); + tc->setArmVersion(static_cast<RvctToolChain::ArmVersion>(m_ui->versionComboBox->currentIndex())); + tc->setEnvironmentChanges(changes); + + m_model->setUserChanges(changes); +} + +void RvctToolChainConfigWidget::discard() +{ + RvctToolChain *tc = static_cast<RvctToolChain *>(toolChain()); + Q_ASSERT(tc); + + m_model->setBaseEnvironment(baseEnvironment(tc)); + + m_ui->compilerPath->setPath(tc->compilerPath()); + m_ui->versionComboBox->setCurrentIndex(static_cast<int>(tc->armVersion())); +} + +bool RvctToolChainConfigWidget::isDirty() const +{ + RvctToolChain *tc = static_cast<RvctToolChain *>(toolChain()); + Q_ASSERT(tc); + + return tc->compilerPath() != m_ui->compilerPath->path() + || tc->armVersion() != static_cast<RvctToolChain::ArmVersion>(m_ui->versionComboBox->currentIndex()) + || tc->environmentChanges() != environmentChanges(); +} + +void RvctToolChainConfigWidget::makeDirty() +{ + emit dirty(toolChain()); +} + +QList<Utils::EnvironmentItem> RvctToolChainConfigWidget::environmentChanges() const +{ + Utils::Environment baseEnv; + Utils::Environment resultEnv = baseEnvironment(static_cast<RvctToolChain *>(toolChain())); + resultEnv.modify(m_model->userChanges()); + return baseEnv.diff(resultEnv); +} + +// ========================================================================== +// RvctToolChainFactory +// ========================================================================== + +QString RvctToolChainFactory::displayName() const +{ + return tr("RVCT"); +} -QByteArray RVCT4ToolChain::rvctBinEnvironmentVariable() +QString RvctToolChainFactory::id() const { - return rvctBinEnvironmentVariableForVersion(4); + return QLatin1String(Constants::RVCT_TOOLCHAIN_ID); } -QByteArray RVCT4ToolChain::predefinedMacros() +QList<ProjectExplorer::ToolChain *> RvctToolChainFactory::autoDetect() { - QByteArray result = RVCTToolChain::predefinedMacros(); - result.append(QString::fromLatin1("#define __arm__\n" - "#define __ARMCC_VERSION %1%2%3\n") - .arg(m_major, 1, 10, QLatin1Char('0')) - .arg(m_minor, 1, 10, QLatin1Char('0')) - .arg(m_build, 3, 10, QLatin1Char('0')).toLatin1()); + Utils::Environment env = Utils::Environment::systemEnvironment(); + + QMap<QString, QList<Utils::EnvironmentItem> > rvcts; + QList<Utils::EnvironmentItem> globalItems; + + // Find all RVCT..x variables + for (Utils::Environment::const_iterator i = env.constBegin(); i != env.constEnd(); ++i) { + if (i.key() == QLatin1String(RVCT_LICENSE_KEY)) + globalItems.append(Utils::EnvironmentItem(i.key(), i.value())); + if (!i.key().startsWith(QLatin1String("RVCT"))) + continue; + + const QString key = i.key().left(6); + QList<Utils::EnvironmentItem> values = rvcts.value(key); + + values.append(Utils::EnvironmentItem(i.key(), i.value())); + + rvcts.insert(key, values); + } + + // Set up toolchains for each RVCT.. set + QList<ProjectExplorer::ToolChain *> result; + for (QMap<QString, QList<Utils::EnvironmentItem> >::const_iterator i = rvcts.constBegin(); + i != rvcts.constEnd(); ++i) { + QList<Utils::EnvironmentItem> changes = i.value(); + changes.append(globalItems); + + QString binary = QDir::fromNativeSeparators(valueOf(changes, QLatin1String("BIN"))); + if (binary.isEmpty()) + continue; + binary = binary + QLatin1Char('/') + RVCT_BINARY; + QFileInfo fi(binary); + if (!fi.exists() || !fi.isExecutable()) + continue; + + RvctToolChain::RvctVersion v = RvctToolChain::version(binary); + if (v.majorVersion == 0 && v.minorVersion == 0 && v.build == 0) + continue; // Failed to start. + + //: %1 arm version, %2 major version, %3 minor version, %4 build number + const QString name = tr("RVCT (%1 %2.%3 Build %4)"); + + RvctToolChain *tc = new RvctToolChain(true); + tc->setCompilerPath(binary); + tc->setEnvironmentChanges(changes); + tc->setDisplayName(name.arg(armVersionString(tc->armVersion())) + .arg(v.majorVersion).arg(v.minorVersion).arg(v.build)); + tc->setVersion(v); + result.append(tc); + + tc = new RvctToolChain(true); + tc->setCompilerPath(binary); + tc->setEnvironmentChanges(changes); + tc->setArmVersion(RvctToolChain::ARMv6); + tc->setDisplayName(name.arg(armVersionString(tc->armVersion())) + .arg(v.majorVersion).arg(v.minorVersion).arg(v.build)); + tc->setVersion(v); + result.append(tc); + } + return result; } +bool RvctToolChainFactory::canCreate() +{ + return true; +} -bool RVCT4ToolChain::equals(const ToolChain *otherIn) const +ProjectExplorer::ToolChain *RvctToolChainFactory::create() { - if (otherIn->type() != type()) - return false; - const RVCT4ToolChain *other = static_cast<const RVCT4ToolChain *>(otherIn); - return other->m_mixin == m_mixin; + RvctToolChain *tc = new RvctToolChain(false); + Utils::Environment env = Utils::Environment::systemEnvironment(); + if (env.hasKey(QLatin1String(RVCT_LICENSE_KEY))) { + tc->setEnvironmentChanges(QList<Utils::EnvironmentItem>() + << Utils::EnvironmentItem(QLatin1String(RVCT_LICENSE_KEY), + env.value(QLatin1String(RVCT_LICENSE_KEY)))); + } + tc->setDisplayName(tr("RVCT")); + return tc; } + +bool RvctToolChainFactory::canRestore(const QVariantMap &data) +{ + return idFromMap(data).startsWith(QLatin1String(Constants::RVCT_TOOLCHAIN_ID)); +} + +ProjectExplorer::ToolChain *RvctToolChainFactory::restore(const QVariantMap &data) +{ + RvctToolChain *tc = new RvctToolChain(false); + if (tc->fromMap(data)) + return tc; + + delete tc; + return 0; + +} + +} // Internal +} // Qt4ProjectManager diff --git a/src/plugins/qt4projectmanager/qt-s60/rvcttoolchain.h b/src/plugins/qt4projectmanager/qt-s60/rvcttoolchain.h index 2294212d20..fb7ce3c26b 100644 --- a/src/plugins/qt4projectmanager/qt-s60/rvcttoolchain.h +++ b/src/plugins/qt4projectmanager/qt-s60/rvcttoolchain.h @@ -34,97 +34,141 @@ #ifndef RVCTTOOLCHAIN_H #define RVCTTOOLCHAIN_H -#include "s60devices.h" - #include <projectexplorer/toolchain.h> +#include <projectexplorer/toolchainconfigwidget.h> +#include <utils/environment.h> + +namespace Utils { +class EnvironmentModel; +class PathChooser; +} // namespace Utils namespace Qt4ProjectManager { namespace Internal { +namespace Ui { +class RvctToolChainConfigWidget; +} + +class RvctToolChainFactory; + // ========================================================================== -// RVCTToolChain +// RvctToolChain // ========================================================================== -class RVCTToolChain : public ProjectExplorer::ToolChain +class RvctToolChain : public ProjectExplorer::ToolChain { public: - explicit RVCTToolChain(const S60Devices::Device &device, - ProjectExplorer::ToolChainType type); - QByteArray predefinedMacros(); - QList<ProjectExplorer::HeaderPath> systemHeaderPaths(); - void addToEnvironment(Utils::Environment &env); - ProjectExplorer::ToolChainType type() const; + struct RvctVersion { + RvctVersion() : majorVersion(0), minorVersion(0), build(0) + { } + + bool isNull() { return majorVersion == 0 && minorVersion == 0 && build == 0; } + void reset() { majorVersion = 0; minorVersion = 0; build = 0; } + + int majorVersion; + int minorVersion; + int build; + }; + + static RvctVersion version(const QString &rvctPath); + + enum ArmVersion { ARMv5, ARMv6 }; + + QString typeName() const; + ProjectExplorer::Abi targetAbi() const; + + bool isValid() const; + + QByteArray predefinedMacros() const; + QList<ProjectExplorer::HeaderPath> systemHeaderPaths() const; + void addToEnvironment(Utils::Environment &env) const; QString makeCommand() const; + QString defaultMakeTarget() const; ProjectExplorer::IOutputParser *outputParser() const; - static QSet<QPair<int, int> > configuredRvctVersions(); + bool operator ==(const ToolChain &) const; - // Return the environment variable indicating the RVCT version - // 'RVCT2<minor>BIN' and its setting - virtual QByteArray rvctBinEnvironmentVariable() = 0; + void setEnvironmentChanges(const QList<Utils::EnvironmentItem> &changes); + QList<Utils::EnvironmentItem> environmentChanges() const; - QString rvctBinPath(); - QString rvctBinary(); + void setCompilerPath(const QString &path); + QString compilerPath() const; -protected: - bool equals(const ToolChain *other) const = 0; + void setArmVersion(ArmVersion); + ArmVersion armVersion() const; - QStringList configuredEnvironment(); + void setVersion(const RvctVersion &v) const; - QByteArray rvctBinEnvironmentVariableForVersion(int major); - void addToRVCTPathVariable(const QString &postfix, const QStringList &values, - Utils::Environment &env) const; - QStringList libPaths(); - void updateVersion(); + ProjectExplorer::ToolChainConfigWidget *configurationWidget(); + ProjectExplorer::ToolChain *clone() const; - QByteArray m_predefinedMacros; - QList<ProjectExplorer::HeaderPath> m_systemHeaderPaths; - - const S60ToolChainMixin m_mixin; - const ProjectExplorer::ToolChainType m_type; - bool m_versionUpToDate; - int m_major; - int m_minor; - int m_build; + QVariantMap toMap() const; + bool fromMap(const QVariantMap &data); private: - QString m_binPath; - QStringList m_additionalEnvironment; + void updateId(); + + explicit RvctToolChain(bool autodetected = false); + RvctToolChain(const RvctToolChain &); + + QString varName(const QString &postFix) const; + + QList<ProjectExplorer::HeaderPath> m_systemHeaderPaths; + QString m_compilerPath; + QList<Utils::EnvironmentItem> m_environmentChanges; + ArmVersion m_armVersion; + mutable RvctVersion m_version; + + friend class RvctToolChainFactory; }; // ========================================================================== -// RVCT2ToolChain +// RvctToolChainConfigWidget // ========================================================================== -class RVCT2ToolChain : public RVCTToolChain +class RvctToolChainConfigWidget : public ProjectExplorer::ToolChainConfigWidget { + Q_OBJECT + public: - explicit RVCT2ToolChain(const S60Devices::Device &device, - ProjectExplorer::ToolChainType type); - QByteArray rvctBinEnvironmentVariable(); + RvctToolChainConfigWidget(RvctToolChain *tc); + + void apply(); + void discard(); + bool isDirty() const; - QByteArray predefinedMacros(); +private slots: + void makeDirty(); -protected: - bool equals(const ToolChain *other) const; +private: + QList<Utils::EnvironmentItem> environmentChanges() const; + + Ui::RvctToolChainConfigWidget *m_ui; + Utils::EnvironmentModel *m_model; }; // ========================================================================== -// RVCT4ToolChain +// RvctToolChainFactory // ========================================================================== -class RVCT4ToolChain : public RVCT2ToolChain +class RvctToolChainFactory : public ProjectExplorer::ToolChainFactory { + Q_OBJECT + public: - explicit RVCT4ToolChain(const S60Devices::Device &device, - ProjectExplorer::ToolChainType type); + // Name used to display the name of the toolchain that will be created. + QString displayName() const; + QString id() const; - QByteArray rvctBinEnvironmentVariable(); + QList<ProjectExplorer::ToolChain *> autoDetect(); - QByteArray predefinedMacros(); + bool canCreate(); + ProjectExplorer::ToolChain *create(); -protected: - bool equals(const ToolChain *other) const; + // Used by the ToolChainManager to restore user-generated ToolChains + bool canRestore(const QVariantMap &data); + ProjectExplorer::ToolChain *restore(const QVariantMap &data); }; } // namespace Internal diff --git a/src/plugins/qt4projectmanager/qt-s60/rvcttoolchainconfigwidget.ui b/src/plugins/qt4projectmanager/qt-s60/rvcttoolchainconfigwidget.ui new file mode 100644 index 0000000000..e2eded3ab5 --- /dev/null +++ b/src/plugins/qt4projectmanager/qt-s60/rvcttoolchainconfigwidget.ui @@ -0,0 +1,85 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>Qt4ProjectManager::Internal::RvctToolChainConfigWidget</class> + <widget class="QWidget" name="Qt4ProjectManager::Internal::RvctToolChainConfigWidget"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>432</width> + <height>173</height> + </rect> + </property> + <property name="windowTitle"> + <string>Form</string> + </property> + <layout class="QGridLayout" name="gridLayout"> + <item row="0" column="0"> + <widget class="QLabel" name="label"> + <property name="text"> + <string>Compiler path:</string> + </property> + </widget> + </item> + <item row="0" column="1"> + <widget class="Utils::PathChooser" name="compilerPath"/> + </item> + <item row="1" column="0"> + <widget class="QLabel" name="label_2"> + <property name="text"> + <string>ARM version:</string> + </property> + </widget> + </item> + <item row="1" column="1"> + <widget class="QComboBox" name="versionComboBox"> + <item> + <property name="text"> + <string>Version 5</string> + </property> + </item> + <item> + <property name="text"> + <string>Version 6</string> + </property> + </item> + </widget> + </item> + <item row="2" column="0" colspan="2"> + <spacer name="verticalSpacer"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::Fixed</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>0</width> + <height>3</height> + </size> + </property> + </spacer> + </item> + <item row="3" column="0" colspan="2"> + <widget class="QLabel" name="label_3"> + <property name="text"> + <string>Environment variables:</string> + </property> + </widget> + </item> + <item row="4" column="0" colspan="2"> + <widget class="QTableView" name="environmentView"/> + </item> + </layout> + </widget> + <customwidgets> + <customwidget> + <class>Utils::PathChooser</class> + <extends>QLineEdit</extends> + <header>utils/pathchooser.h</header> + </customwidget> + </customwidgets> + <resources/> + <connections/> +</ui> diff --git a/src/plugins/qt4projectmanager/qt-s60/s60deployconfiguration.cpp b/src/plugins/qt4projectmanager/qt-s60/s60deployconfiguration.cpp index e3f8b5fd8d..4dd5ed7bb7 100644 --- a/src/plugins/qt4projectmanager/qt-s60/s60deployconfiguration.cpp +++ b/src/plugins/qt4projectmanager/qt-s60/s60deployconfiguration.cpp @@ -33,6 +33,7 @@ #include "s60deployconfiguration.h" #include "s60deployconfigurationwidget.h" +#include "s60manager.h" #include "qt4project.h" #include "qt4target.h" #include "qt4projectmanagerconstants.h" @@ -47,6 +48,7 @@ #include <projectexplorer/buildconfiguration.h> #include <projectexplorer/buildsteplist.h> #include <projectexplorer/project.h> +#include <projectexplorer/toolchain.h> #include <QtCore/QFileInfo> @@ -182,7 +184,7 @@ QStringList S60DeployConfiguration::packageFileNamesWithTargetInfo() const QString baseFileName = ti.buildDir + QLatin1Char('/') + ti.target; baseFileName += QLatin1Char('_') + (isDebug() ? QLatin1String("debug") : QLatin1String("release")) - + QLatin1Char('-') + symbianPlatform() + QLatin1String(".sis"); + + QLatin1Char('-') + S60Manager::platform(qt4Target()->activeBuildConfiguration()->toolChain()) + QLatin1String(".sis"); result << baseFileName; } return result; @@ -246,26 +248,11 @@ bool S60DeployConfiguration::isSigned() const return false; } -ProjectExplorer::ToolChainType S60DeployConfiguration::toolChainType() const +ProjectExplorer::ToolChain *S60DeployConfiguration::toolChain() const { if (Qt4BuildConfiguration *bc = qobject_cast<Qt4BuildConfiguration *>(target()->activeBuildConfiguration())) - return bc->toolChainType(); - return ProjectExplorer::ToolChain_INVALID; -} - -QString S60DeployConfiguration::symbianPlatform() const -{ - const Qt4BuildConfiguration *qt4bc = qt4Target()->activeBuildConfiguration(); - switch (qt4bc->toolChainType()) { - case ProjectExplorer::ToolChain_GCCE: - case ProjectExplorer::ToolChain_GCCE_GNUPOC: - return QLatin1String("gcce"); - case ProjectExplorer::ToolChain_RVCT2_ARMV5: - case ProjectExplorer::ToolChain_RVCT4_ARMV5: - return QLatin1String("armv5"); - default: // including ProjectExplorer::RVCT_ARMV6_GNUPOC: - return QLatin1String("armv6"); - } + return bc->toolChain(); + return 0; } bool S60DeployConfiguration::isDebug() const diff --git a/src/plugins/qt4projectmanager/qt-s60/s60deployconfiguration.h b/src/plugins/qt4projectmanager/qt-s60/s60deployconfiguration.h index 8efedf6ce0..d57f4dd1f5 100644 --- a/src/plugins/qt4projectmanager/qt-s60/s60deployconfiguration.h +++ b/src/plugins/qt4projectmanager/qt-s60/s60deployconfiguration.h @@ -35,11 +35,11 @@ #define S60DEPLOYCONFIGURATION_H #include <projectexplorer/deployconfiguration.h> -#include <projectexplorer/toolchaintype.h> namespace ProjectExplorer { class BuildConfiguration; class RunConfiguration; +class ToolChain; } namespace Qt4ProjectManager { @@ -72,7 +72,7 @@ public: const QtVersion *qtVersion() const; Qt4SymbianTarget *qt4Target() const; - ProjectExplorer::ToolChainType toolChainType() const; + ProjectExplorer::ToolChain *toolChain() const; QString serialPortName() const; void setSerialPortName(const QString &name); @@ -120,7 +120,6 @@ protected: private: void ctor(); bool isSigned() const; - QString symbianPlatform() const; QString symbianTarget() const; QString createPackageName(const QString &baseName) const; bool isDebug() const; diff --git a/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.cpp b/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.cpp index ae9a6614cc..bcce8710bb 100644 --- a/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.cpp +++ b/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.cpp @@ -155,39 +155,16 @@ Qt4SymbianTarget *S60DeviceRunConfiguration::qt4Target() const return static_cast<Qt4SymbianTarget *>(target()); } -ProjectExplorer::ToolChainType S60DeviceRunConfiguration::toolChainType( - ProjectExplorer::BuildConfiguration *configuration) const -{ - if (Qt4BuildConfiguration *bc = qobject_cast<Qt4BuildConfiguration *>(configuration)) - return bc->toolChainType(); - return ProjectExplorer::ToolChain_INVALID; -} - -ProjectExplorer::ToolChainType S60DeviceRunConfiguration::toolChainType() const -{ - if (Qt4BuildConfiguration *bc = qobject_cast<Qt4BuildConfiguration *>(target()->activeBuildConfiguration())) - return bc->toolChainType(); - return ProjectExplorer::ToolChain_INVALID; -} - bool S60DeviceRunConfiguration::isEnabled(ProjectExplorer::BuildConfiguration *configuration) const { if (!m_validParse) return false; - const Qt4BuildConfiguration *qt4bc = static_cast<const Qt4BuildConfiguration *>(configuration); - switch (qt4bc->toolChainType()) { - case ProjectExplorer::ToolChain_GCCE: - case ProjectExplorer::ToolChain_RVCT2_ARMV5: - case ProjectExplorer::ToolChain_RVCT2_ARMV6: - case ProjectExplorer::ToolChain_RVCT4_ARMV5: - case ProjectExplorer::ToolChain_RVCT4_ARMV6: - case ProjectExplorer::ToolChain_GCCE_GNUPOC: - case ProjectExplorer::ToolChain_RVCT_ARMV5_GNUPOC: - return true; - default: - break; - } - return false; + + Q_ASSERT(configuration->target() == target()); + Q_ASSERT(target()->id() == Constants::S60_DEVICE_TARGET_ID); + + const Qt4BuildConfiguration *qt4bc = qobject_cast<const Qt4BuildConfiguration *>(configuration); + return qt4bc && qt4bc->toolChain(); } QWidget *S60DeviceRunConfiguration::createConfigurationWidget() @@ -266,21 +243,6 @@ QString S60DeviceRunConfiguration::symbianTarget() const return isDebug() ? QLatin1String("udeb") : QLatin1String("urel"); } -static inline QString symbianPlatformForToolChain(ProjectExplorer::ToolChainType t) -{ - switch (t) { - case ProjectExplorer::ToolChain_GCCE: - case ProjectExplorer::ToolChain_GCCE_GNUPOC: - return QLatin1String("gcce"); - case ProjectExplorer::ToolChain_RVCT2_ARMV5: - case ProjectExplorer::ToolChain_RVCT4_ARMV5: - return QLatin1String("armv5"); - default: // including ProjectExplorer::RVCT_ARMV6_GNUPOC: - break; - } - return QLatin1String("armv6"); -} - /* Grep a package file for the '.exe' file. Currently for use on Linux only * as the '.pkg'-files on Windows do not contain drive letters, which is not * handled here. \code @@ -313,47 +275,35 @@ static inline QString executableFromPackageUnix(const QString &packageFileName) static inline QString localExecutableFromDevice(const QtVersion *qtv, const QString &symbianTarget, /* udeb/urel */ const QString &targetName, - ProjectExplorer::ToolChainType t) + const ProjectExplorer::ToolChain *tc) { - QTC_ASSERT(qtv, return QString(); ) + Q_ASSERT(qtv); + if (!tc) + return QString(); const S60Devices::Device device = S60Manager::instance()->deviceForQtVersion(qtv); QString localExecutable; + QString platform = S60Manager::platform(tc); + if (qtv->isBuildWithSymbianSbsV2() && platform == QLatin1String("gcce")) + platform = "armv5"; QTextStream(&localExecutable) << device.epocRoot << "/epoc32/release/" - << symbianPlatformForToolChain(t) - << '/' << symbianTarget << '/' << targetName - << ".exe"; + << platform << '/' << symbianTarget << '/' << targetName << ".exe"; return localExecutable; } QString S60DeviceRunConfiguration::localExecutableFileName() const { - const ProjectExplorer::ToolChainType toolChain = toolChainType(); - switch (toolChain) { - case ProjectExplorer::ToolChain_GCCE_GNUPOC: - case ProjectExplorer::ToolChain_RVCT_ARMV5_GNUPOC: { - TargetInformation ti = qt4Target()->qt4Project()->rootProjectNode()->targetInformation(projectFilePath()); - if (!ti.valid) - return QString(); + TargetInformation ti = qt4Target()->qt4Project()->rootProjectNode()->targetInformation(projectFilePath()); + if (!ti.valid) + return QString(); + + const ProjectExplorer::Abi hostAbi = ProjectExplorer::Abi::hostAbi(); + if (hostAbi.os() == ProjectExplorer::Abi::Linux) { return executableFromPackageUnix(ti.buildDir + QLatin1Char('/') + ti.target + QLatin1String("_template.pkg")); } - case ProjectExplorer::ToolChain_RVCT2_ARMV5: - case ProjectExplorer::ToolChain_RVCT2_ARMV6: - return localExecutableFromDevice(qtVersion(), symbianTarget(), targetName(), toolChain); - break; - case ProjectExplorer::ToolChain_GCCE: { - // As of 4.7.1, qmake-gcce-Raptor builds were changed to put all executables into 'armv5' - const QtVersion *qtv = qtVersion(); - QTC_ASSERT(qtv, return QString(); ) - return qtv->isBuildWithSymbianSbsV2() ? - localExecutableFromDevice(qtv, symbianTarget(), targetName(), ProjectExplorer::ToolChain_RVCT2_ARMV5) : - localExecutableFromDevice(qtv, symbianTarget(), targetName(), toolChain); - } - break; - default: - break; - } - return QString(); + + ProjectExplorer::ToolChain *tc = qt4Target()->activeBuildConfiguration()->toolChain(); + return localExecutableFromDevice(qtVersion(), symbianTarget(), targetName(), tc); } quint32 S60DeviceRunConfiguration::executableUid() const @@ -515,7 +465,7 @@ static Debugger::DebuggerStartParameters s60DebuggerStartParams(const S60DeviceR sp.remoteChannel = activeDeployConf->serialPortName(); sp.processArgs = rc->commandLineArguments(); sp.startMode = Debugger::StartInternal; - sp.toolChainType = rc->toolChainType(); + sp.toolChainAbi = rc->abi(); sp.executable = debugFileName; sp.executableUid = rc->executableUid(); sp.enabledEngines = Debugger::GdbEngineType; @@ -552,7 +502,7 @@ S60DeviceDebugRunControl::S60DeviceDebugRunControl(S60DeviceRunConfiguration *rc void S60DeviceDebugRunControl::start() { Debugger::ConfigurationCheck check = - Debugger::checkDebugConfiguration(startParameters().toolChainType); + Debugger::checkDebugConfiguration(startParameters().toolChainAbi); if (!check) { appendMessage(check.errorMessage, ErrorMessageFormat); diff --git a/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.h b/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.h index 81fa2d7b91..71de1644c0 100644 --- a/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.h +++ b/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.h @@ -36,7 +36,6 @@ #include <debugger/debuggerrunner.h> #include <projectexplorer/runconfiguration.h> -#include <projectexplorer/toolchaintype.h> #include <QtCore/QFutureInterface> #include <QtCore/QScopedPointer> @@ -79,8 +78,6 @@ public: QString projectFilePath() const; - ProjectExplorer::ToolChainType toolChainType() const; - QString targetName() const; QString localExecutableFileName() const; quint32 executableUid() const; @@ -103,7 +100,6 @@ private slots: void proFileUpdate(Qt4ProjectManager::Internal::Qt4ProFileNode *pro, bool success); private: - ProjectExplorer::ToolChainType toolChainType(ProjectExplorer::BuildConfiguration *configuration) const; void ctor(); void handleParserState(bool sucess); diff --git a/src/plugins/qt4projectmanager/qt-s60/s60devices.cpp b/src/plugins/qt4projectmanager/qt-s60/s60devices.cpp index 83e0b540e0..1c80ff002d 100644 --- a/src/plugins/qt4projectmanager/qt-s60/s60devices.cpp +++ b/src/plugins/qt4projectmanager/qt-s60/s60devices.cpp @@ -503,120 +503,6 @@ void GnuPocS60Devices::writeSettings() writeSdkQtAssociationSettings(Core::ICore::instance()->settings(), QLatin1String(GNUPOC_SETTINGS_GROUP)); } -// S60ToolChainMixin -S60ToolChainMixin::S60ToolChainMixin(const S60Devices::Device &d) : - m_device(d) -{ -} - -const S60Devices::Device & S60ToolChainMixin::device() const -{ - return m_device; -} - -bool S60ToolChainMixin::equals(const S60ToolChainMixin &rhs) const -{ - return m_device.id == rhs.m_device.id - && m_device.name == rhs.m_device.name; -} - -static const char *epocHeaderPathsC[] = { - "include", "mkspecs/common/symbian", "epoc32/include", - "epoc32/include/osextensions/stdapis", "epoc32/include/osextensions/stdapis/sys", - "epoc32/include/stdapis", "epoc32/include/stdapis/sys", - "epoc32/include/osextensions/stdapis/stlport", "epoc32/include/stdapis/stlport", - "epoc32/include/oem", "epoc32/include/middleware", "epoc32/include/domain/middleware", - "epoc32/include/osextensions", "epoc32/include/domain/osextensions", - "epoc32/include/domain/osextensions/loc", "epoc32/include/domain/middleware/loc", - "epoc32/include/domain/osextensions/loc/sc", "epoc32/include/domain/middleware/loc/sc" -}; - -QList<ProjectExplorer::HeaderPath> S60ToolChainMixin::epocHeaderPaths() const -{ - QList<ProjectExplorer::HeaderPath> rc; - - QString root = m_device.epocRoot + QLatin1Char('/'); - const int count = sizeof(epocHeaderPathsC) / sizeof(const char *); - for (int i = 0; i < count; ++i) - rc << ProjectExplorer::HeaderPath(root + QLatin1String(epocHeaderPathsC[i]), - ProjectExplorer::HeaderPath::GlobalHeaderPath); - return rc; -} - -void S60ToolChainMixin::addEpocToEnvironment(Utils::Environment *env) const -{ -#if defined(Q_OS_WIN) - QString winDir = QLatin1String(qgetenv("WINDIR")); - if (!winDir.isEmpty()) - env->prependOrSetPath(QDir(winDir).filePath(QLatin1String("system32"))); -#endif - - QDir epocDir(m_device.epocRoot); - - env->prependOrSetPath(epocDir.filePath(QLatin1String("epoc32/tools"))); // e.g. make.exe - - if (epocDir.exists(QLatin1String("epoc32/gcc/bin"))) - env->prependOrSetPath(epocDir.filePath(QLatin1String("epoc32/gcc/bin"))); // e.g. cpp.exe, *NOT* gcc.exe - // Find perl in the special Symbian flavour: - if (epocDir.exists(QLatin1String("../../tools/perl/bin"))) { - epocDir.cd(QLatin1String("../../tools/perl/bin")); - env->prependOrSetPath(epocDir.absolutePath()); - } else { - env->prependOrSetPath(epocDir.filePath(QLatin1String("perl/bin"))); - } - - addBaseToEnvironment(env); -} - -static const char *gnuPocHeaderPathsC[] = { - "epoc32/include", "epoc32/include/variant", "epoc32/include/stdapis", - "epoc32/include/stdapis/stlport" }; - -QList<ProjectExplorer::HeaderPath> S60ToolChainMixin::gnuPocHeaderPaths() const -{ - QList<ProjectExplorer::HeaderPath> rc; - const QString root = m_device.epocRoot + QLatin1Char('/'); - const int count = sizeof(gnuPocHeaderPathsC)/sizeof(const char *); - for (int i = 0; i < count; i++) - rc.push_back(ProjectExplorer::HeaderPath(root + QLatin1String(gnuPocHeaderPathsC[i]), - ProjectExplorer::HeaderPath::GlobalHeaderPath)); - return rc; -} - -QStringList S60ToolChainMixin::gnuPocRvctLibPaths(int armver, bool debug) const -{ - QStringList rc; - QString root; - QTextStream(&root) << m_device.epocRoot << "epoc32/release/armv" << armver << '/'; - rc.push_back(root + QLatin1String("lib")); - rc.push_back(root + (debug ? QLatin1String("udeb") : QLatin1String("urel"))); - return rc; -} - -QList<ProjectExplorer::HeaderPath> S60ToolChainMixin::gnuPocRvctHeaderPaths(int major, int minor) const -{ - // Additional header for rvct - QList<ProjectExplorer::HeaderPath> rc = gnuPocHeaderPaths(); - QString rvctHeader; - QTextStream(&rvctHeader) << m_device.epocRoot << "/epoc32/include/rvct" << major << '_' << minor; - rc.push_back(ProjectExplorer::HeaderPath(rvctHeader, ProjectExplorer::HeaderPath::GlobalHeaderPath)); - return rc; -} - -void S60ToolChainMixin::addGnuPocToEnvironment(Utils::Environment *env) const -{ - env->prependOrSetPath(QDir::toNativeSeparators(m_device.toolsRoot + QLatin1String("/epoc32/tools"))); - addBaseToEnvironment(env); -} - -void S60ToolChainMixin::addBaseToEnvironment(Utils::Environment *env) const -{ - QString epocRootPath(m_device.epocRoot); - if (!epocRootPath.endsWith(QLatin1Char('/'))) - epocRootPath.append(QLatin1Char('/')); - env->set(QLatin1String("EPOCROOT"), QDir::toNativeSeparators(S60Devices::cleanedRootPath(epocRootPath))); -} - QDebug operator<<(QDebug db, const S60Devices::Device &d) { QDebug nospace = db.nospace(); diff --git a/src/plugins/qt4projectmanager/qt-s60/s60devices.h b/src/plugins/qt4projectmanager/qt-s60/s60devices.h index ab81994630..80623c65c2 100644 --- a/src/plugins/qt4projectmanager/qt-s60/s60devices.h +++ b/src/plugins/qt4projectmanager/qt-s60/s60devices.h @@ -168,39 +168,6 @@ private: virtual void writeSettings(); }; -/* Mixin for the toolchains with convenience functions for EPOC - * (Windows) and GnuPoc (Linux). */ - -class S60ToolChainMixin { - Q_DISABLE_COPY(S60ToolChainMixin) -public: - explicit S60ToolChainMixin(const S60Devices::Device &device); - - const S60Devices::Device &device() const; - - // Epoc - QList<ProjectExplorer::HeaderPath> epocHeaderPaths() const; - void addEpocToEnvironment(Utils::Environment *env) const; - - // GnuPoc - QList<ProjectExplorer::HeaderPath> gnuPocHeaderPaths() const; - QList<ProjectExplorer::HeaderPath> gnuPocRvctHeaderPaths(int major, int minor) const; - QStringList gnuPocRvctLibPaths(int armver, bool debug) const; - void addGnuPocToEnvironment(Utils::Environment *env) const; - - void addBaseToEnvironment(Utils::Environment *env) const; - - bool equals(const S60ToolChainMixin &rhs) const; - -private: - const S60Devices::Device m_device; -}; - -inline bool operator==(const S60ToolChainMixin &s1, const S60ToolChainMixin &s2) -{ return s1.equals(s2); } -inline bool operator!=(const S60ToolChainMixin &s1, const S60ToolChainMixin &s2) -{ return !s1.equals(s2); } - QDebug operator<<(QDebug dbg, const S60Devices::Device &d); QDebug operator<<(QDebug dbg, const S60Devices &d); diff --git a/src/plugins/qt4projectmanager/qt-s60/s60emulatorrunconfiguration.cpp b/src/plugins/qt4projectmanager/qt-s60/s60emulatorrunconfiguration.cpp index a6e8728c8f..1275b7aad1 100644 --- a/src/plugins/qt4projectmanager/qt-s60/s60emulatorrunconfiguration.cpp +++ b/src/plugins/qt4projectmanager/qt-s60/s60emulatorrunconfiguration.cpp @@ -142,10 +142,11 @@ bool S60EmulatorRunConfiguration::isEnabled(ProjectExplorer::BuildConfiguration { if (!m_validParse) return false; - Qt4BuildConfiguration *qt4bc = qobject_cast<Qt4BuildConfiguration *>(configuration); - QTC_ASSERT(qt4bc, return false); - const ProjectExplorer::ToolChainType type = qt4bc->toolChainType(); - return type == ProjectExplorer::ToolChain_WINSCW; + Q_ASSERT(configuration->target() == target()); + Q_ASSERT(target()->id() == Constants::S60_EMULATOR_TARGET_ID); + + const Qt4BuildConfiguration *qt4bc = qobject_cast<const Qt4BuildConfiguration *>(configuration); + return qt4bc && qt4bc->toolChain(); } QWidget *S60EmulatorRunConfiguration::createConfigurationWidget() @@ -323,9 +324,9 @@ QStringList S60EmulatorRunConfigurationFactory::availableCreationIds(Target *par QString S60EmulatorRunConfigurationFactory::displayNameForId(const QString &id) const { - if (!pathFromId(id).isEmpty()) + if (!pathFromId(id).isEmpty()) return tr("%1 in Symbian Emulator").arg(QFileInfo(pathFromId(id)).completeBaseName()); - return QString(); + return QString(); } // ======== S60EmulatorRunControl @@ -333,9 +334,8 @@ QString S60EmulatorRunConfigurationFactory::displayNameForId(const QString &id) S60EmulatorRunControl::S60EmulatorRunControl(S60EmulatorRunConfiguration *runConfiguration, QString mode) : RunControl(runConfiguration, mode) { - // stuff like the EPOCROOT and EPOCDEVICE env variable - Utils::Environment env = Utils::Environment::systemEnvironment(); - runConfiguration->qt4Target()->activeBuildConfiguration()->toolChain()->addToEnvironment(env); + // FIXME: This should be configurable! + Utils::Environment env = runConfiguration->qt4Target()->activeBuildConfiguration()->environment(); m_applicationLauncher.setEnvironment(env); m_executable = runConfiguration->executable(); diff --git a/src/plugins/qt4projectmanager/qt-s60/s60manager.cpp b/src/plugins/qt4projectmanager/qt-s60/s60manager.cpp index c616e409a7..4c38fe58da 100644 --- a/src/plugins/qt4projectmanager/qt-s60/s60manager.cpp +++ b/src/plugins/qt4projectmanager/qt-s60/s60manager.cpp @@ -35,9 +35,6 @@ #include "qtversionmanager.h" #include "s60devicespreferencepane.h" -#include "winscwtoolchain.h" -#include "gccetoolchain.h" -#include "rvcttoolchain.h" #include "s60emulatorrunconfiguration.h" #include "s60devicerunconfiguration.h" #include "s60createpackagestep.h" @@ -46,6 +43,10 @@ #include "qt4symbiantargetfactory.h" +#include "gccetoolchain.h" +#include "rvcttoolchain.h" +#include "winscwtoolchain.h" + #include <symbianutils/symbiandevicemanager.h> #include <coreplugin/icore.h> @@ -112,25 +113,27 @@ S60Manager::S60Manager(QObject *parent) { m_instance = this; + addAutoReleasedObject(new GcceToolChainFactory); + addAutoReleasedObject(new RvctToolChainFactory); + addAutoReleasedObject(new WinscwToolChainFactory); + #ifdef QTCREATOR_WITH_S60 addAutoReleasedObject(new S60DevicesPreferencePane(m_devices, this)); #endif addAutoReleasedObject(new S60EmulatorRunConfigurationFactory); - addAutoReleasedObject(new RunControlFactory<S60EmulatorRunControl, - S60EmulatorRunConfiguration> - (QLatin1String(ProjectExplorer::Constants::RUNMODE), - tr("Run in Emulator"), parent)); + addAutoReleasedObject(new RunControlFactory<S60EmulatorRunControl, S60EmulatorRunConfiguration> + (QLatin1String(ProjectExplorer::Constants::RUNMODE), + tr("Run in Emulator"), parent)); addAutoReleasedObject(new S60DeviceRunConfigurationFactory); addAutoReleasedObject(new S60RunControlFactory(QLatin1String(ProjectExplorer::Constants::RUNMODE), tr("Run on Device"), parent)); addAutoReleasedObject(new S60CreatePackageStepFactory); addAutoReleasedObject(new S60DeployStepFactory); - addAutoReleasedObject(new RunControlFactory<S60DeviceDebugRunControl, - S60DeviceRunConfiguration> - (QLatin1String(Debugger::Constants::DEBUGMODE), - tr("Debug on Device"), parent)); + addAutoReleasedObject(new RunControlFactory<S60DeviceDebugRunControl, S60DeviceRunConfiguration> + (QLatin1String(Debugger::Constants::DEBUGMODE), + tr("Debug on Device"), parent)); addAutoReleasedObject(new Qt4SymbianTargetFactory); updateQtVersions(); @@ -149,14 +152,12 @@ S60Manager::~S60Manager() } } -bool S60Manager::hasRvct2Compiler() -{ - return RVCT2ToolChain::configuredRvctVersions().contains(qMakePair(2, 2)); -} - -bool S60Manager::hasRvct4Compiler() +QString S60Manager::platform(const ProjectExplorer::ToolChain *tc) { - return RVCT2ToolChain::configuredRvctVersions().contains(qMakePair(2, 2)); + if (!tc || tc->targetAbi().os() == ProjectExplorer::Abi::Symbian) + return QString(); + QString target = tc->defaultMakeTarget(); + return target.right(target.lastIndexOf(QLatin1Char('-'))); } void S60Manager::addAutoReleasedObject(QObject *o) @@ -227,39 +228,6 @@ void S60Manager::updateQtVersions() } } -ProjectExplorer::ToolChain *S60Manager::createWINSCWToolChain(const Qt4ProjectManager::QtVersion *version) const -{ - Q_ASSERT(version); - return new WINSCWToolChain(deviceForQtVersion(version), version->mwcDirectory()); -} - -ProjectExplorer::ToolChain *S60Manager::createGCCEToolChain(const Qt4ProjectManager::QtVersion *version) const -{ - Q_ASSERT(version); - return GCCEToolChain::create(deviceForQtVersion(version), version->gcceDirectory(), ProjectExplorer::ToolChain_GCCE); -} - -ProjectExplorer::ToolChain *S60Manager::createGCCE_GnuPocToolChain(const Qt4ProjectManager::QtVersion *version) const -{ - Q_ASSERT(version); - return GCCEToolChain::create(deviceForQtVersion(version), version->gcceDirectory(), ProjectExplorer::ToolChain_GCCE_GNUPOC); -} - -ProjectExplorer::ToolChain *S60Manager::createRVCTToolChain( - const Qt4ProjectManager::QtVersion *version, - ProjectExplorer::ToolChainType type) const -{ - Q_ASSERT(version); - if (type == ProjectExplorer::ToolChain_RVCT2_ARMV5 - || type == ProjectExplorer::ToolChain_RVCT2_ARMV6 - || type == ProjectExplorer::ToolChain_RVCT_ARMV5_GNUPOC) - return new RVCT2ToolChain(deviceForQtVersion(version), type); - if (type == ProjectExplorer::ToolChain_RVCT4_ARMV5 - || type == ProjectExplorer::ToolChain_RVCT4_ARMV6) - return new RVCT4ToolChain(deviceForQtVersion(version), type); - return 0; -} - S60Devices::Device S60Manager::deviceForQtVersion(const Qt4ProjectManager::QtVersion *version) const { Q_ASSERT(version); diff --git a/src/plugins/qt4projectmanager/qt-s60/s60manager.h b/src/plugins/qt4projectmanager/qt-s60/s60manager.h index e9a3af3bcf..a4460bcedb 100644 --- a/src/plugins/qt4projectmanager/qt-s60/s60manager.h +++ b/src/plugins/qt4projectmanager/qt-s60/s60manager.h @@ -36,8 +36,6 @@ #include "s60devices.h" -#include <projectexplorer/toolchaintype.h> - #include <QtCore/QObject> namespace ProjectExplorer { @@ -57,18 +55,11 @@ public: ~S60Manager(); static S60Manager *instance(); - ProjectExplorer::ToolChain *createWINSCWToolChain(const Qt4ProjectManager::QtVersion *version) const; - ProjectExplorer::ToolChain *createGCCEToolChain(const Qt4ProjectManager::QtVersion *version) const; - ProjectExplorer::ToolChain *createGCCE_GnuPocToolChain(const Qt4ProjectManager::QtVersion *version) const; - ProjectExplorer::ToolChain *createRVCTToolChain(const Qt4ProjectManager::QtVersion *version, - ProjectExplorer::ToolChainType type) const; - S60Devices *devices() const { return m_devices; } S60Devices::Device deviceForQtVersion(const Qt4ProjectManager::QtVersion *version) const; QString deviceIdFromDetectionSource(const QString &autoDetectionSource) const; - static bool hasRvct2Compiler(); - static bool hasRvct4Compiler(); + static QString platform(const ProjectExplorer::ToolChain *tc); private slots: void updateQtVersions(); diff --git a/src/plugins/qt4projectmanager/qt-s60/s60runcontrolbase.cpp b/src/plugins/qt4projectmanager/qt-s60/s60runcontrolbase.cpp index 717cdf862b..36b586af7b 100644 --- a/src/plugins/qt4projectmanager/qt-s60/s60runcontrolbase.cpp +++ b/src/plugins/qt4projectmanager/qt-s60/s60runcontrolbase.cpp @@ -74,8 +74,7 @@ QString S60RunControlBase::msgListFile(const QString &file) S60RunControlBase::S60RunControlBase(RunConfiguration *runConfiguration, const QString &mode) : RunControl(runConfiguration, mode), - m_launchProgress(0), - m_toolChain(ProjectExplorer::ToolChain_INVALID) + m_launchProgress(0) { connect(this, SIGNAL(finished()), this, SLOT(reportLaunchFinished())); connect(this, SIGNAL(finished()), this, SLOT(handleFinished())); @@ -87,7 +86,6 @@ S60RunControlBase::S60RunControlBase(RunConfiguration *runConfiguration, const Q const S60DeployConfiguration *activeDeployConf = qobject_cast<S60DeployConfiguration *>(s60runConfig->qt4Target()->activeDeployConfiguration()); QTC_ASSERT(activeDeployConf, return); - m_toolChain = s60runConfig->toolChainType(); m_executableUid = s60runConfig->executableUid(); m_targetName = s60runConfig->targetName(); m_commandLineArguments = s60runConfig->commandLineArguments(); @@ -100,7 +98,7 @@ S60RunControlBase::S60RunControlBase(RunConfiguration *runConfiguration, const Q m_runSmartInstaller = activeDeployConf->runSmartInstaller(); if (debug) - qDebug() << "S60RunControlBase::CT" << m_targetName << ProjectExplorer::ToolChain::toolChainName(m_toolChain); + qDebug() << "S60RunControlBase::CT" << m_targetName; } void S60RunControlBase::start() @@ -210,11 +208,6 @@ void S60RunControlBase::reportLaunchFinished() setProgress(maxProgress()); } -ToolChainType S60RunControlBase::toolChain() const -{ - return m_toolChain; -} - quint32 S60RunControlBase::executableUid() const { return m_executableUid; diff --git a/src/plugins/qt4projectmanager/qt-s60/s60runcontrolbase.h b/src/plugins/qt4projectmanager/qt-s60/s60runcontrolbase.h index 00a61c3cf4..d0a567dd74 100644 --- a/src/plugins/qt4projectmanager/qt-s60/s60runcontrolbase.h +++ b/src/plugins/qt4projectmanager/qt-s60/s60runcontrolbase.h @@ -35,7 +35,7 @@ #define S60RUNCONTROLBASE_H #include <projectexplorer/runconfiguration.h> -#include <projectexplorer/toolchaintype.h> +#include <projectexplorer/toolchain.h> #include <QtCore/QFutureInterface> @@ -61,7 +61,6 @@ protected: virtual bool setupLauncher() = 0; protected: - ProjectExplorer::ToolChainType toolChain() const; quint32 executableUid() const; QString executableName() const; const QString &targetName() const; @@ -87,7 +86,6 @@ private slots: private: QFutureInterface<void> *m_launchProgress; - ProjectExplorer::ToolChainType m_toolChain; quint32 m_executableUid; QString m_targetName; QString m_commandLineArguments; diff --git a/src/plugins/qt4projectmanager/qt-s60/winscwtoolchain.cpp b/src/plugins/qt4projectmanager/qt-s60/winscwtoolchain.cpp index 6cdf402167..14c8ead8c6 100644 --- a/src/plugins/qt4projectmanager/qt-s60/winscwtoolchain.cpp +++ b/src/plugins/qt4projectmanager/qt-s60/winscwtoolchain.cpp @@ -33,100 +33,372 @@ #include "winscwtoolchain.h" +#include "qt4projectmanager/qt4projectmanagerconstants.h" + +#include "ui_winscwtoolchainconfigwidget.h" #include "winscwparser.h" -#include <QtCore/QByteArray> -#include <QtCore/QString> +#include <utils/environment.h> + +#include <QtCore/QDir> +#include <QtCore/QFileInfo> + +namespace Qt4ProjectManager { +namespace Internal { + +static const char *const WINSCW_COMPILER_PATH_KEY = "Qt4ProjectManager.Winscw.CompilerPath"; +static const char *const WINSCW_SYSTEM_INCLUDE_PATH_KEY = "Qt4ProjectManager.Winscw.IncludePath"; +static const char *const WINSCW_SYSTEM_LIBRARY_PATH_KEY = "Qt4ProjectManager.Winscw.LibraryPath"; -using namespace ProjectExplorer; -using namespace Qt4ProjectManager::Internal; +static const char *const WINSCW_DEFAULT_SYSTEM_INCLUDES[] = { + "/MSL/MSL_C/MSL_Common/Include", + "/MSL/MSL_C/MSL_Win32/Include", + "/MSL/MSL_CMSL_X86", + "/MSL/MSL_C++/MSL_Common/Include", + "/MSL/MSL_Extras/MSL_Common/Include", + "/MSL/MSL_Extras/MSL_Win32/Include", + "/Win32-x86 Support/Headers/Win32 SDK", + 0 +}; -WINSCWToolChain::WINSCWToolChain(const S60Devices::Device &device, const QString &mwcDirectory) - : m_mixin(device), - m_carbidePath(mwcDirectory), - m_deviceId(device.id), - m_deviceName(device.name), - m_deviceRoot(device.epocRoot) +static const char *const WINSCW_DEFAULT_SYSTEM_LIBRARIES[] = { + "/Win32-x86 Support/Libraries/Win32 SDK", + "/Runtime/Runtime_x86/Runtime_Win32/Libs", + 0 +}; + +static QString winscwRoot(const QString &path) { + if (path.isEmpty()) + return QString(); + QDir dir(path); + dir.cdUp(); + dir.cdUp(); + dir.cdUp(); + dir.cd("Symbian_Support"); + return dir.absolutePath(); } -ProjectExplorer::ToolChainType WINSCWToolChain::type() const +static QString toNativePath(const QStringList &list) { - return ProjectExplorer::ToolChain_WINSCW; + return QDir::toNativeSeparators(list.join(QString(QLatin1Char(';')))); } -QByteArray WINSCWToolChain::predefinedMacros() +static QStringList fromNativePath(const QString &list) { - return QByteArray("#define __SYMBIAN32__\n"); + QString tmp = QDir::fromNativeSeparators(list); + return tmp.split(';'); } -QList<HeaderPath> WINSCWToolChain::systemHeaderPaths() +static QStringList detectIncludesFor(const QString path) { - if (m_systemHeaderPaths.isEmpty()) { - foreach (const QString &value, systemIncludes()) { - m_systemHeaderPaths.append(HeaderPath(value, HeaderPath::GlobalHeaderPath)); - } - m_systemHeaderPaths += m_mixin.epocHeaderPaths(); + QString root = winscwRoot(path); + QStringList result; + for (int i = 0; WINSCW_DEFAULT_SYSTEM_INCLUDES[i] != 0; ++i) { + QDir dir(root + QLatin1String(WINSCW_DEFAULT_SYSTEM_INCLUDES[i])); + if (dir.exists()) + result.append(dir.absolutePath()); } - return m_systemHeaderPaths; -} - -QStringList WINSCWToolChain::systemIncludes() const -{ - if (m_carbidePath.isEmpty()) { - Utils::Environment env = Utils::Environment::systemEnvironment(); - QString symIncludesValue = env.value("MWCSYM2INCLUDES"); - if (!symIncludesValue.isEmpty()) - return symIncludesValue.split(QLatin1Char(';')); - } else { - QStringList symIncludes = QStringList() - << "\\MSL\\MSL_C\\MSL_Common\\Include" - << "\\MSL\\MSL_C\\MSL_Win32\\Include" - << "\\MSL\\MSL_CMSL_X86" - << "\\MSL\\MSL_C++\\MSL_Common\\Include" - << "\\MSL\\MSL_Extras\\MSL_Common\\Include" - << "\\MSL\\MSL_Extras\\MSL_Win32\\Include" - << "\\Win32-x86 Support\\Headers\\Win32 SDK"; - for (int i = 0; i < symIncludes.size(); ++i) - symIncludes[i].prepend(QString("%1\\x86Build\\Symbian_Support").arg(m_carbidePath)); - return symIncludes; - } - return QStringList(); + return result; } -void WINSCWToolChain::addToEnvironment(Utils::Environment &env) +static QStringList detectLibrariesFor(const QString path) { - if (!m_carbidePath.isEmpty()) { - env.set("MWCSYM2INCLUDES", systemIncludes().join(QString(QLatin1Char(';')))); - QStringList symLibraries = QStringList() - << "\\Win32-x86 Support\\Libraries\\Win32 SDK" - << "\\Runtime\\Runtime_x86\\Runtime_Win32\\Libs"; - for (int i = 0; i < symLibraries.size(); ++i) - symLibraries[i].prepend(QString("%1\\x86Build\\Symbian_Support").arg(m_carbidePath)); - env.set("MWSYM2LIBRARIES", symLibraries.join(";")); - env.set("MWSYM2LIBRARYFILES", "MSL_All_MSE_Symbian_D.lib;gdi32.lib;user32.lib;kernel32.lib"); - env.prependOrSetPath(QString("%1\\x86Build\\Symbian_Tools\\Command_Line_Tools").arg(m_carbidePath)); // compiler + QString root = winscwRoot(path); + QStringList result; + for (int i = 0; WINSCW_DEFAULT_SYSTEM_LIBRARIES[i] != 0; ++i) { + QDir dir(root + QLatin1String(WINSCW_DEFAULT_SYSTEM_LIBRARIES[i])); + if (dir.exists()) + result.append(dir.absolutePath()); } - m_mixin.addEpocToEnvironment(&env); + return result; +} + +// -------------------------------------------------------------------------- +// WinscwToolChain +// -------------------------------------------------------------------------- + +WinscwToolChain::WinscwToolChain(bool autodetected) : + ProjectExplorer::ToolChain(QLatin1String(Constants::WINSCW_TOOLCHAIN_ID), autodetected) +{ } + +WinscwToolChain::WinscwToolChain(const WinscwToolChain &tc) : + ProjectExplorer::ToolChain(tc), + m_systemIncludePathes(tc.m_systemIncludePathes), + m_systemLibraryPathes(tc.m_systemLibraryPathes), + m_compilerPath(tc.m_compilerPath) +{ } + +WinscwToolChain::~WinscwToolChain() +{ } + +QString WinscwToolChain::typeName() const +{ + return WinscwToolChainFactory::tr("WINSCW"); +} + +ProjectExplorer::Abi WinscwToolChain::targetAbi() const +{ + return ProjectExplorer::Abi(ProjectExplorer::Abi::ARM, ProjectExplorer::Abi::Symbian, + ProjectExplorer::Abi::Symbian_emulator, + ProjectExplorer::Abi::Format_ELF, false); +} + +bool WinscwToolChain::isValid() const +{ + if (m_compilerPath.isEmpty()) + return false; + + QFileInfo fi(m_compilerPath); + return fi.exists() && fi.isExecutable(); +} + +QByteArray WinscwToolChain::predefinedMacros() const +{ + return QByteArray("#define __SYMBIAN32__\n"); +} + +QList<ProjectExplorer::HeaderPath> WinscwToolChain::systemHeaderPaths() const +{ + QList<ProjectExplorer::HeaderPath> result; + foreach (const QString &value, m_systemIncludePathes) + result.append(ProjectExplorer::HeaderPath(value, ProjectExplorer::HeaderPath::GlobalHeaderPath)); + return result; +} + +void WinscwToolChain::addToEnvironment(Utils::Environment &env) const +{ + if (!isValid()) + return; + + env.set(QLatin1String("MWCSYM2INCLUDES"), toNativePath(m_systemIncludePathes)); + env.set(QLatin1String("MWSYM2LIBRARIES"), toNativePath(m_systemLibraryPathes)); + env.set(QLatin1String("MWSYM2LIBRARYFILES"), + QLatin1String("MSL_All_MSE_Symbian_D.lib;gdi32.lib;user32.lib;kernel32.lib")); + env.prependOrSetPath(QFileInfo(m_compilerPath).absolutePath()); } -QString WINSCWToolChain::makeCommand() const +QString WinscwToolChain::makeCommand() const { +#if defined Q_OS_WIN + return QLatin1String("make.exe"); +#else return QLatin1String("make"); +#endif +} + + +QString WinscwToolChain::defaultMakeTarget() const +{ + return QLatin1String("winscw"); } -IOutputParser *WINSCWToolChain::outputParser() const +ProjectExplorer::IOutputParser *WinscwToolChain::outputParser() const { return new WinscwParser; } -bool WINSCWToolChain::equals(const ToolChain *other) const +bool WinscwToolChain::operator ==(const ProjectExplorer::ToolChain &tc) const +{ + if (!ToolChain::operator ==(tc)) + return false; + + const WinscwToolChain *tcPtr = dynamic_cast<const WinscwToolChain *>(&tc); + Q_ASSERT(tcPtr); + return m_compilerPath == tcPtr->m_compilerPath + && m_systemIncludePathes == tcPtr->m_systemIncludePathes + && m_systemLibraryPathes == tcPtr->m_systemLibraryPathes; +} + +ProjectExplorer::ToolChainConfigWidget *WinscwToolChain::configurationWidget() +{ + return new WinscwToolChainConfigWidget(this); +} + +ProjectExplorer::ToolChain *WinscwToolChain::clone() const +{ + return new WinscwToolChain(*this); +} + +QVariantMap WinscwToolChain::toMap() const +{ + QVariantMap result = ToolChain::toMap(); + result.insert(QLatin1String(WINSCW_COMPILER_PATH_KEY), m_compilerPath); + result.insert(QLatin1String(WINSCW_SYSTEM_INCLUDE_PATH_KEY), m_systemIncludePathes.join(QString(QLatin1Char(';')))); + result.insert(QLatin1String(WINSCW_SYSTEM_LIBRARY_PATH_KEY), m_systemLibraryPathes.join(QString(QLatin1Char(';')))); + return result; +} + +bool WinscwToolChain::fromMap(const QVariantMap &data) +{ + if (!ToolChain::fromMap(data)) + return false; + m_compilerPath = data.value(QLatin1String(WINSCW_COMPILER_PATH_KEY)).toString(); + m_systemIncludePathes = data.value(QLatin1String(WINSCW_SYSTEM_INCLUDE_PATH_KEY)).toString().split(QLatin1Char(';')); + m_systemLibraryPathes = data.value(QLatin1String(WINSCW_SYSTEM_LIBRARY_PATH_KEY)).toString().split(QLatin1Char(';')); + + return isValid(); +} + +void WinscwToolChain::setSystemIncludePathes(const QStringList &pathes) { - const WINSCWToolChain *otherWINSCW = static_cast<const WINSCWToolChain *>(other); - return (other->type() == type() - && m_deviceId == otherWINSCW->m_deviceId - && m_deviceName == otherWINSCW->m_deviceName - && m_deviceRoot == otherWINSCW->m_deviceRoot - && m_carbidePath == otherWINSCW->m_carbidePath); + m_systemIncludePathes = pathes; } + +QStringList WinscwToolChain::systemIncludePathes() const +{ + return m_systemIncludePathes; +} + +void WinscwToolChain::setSystemLibraryPathes(const QStringList &pathes) +{ + m_systemLibraryPathes = pathes; +} + +QStringList WinscwToolChain::systemLibraryPathes() const +{ + return m_systemLibraryPathes; +} + +void WinscwToolChain::setCompilerPath(const QString &path) +{ + if (m_compilerPath == path) + return; + + m_compilerPath = path; + updateId(); +} + +QString WinscwToolChain::compilerPath() const +{ + return m_compilerPath; +} + +void WinscwToolChain::updateId() +{ + setId(QString::fromLatin1("%1:%2").arg(Constants::WINSCW_TOOLCHAIN_ID).arg(m_compilerPath)); +} + +// -------------------------------------------------------------------------- +// ToolChainConfigWidget +// -------------------------------------------------------------------------- + +WinscwToolChainConfigWidget::WinscwToolChainConfigWidget(WinscwToolChain *tc) : + ProjectExplorer::ToolChainConfigWidget(tc), + m_ui(new Ui::WinscwToolChainConfigWidget) +{ + m_ui->setupUi(this); + + m_ui->compilerPath->setExpectedKind(Utils::PathChooser::ExistingCommand); + connect(m_ui->compilerPath, SIGNAL(changed(QString)), + this, SLOT(handleCompilerPathUpdate())); + connect(m_ui->includeEdit, SIGNAL(textChanged(QString)), this, SLOT(makeDirty())); + connect(m_ui->libraryEdit, SIGNAL(textChanged(QString)), this, SLOT(makeDirty())); + + discard(); +} + +void WinscwToolChainConfigWidget::apply() +{ + WinscwToolChain *tc = static_cast<WinscwToolChain *>(toolChain()); + Q_ASSERT(tc); + tc->setCompilerPath(m_ui->compilerPath->path()); + tc->setSystemIncludePathes(fromNativePath(m_ui->includeEdit->text())); + tc->setSystemLibraryPathes(fromNativePath(m_ui->libraryEdit->text())); +} + +void WinscwToolChainConfigWidget::discard() +{ + WinscwToolChain *tc = static_cast<WinscwToolChain *>(toolChain()); + Q_ASSERT(tc); + m_ui->compilerPath->setPath(tc->compilerPath()); + m_ui->includeEdit->setText(toNativePath(tc->systemIncludePathes())); + m_ui->libraryEdit->setText(toNativePath(tc->systemLibraryPathes())); +} + +bool WinscwToolChainConfigWidget::isDirty() const +{ + WinscwToolChain *tc = static_cast<WinscwToolChain *>(toolChain()); + Q_ASSERT(tc); + return tc->compilerPath() != m_ui->compilerPath->path() + || tc->systemIncludePathes() != fromNativePath(m_ui->includeEdit->text()) + || tc->systemLibraryPathes() != fromNativePath(m_ui->libraryEdit->text()); +} + +void WinscwToolChainConfigWidget::handleCompilerPathUpdate() +{ + QString path = m_ui->compilerPath->path(); + if (path.isEmpty()) + return; + QFileInfo fi(path); + if (!fi.exists()) + return; + m_ui->includeEdit->setText(toNativePath(detectIncludesFor(path))); + m_ui->libraryEdit->setText(toNativePath(detectLibrariesFor(path))); +} + +void WinscwToolChainConfigWidget::makeDirty() +{ + emit dirty(toolChain()); +} + +// -------------------------------------------------------------------------- +// ToolChainFactory +// -------------------------------------------------------------------------- + +WinscwToolChainFactory::WinscwToolChainFactory() : + ProjectExplorer::ToolChainFactory() +{ } + +QString WinscwToolChainFactory::displayName() const +{ + return tr("WINSCW"); +} + +QString WinscwToolChainFactory::id() const +{ + return QLatin1String(Constants::WINSCW_TOOLCHAIN_ID); +} + +QList<ProjectExplorer::ToolChain *> WinscwToolChainFactory::autoDetect() +{ + QList<ProjectExplorer::ToolChain *> result; + QString cc = Utils::Environment::systemEnvironment().searchInPath(QLatin1String("mwwinrc")); + if (!cc.isEmpty()) { + WinscwToolChain *tc = new WinscwToolChain(true); + tc->setCompilerPath(cc); + tc->setSystemIncludePathes(detectIncludesFor(cc)); + tc->setSystemLibraryPathes(detectLibrariesFor(cc)); + result.append(tc); + } + return result; +} + +bool WinscwToolChainFactory::canCreate() +{ + return true; +} + +ProjectExplorer::ToolChain *WinscwToolChainFactory::create() +{ + return new WinscwToolChain(false); +} + +bool WinscwToolChainFactory::canRestore(const QVariantMap &data) +{ + return idFromMap(data).startsWith(QLatin1String(Constants::WINSCW_TOOLCHAIN_ID)); +} + +ProjectExplorer::ToolChain *WinscwToolChainFactory::restore(const QVariantMap &data) +{ + WinscwToolChain *tc = new WinscwToolChain(false); + if (tc->fromMap(data)) + return tc; + + delete tc; + return 0; +} + +} // namespace Internal +} // namespace Qt4ProjectManager diff --git a/src/plugins/qt4projectmanager/qt-s60/winscwtoolchain.h b/src/plugins/qt4projectmanager/qt-s60/winscwtoolchain.h index b618045cb9..9d85de4ed2 100644 --- a/src/plugins/qt4projectmanager/qt-s60/winscwtoolchain.h +++ b/src/plugins/qt4projectmanager/qt-s60/winscwtoolchain.h @@ -34,37 +34,111 @@ #ifndef WINSCWTOOLCHAIN_H #define WINSCWTOOLCHAIN_H -#include "s60devices.h" - #include <projectexplorer/toolchain.h> +#include <projectexplorer/toolchainconfigwidget.h> namespace Qt4ProjectManager { namespace Internal { +namespace Ui { +class WinscwToolChainConfigWidget; +} // namespace Ui + +// -------------------------------------------------------------------------- +// WinscwToolChain +// -------------------------------------------------------------------------- -class WINSCWToolChain : public ProjectExplorer::ToolChain +class WinscwToolChain : public ProjectExplorer::ToolChain { public: - explicit WINSCWToolChain(const S60Devices::Device &device, const QString &mwcDirectory); - QByteArray predefinedMacros(); - QList<ProjectExplorer::HeaderPath> systemHeaderPaths(); - void addToEnvironment(Utils::Environment &env); - ProjectExplorer::ToolChainType type() const; + WinscwToolChain(const WinscwToolChain &); + ~WinscwToolChain(); + + QString typeName() const; + ProjectExplorer::Abi targetAbi() const; + + bool isValid() const; + + QByteArray predefinedMacros() const; + QList<ProjectExplorer::HeaderPath> systemHeaderPaths() const; + void addToEnvironment(Utils::Environment &env) const; QString makeCommand() const; + QString defaultMakeTarget() const; ProjectExplorer::IOutputParser *outputParser() const; -protected: - bool equals(const ToolChain *other) const; + bool operator ==(const ProjectExplorer::ToolChain &) const; + + ProjectExplorer::ToolChainConfigWidget *configurationWidget(); + ProjectExplorer::ToolChain *clone() const; + + QVariantMap toMap() const; + bool fromMap(const QVariantMap &data); + + void setSystemIncludePathes(const QStringList &); + QStringList systemIncludePathes() const; + + void setSystemLibraryPathes(const QStringList &); + QStringList systemLibraryPathes() const; + + void setCompilerPath(const QString &); + QString compilerPath() const; private: - QStringList systemIncludes() const; + void updateId(); + + explicit WinscwToolChain(bool); + + QStringList m_systemIncludePathes; + QStringList m_systemLibraryPathes; + QString m_compilerPath; + + friend class WinscwToolChainFactory; +}; + +// -------------------------------------------------------------------------- +// WinscwToolChainConfigWidget +// -------------------------------------------------------------------------- + +class WinscwToolChainConfigWidget : public ProjectExplorer::ToolChainConfigWidget +{ + Q_OBJECT + +public: + WinscwToolChainConfigWidget(WinscwToolChain *); + + void apply(); + void discard(); + bool isDirty() const; + +private slots: + void handleCompilerPathUpdate(); + void makeDirty(); + +private: + Ui::WinscwToolChainConfigWidget *m_ui; +}; + +// -------------------------------------------------------------------------- +// WinscwToolChainFactory +// -------------------------------------------------------------------------- + +class WinscwToolChainFactory : public ProjectExplorer::ToolChainFactory +{ + Q_OBJECT + +public: + WinscwToolChainFactory(); + + QString displayName() const; + QString id() const; + + QList<ProjectExplorer::ToolChain *> autoDetect(); - const S60ToolChainMixin m_mixin; + bool canCreate(); + ProjectExplorer::ToolChain *create(); - QString m_carbidePath; - QString m_deviceId; - QString m_deviceName; - QString m_deviceRoot; - QList<ProjectExplorer::HeaderPath> m_systemHeaderPaths; + // Used by the ToolChainManager to restore user-generated ToolChains + bool canRestore(const QVariantMap &data); + ProjectExplorer::ToolChain *restore(const QVariantMap &data); }; } // namespace Internal diff --git a/src/plugins/qt4projectmanager/qt-s60/winscwtoolchainconfigwidget.ui b/src/plugins/qt4projectmanager/qt-s60/winscwtoolchainconfigwidget.ui new file mode 100644 index 0000000000..cee8384612 --- /dev/null +++ b/src/plugins/qt4projectmanager/qt-s60/winscwtoolchainconfigwidget.ui @@ -0,0 +1,58 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>Qt4ProjectManager::Internal::WinscwToolChainConfigWidget</class> + <widget class="QWidget" name="Qt4ProjectManager::Internal::WinscwToolChainConfigWidget"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>428</width> + <height>95</height> + </rect> + </property> + <property name="windowTitle"> + <string>Dialog</string> + </property> + <layout class="QGridLayout" name="gridLayout"> + <item row="0" column="0"> + <widget class="QLabel" name="label"> + <property name="text"> + <string>Compiler path:</string> + </property> + </widget> + </item> + <item row="0" column="1"> + <widget class="Utils::PathChooser" name="compilerPath"/> + </item> + <item row="1" column="0"> + <widget class="QLabel" name="label_2"> + <property name="text"> + <string>System include path:</string> + </property> + </widget> + </item> + <item row="1" column="1"> + <widget class="QLineEdit" name="includeEdit"/> + </item> + <item row="2" column="0"> + <widget class="QLabel" name="label_3"> + <property name="text"> + <string>System library path:</string> + </property> + </widget> + </item> + <item row="2" column="1"> + <widget class="QLineEdit" name="libraryEdit"/> + </item> + </layout> + </widget> + <customwidgets> + <customwidget> + <class>Utils::PathChooser</class> + <extends>QLineEdit</extends> + <header>utils/pathchooser.h</header> + </customwidget> + </customwidgets> + <resources/> + <connections/> +</ui> diff --git a/src/plugins/qt4projectmanager/qt4buildconfiguration.cpp b/src/plugins/qt4projectmanager/qt4buildconfiguration.cpp index b64a83cb4f..3998b76591 100644 --- a/src/plugins/qt4projectmanager/qt4buildconfiguration.cpp +++ b/src/plugins/qt4projectmanager/qt4buildconfiguration.cpp @@ -45,6 +45,7 @@ #include <limits> #include <projectexplorer/buildsteplist.h> #include <projectexplorer/projectexplorerconstants.h> +#include <projectexplorer/toolchainmanager.h> #include <QtCore/QDebug> @@ -72,7 +73,6 @@ Qt4BuildConfiguration::Qt4BuildConfiguration(Qt4BaseTarget *target) : m_shadowBuild(true), m_isEnabled(false), m_qtVersionId(-1), - m_toolChainType(-1), // toolChainType() makes sure to return the default toolchainType m_qmakeBuildConfiguration(0), m_subNodeBuild(0) { @@ -84,7 +84,6 @@ Qt4BuildConfiguration::Qt4BuildConfiguration(Qt4BaseTarget *target, const QStrin m_shadowBuild(true), m_isEnabled(false), m_qtVersionId(-1), - m_toolChainType(-1), // toolChainType() makes sure to return the default toolchainType m_qmakeBuildConfiguration(0), m_subNodeBuild(0) { @@ -97,7 +96,6 @@ Qt4BuildConfiguration::Qt4BuildConfiguration(Qt4BaseTarget *target, Qt4BuildConf m_isEnabled(false), m_buildDirectory(source->m_buildDirectory), m_qtVersionId(source->m_qtVersionId), - m_toolChainType(source->m_toolChainType), m_qmakeBuildConfiguration(source->m_qmakeBuildConfiguration), m_subNodeBuild(0) // temporary value, so not copied { @@ -115,7 +113,7 @@ QVariantMap Qt4BuildConfiguration::toMap() const map.insert(QLatin1String(USE_SHADOW_BUILD_KEY), m_shadowBuild); map.insert(QLatin1String(BUILD_DIRECTORY_KEY), m_buildDirectory); map.insert(QLatin1String(QT_VERSION_ID_KEY), m_qtVersionId); - map.insert(QLatin1String(TOOLCHAIN_KEY), m_toolChainType); + map.insert(QLatin1String(TOOLCHAIN_KEY), toolChain() ? toolChain()->id() : QLatin1String("<UNSET>")); map.insert(QLatin1String(BUILD_CONFIGURATION_KEY), int(m_qmakeBuildConfiguration)); return map; } @@ -129,7 +127,8 @@ bool Qt4BuildConfiguration::fromMap(const QVariantMap &map) m_shadowBuild = map.value(QLatin1String(USE_SHADOW_BUILD_KEY), true).toBool(); m_buildDirectory = map.value(QLatin1String(BUILD_DIRECTORY_KEY), qt4Target()->defaultBuildDirectory()).toString(); m_qtVersionId = map.value(QLatin1String(QT_VERSION_ID_KEY)).toInt(); - m_toolChainType = map.value(QLatin1String(TOOLCHAIN_KEY)).toInt(); + ProjectExplorer::ToolChain *tc = 0; + tc = ProjectExplorer::ToolChainManager::instance()->findToolChain(map.value(QLatin1String(TOOLCHAIN_KEY)).toString()); m_qmakeBuildConfiguration = QtVersion::QmakeBuildConfigs(map.value(QLatin1String(BUILD_CONFIGURATION_KEY)).toInt()); // Pick a Qt version if the default version is used: @@ -160,14 +159,15 @@ bool Qt4BuildConfiguration::fromMap(const QVariantMap &map) } } - if (version->isValid()) + if (version->isValid()) { + if (!tc) + tc = qt4Target()->preferredToolChain(this); + if (tc && qt4Target()->possibleToolChains(this).contains(tc)) + setToolChain(tc); m_shadowBuild = (m_shadowBuild && version->supportsShadowBuilds()); + } - QList<ProjectExplorer::ToolChainType> possibleTcs(qt4Target()->filterToolChainTypes(qtVersion()->possibleToolChainTypes())); - if (!possibleTcs.contains(toolChainType())) - setToolChainType(qt4Target()->preferredToolChainType(possibleTcs)); - - if (toolChainType() == ProjectExplorer::ToolChain_INVALID) { + if (!toolChain()) { qWarning() << "No toolchain available for" << qtVersion()->displayName() << "used in" << target()->id() << "!"; return false; } @@ -298,12 +298,6 @@ void Qt4BuildConfiguration::setShadowBuildAndDirectory(bool shadowBuild, const Q emit proFileEvaluateNeeded(this); } -ProjectExplorer::ToolChain *Qt4BuildConfiguration::toolChain() const -{ - const ProjectExplorer::ToolChainType tct = toolChainType(); - return qtVersion()->toolChain(tct); -} - QString Qt4BuildConfiguration::makeCommand() const { ToolChain *tc = toolChain(); @@ -322,25 +316,11 @@ static inline QString symbianMakeTarget(QtVersion::QmakeBuildConfigs buildConfig QString Qt4BuildConfiguration::defaultMakeTarget() const { ToolChain *tc = toolChain(); - if (!tc) + if (!tc || target()->id() != Constants::S60_DEVICE_TARGET_ID) return QString(); const QtVersion::QmakeBuildConfigs buildConfig = qmakeBuildConfiguration(); - switch (tc->type()) { - case ProjectExplorer::ToolChain_GCCE: - return symbianMakeTarget(buildConfig, QLatin1String("gcce")); - case ProjectExplorer::ToolChain_RVCT2_ARMV5: - case ProjectExplorer::ToolChain_RVCT4_ARMV5: - return symbianMakeTarget(buildConfig, QLatin1String("armv5")); - case ProjectExplorer::ToolChain_RVCT2_ARMV6: - case ProjectExplorer::ToolChain_RVCT4_ARMV6: - return symbianMakeTarget(buildConfig, QLatin1String("armv6")); - case ProjectExplorer::ToolChain_RVCT_ARMV5_GNUPOC: - case ProjectExplorer::ToolChain_GCCE_GNUPOC: - default: - break; - } - return QString(); + return symbianMakeTarget(buildConfig, tc->defaultMakeTarget()); } QString Qt4BuildConfiguration::makefile() const @@ -363,15 +343,8 @@ void Qt4BuildConfiguration::setQtVersion(QtVersion *version) m_qtVersionId = version->uniqueId(); - if (!version->possibleToolChainTypes().contains(ProjectExplorer::ToolChainType(m_toolChainType))) { - QList<ProjectExplorer::ToolChainType> candidates = - qt4Target()->filterToolChainTypes(qtVersion()->possibleToolChainTypes()); - if (candidates.isEmpty()) - m_toolChainType = ProjectExplorer::ToolChain_INVALID; - else - m_toolChainType = candidates.first(); - } - + if (!qt4Target()->possibleToolChains(this).contains(toolChain())) + setToolChain(qt4Target()->preferredToolChain(this)); m_shadowBuild = m_shadowBuild && qtVersion()->supportsShadowBuilds(); emit proFileEvaluateNeeded(this); @@ -380,25 +353,20 @@ void Qt4BuildConfiguration::setQtVersion(QtVersion *version) emitBuildDirectoryChanged(); } -void Qt4BuildConfiguration::setToolChainType(ProjectExplorer::ToolChainType type) +void Qt4BuildConfiguration::setToolChain(ProjectExplorer::ToolChain *tc) { - if (!qt4Target()->filterToolChainTypes(qtVersion()->possibleToolChainTypes()).contains(type) - || m_toolChainType == type) + Q_ASSERT(qtVersion()); + if (!qt4Target()->possibleToolChains(this).contains(tc) + || tc->restrictedToTargets().contains(target()->id())) return; - m_toolChainType = type; + BuildConfiguration::setToolChain(tc); emit proFileEvaluateNeeded(this); - emit toolChainTypeChanged(); emit environmentChanged(); emitBuildDirectoryChanged(); } -ProjectExplorer::ToolChainType Qt4BuildConfiguration::toolChainType() const -{ - return ProjectExplorer::ToolChainType(m_toolChainType); -} - QtVersion::QmakeBuildConfigs Qt4BuildConfiguration::qmakeBuildConfiguration() const { return m_qmakeBuildConfiguration; diff --git a/src/plugins/qt4projectmanager/qt4buildconfiguration.h b/src/plugins/qt4projectmanager/qt4buildconfiguration.h index df0e9f2123..d194a4f502 100644 --- a/src/plugins/qt4projectmanager/qt4buildconfiguration.h +++ b/src/plugins/qt4projectmanager/qt4buildconfiguration.h @@ -37,7 +37,6 @@ #include "qtversionmanager.h" #include <projectexplorer/buildconfiguration.h> -#include <projectexplorer/toolchaintype.h> namespace ProjectExplorer { class ToolChain; @@ -79,9 +78,7 @@ public: QtVersion *qtVersion() const; void setQtVersion(QtVersion *); - ProjectExplorer::ToolChain *toolChain() const; - void setToolChainType(ProjectExplorer::ToolChainType type); - ProjectExplorer::ToolChainType toolChainType() const; + void setToolChain(ProjectExplorer::ToolChain *tc); QtVersion::QmakeBuildConfigs qmakeBuildConfiguration() const; void setQMakeBuildConfiguration(QtVersion::QmakeBuildConfigs config); @@ -134,9 +131,6 @@ signals: /// emitted if the qt version changes (either directly, or because the default qt version changed /// or because the user changed the settings for the qt version void qtVersionChanged(); - /// emitted iff the setToolChainType() function is called, not emitted for qtversion changes - /// even if those result in a toolchain change - void toolChainTypeChanged(); /// emitted for setQMakeBuildConfig, not emitted for qt version changes, even /// if those change the qmakebuildconfig void qmakeBuildConfigurationChanged(); @@ -168,7 +162,6 @@ private: QString m_buildDirectory; QString m_lastEmmitedBuildDirectory; int m_qtVersionId; - int m_toolChainType; QtVersion::QmakeBuildConfigs m_qmakeBuildConfiguration; Qt4ProjectManager::Internal::Qt4ProFileNode *m_subNodeBuild; }; diff --git a/src/plugins/qt4projectmanager/qt4project.cpp b/src/plugins/qt4projectmanager/qt4project.cpp index c1f1e7a8c7..5a18b1a20e 100644 --- a/src/plugins/qt4projectmanager/qt4project.cpp +++ b/src/plugins/qt4projectmanager/qt4project.cpp @@ -431,14 +431,10 @@ void Qt4Project::updateCppCodeModel() ToolChain *tc = activeBC->toolChain(); if (tc) { predefinedMacros = tc->predefinedMacros(); - //qDebug()<<"Predefined Macros"; - //qDebug()<<tc->predefinedMacros(); - //qDebug()<<""; - //qDebug()<<"System Header Paths"; - //foreach(const HeaderPath &hp, tc->systemHeaderPaths()) - // qDebug()<<hp.path(); - - foreach (const HeaderPath &headerPath, tc->systemHeaderPaths()) { + + QList<HeaderPath> headers = tc->systemHeaderPaths(); + headers.append(activeBC->qtVersion()->systemHeaderPathes()); + foreach (const HeaderPath &headerPath, headers) { if (headerPath.kind() == HeaderPath::FrameworkHeaderPath) predefinedFrameworkPaths.append(headerPath.path()); else @@ -920,8 +916,11 @@ ProFileReader *Qt4Project::createProFileReader(Qt4ProFileNode *qt4ProFileNode) QtVersion *version = activeTarget()->activeBuildConfiguration()->qtVersion(); if (version->isValid()) { m_proFileOption->properties = version->versionInfo(); - m_proFileOption->sysroot - = activeTarget()->activeBuildConfiguration()->toolChain()->sysroot(); + if (activeTarget() + && activeTarget()->activeBuildConfiguration() + && activeTarget()->activeBuildConfiguration()->toolChain()) + m_proFileOption->sysroot + = activeTarget()->activeBuildConfiguration()->qtVersion()->systemRoot(); } } diff --git a/src/plugins/qt4projectmanager/qt4projectconfigwidget.cpp b/src/plugins/qt4projectmanager/qt4projectconfigwidget.cpp index cb25702b00..77fda631dd 100644 --- a/src/plugins/qt4projectmanager/qt4projectconfigwidget.cpp +++ b/src/plugins/qt4projectmanager/qt4projectconfigwidget.cpp @@ -44,7 +44,7 @@ #include <coreplugin/icore.h> -#include <projectexplorer/toolchain.h> +#include <projectexplorer/toolchainmanager.h> #include <projectexplorer/projectexplorerconstants.h> #include <projectexplorer/buildconfiguration.h> #include <utils/qtcassert.h> @@ -61,7 +61,7 @@ bool debug = false; using namespace Qt4ProjectManager; using namespace Qt4ProjectManager::Internal; -using ProjectExplorer::ToolChain; +using namespace ProjectExplorer; Qt4ProjectConfigWidget::Qt4ProjectConfigWidget(Qt4BaseTarget *target) : BuildConfigWidget(), @@ -106,6 +106,9 @@ Qt4ProjectConfigWidget::Qt4ProjectConfigWidget(Qt4BaseTarget *target) connect(m_ui->manageQtVersionPushButtons, SIGNAL(clicked()), this, SLOT(manageQtVersions())); + connect(m_ui->manageToolChainPushButton, SIGNAL(clicked()), + this, SLOT(manageToolChains())); + connect(target->qt4Project(), SIGNAL(environmentChanged()), this, SLOT(environmentChanged())); @@ -139,7 +142,8 @@ void Qt4ProjectConfigWidget::updateDetails() "with tool chain <b>%2</b><br>" "building in <b>%3</b>") .arg(versionString, - ProjectExplorer::ToolChain::toolChainName(m_buildConfiguration->toolChainType()), + m_buildConfiguration->toolChain() ? m_buildConfiguration->toolChain()->displayName() : + tr("<Invalid ToolChain>"), QDir::toNativeSeparators(m_buildConfiguration->buildDirectory()))); } } @@ -164,6 +168,13 @@ void Qt4ProjectConfigWidget::manageQtVersions() core->showOptionsDialog(Constants::QT_SETTINGS_CATEGORY, Constants::QTVERSION_SETTINGS_PAGE_ID); } +void Qt4ProjectConfigWidget::manageToolChains() +{ + Core::ICore *core = Core::ICore::instance(); + core->showOptionsDialog(ProjectExplorer::Constants::TOOLCHAIN_SETTINGS_CATEGORY, + ProjectExplorer::Constants::TOOLCHAIN_SETTINGS_PAGE_ID); +} + QString Qt4ProjectConfigWidget::displayName() const { return tr("General"); @@ -183,8 +194,8 @@ void Qt4ProjectConfigWidget::init(ProjectExplorer::BuildConfiguration *bc) this, SLOT(qtVersionChanged())); disconnect(m_buildConfiguration, SIGNAL(qmakeBuildConfigurationChanged()), this, SLOT(updateImportLabel())); - disconnect(m_buildConfiguration, SIGNAL(toolChainTypeChanged()), - this, SLOT(toolChainTypeChanged())); + disconnect(m_buildConfiguration, SIGNAL(toolChainChanged()), + this, SLOT(toolChainChanged())); } m_buildConfiguration = static_cast<Qt4BuildConfiguration *>(bc); m_ui->shadowBuildDirEdit->setEnvironment(m_buildConfiguration->environment()); @@ -195,8 +206,8 @@ void Qt4ProjectConfigWidget::init(ProjectExplorer::BuildConfiguration *bc) this, SLOT(qtVersionChanged())); connect(m_buildConfiguration, SIGNAL(qmakeBuildConfigurationChanged()), this, SLOT(updateImportLabel())); - connect(m_buildConfiguration, SIGNAL(toolChainTypeChanged()), - this, SLOT(toolChainTypeChanged())); + connect(m_buildConfiguration, SIGNAL(toolChainChanged()), + this, SLOT(toolChainChanged())); qtVersionsChanged(); QtVersionManager *vm = QtVersionManager::instance(); @@ -211,6 +222,11 @@ void Qt4ProjectConfigWidget::init(ProjectExplorer::BuildConfiguration *bc) updateImportLabel(); updateToolChainCombo(); updateDetails(); + + connect(ToolChainManager::instance(), SIGNAL(toolChainAdded(ProjectExplorer::ToolChain*)), + this, SLOT(updateToolChainCombo())); + connect(ToolChainManager::instance(), SIGNAL(toolChainRemoved(ProjectExplorer::ToolChain*)), + this, SLOT(updateToolChainCombo())); } void Qt4ProjectConfigWidget::qtVersionChanged() @@ -435,14 +451,14 @@ void Qt4ProjectConfigWidget::qtVersionSelected(const QString &) updateDetails(); } -void Qt4ProjectConfigWidget::toolChainTypeChanged() +void Qt4ProjectConfigWidget::toolChainChanged() { if (m_ignoreChange) return; for (int i=0; i < m_ui->toolChainComboBox->count(); ++i) { - ProjectExplorer::ToolChainType tt = - m_ui->toolChainComboBox->itemData(i, Qt::UserRole).value<ProjectExplorer::ToolChainType>(); - if (tt == m_buildConfiguration->toolChainType()) { + ProjectExplorer::ToolChain *tc = + static_cast<ProjectExplorer::ToolChain *>(m_ui->toolChainComboBox->itemData(i, Qt::UserRole).value<void *>()); + if (tc == m_buildConfiguration->toolChain()) { m_ignoreChange = true; m_ui->toolChainComboBox->setCurrentIndex(i); m_ignoreChange = false; @@ -453,29 +469,38 @@ void Qt4ProjectConfigWidget::toolChainTypeChanged() void Qt4ProjectConfigWidget::updateToolChainCombo() { m_ui->toolChainComboBox->clear(); - QList<ProjectExplorer::ToolChainType> toolchains = - m_buildConfiguration->qtVersion()->possibleToolChainTypes(); - - toolchains = m_buildConfiguration->qt4Target()->filterToolChainTypes(toolchains); - - foreach (ProjectExplorer::ToolChainType toolchain, toolchains) - m_ui->toolChainComboBox->addItem(ToolChain::toolChainName(toolchain), qVariantFromValue(toolchain)); - m_ui->toolChainComboBox->setEnabled(toolchains.size() > 1); + QList<ProjectExplorer::ToolChain *> toolchains = + m_buildConfiguration->qt4Target()->possibleToolChains(m_buildConfiguration); + foreach (ProjectExplorer::ToolChain *toolchain, toolchains) + m_ui->toolChainComboBox->addItem(toolchain->displayName(), + qVariantFromValue(static_cast<void *>(toolchain))); m_ignoreChange = true; - m_ui->toolChainComboBox->setCurrentIndex(toolchains.indexOf(m_buildConfiguration->toolChainType())); + if (!m_buildConfiguration->toolChain() || toolchains.isEmpty()) { + m_ui->toolChainComboBox->addItem(tr("<Invalid Toolchain>"), qVariantFromValue(static_cast<void *>(0))); + m_ui->toolChainComboBox->setCurrentIndex(m_ui->toolChainComboBox->count() - 1); + } else if (toolchains.contains(m_buildConfiguration->toolChain())) { + m_ui->toolChainComboBox->setCurrentIndex(toolchains.indexOf(m_buildConfiguration->toolChain())); + } else { // reset to some sensible toolchain + ToolChain *tc = 0; + if (!toolchains.isEmpty()) + tc = toolchains.at(0); + m_buildConfiguration->setToolChain(tc); + } m_ignoreChange = false; + m_ui->toolChainComboBox->setEnabled(toolchains.size() > 1); } void Qt4ProjectConfigWidget::toolChainSelected(int index) { if (m_ignoreChange) return; - ProjectExplorer::ToolChainType selectedToolChainType = - m_ui->toolChainComboBox->itemData(index, - Qt::UserRole).value<ProjectExplorer::ToolChainType>(); + ProjectExplorer::ToolChain *selectedToolChain = + static_cast<ProjectExplorer::ToolChain *>( + m_ui->toolChainComboBox->itemData(index, + Qt::UserRole).value<void *>()); m_ignoreChange = true; - m_buildConfiguration->setToolChainType(selectedToolChainType); + m_buildConfiguration->setToolChain(selectedToolChain); m_ignoreChange = false; updateDetails(); } diff --git a/src/plugins/qt4projectmanager/qt4projectconfigwidget.h b/src/plugins/qt4projectmanager/qt4projectconfigwidget.h index cf2227bb87..b4ae13b00e 100644 --- a/src/plugins/qt4projectmanager/qt4projectconfigwidget.h +++ b/src/plugins/qt4projectmanager/qt4projectconfigwidget.h @@ -72,18 +72,20 @@ private slots: void qtVersionSelected(const QString &); void toolChainSelected(int index); void manageQtVersions(); + void manageToolChains(); void importLabelClicked(); // Changes triggered from creator void qtVersionsChanged(); void qtVersionChanged(); void buildDirectoryChanged(); - void toolChainTypeChanged(); + void toolChainChanged(); void updateImportLabel(); void environmentChanged(); + void updateToolChainCombo(); + private: void updateDetails(); - void updateToolChainCombo(); void updateShadowBuildUi(); Ui::Qt4ProjectConfigWidget *m_ui; diff --git a/src/plugins/qt4projectmanager/qt4projectconfigwidget.ui b/src/plugins/qt4projectmanager/qt4projectconfigwidget.ui index 1bcb7177c9..7b40a1cfdb 100644 --- a/src/plugins/qt4projectmanager/qt4projectconfigwidget.ui +++ b/src/plugins/qt4projectmanager/qt4projectconfigwidget.ui @@ -56,7 +56,28 @@ </widget> </item> <item row="1" column="1"> - <widget class="QComboBox" name="toolChainComboBox"/> + <layout class="QHBoxLayout" name="horizontalLayout_3"> + <property name="spacing"> + <number>4</number> + </property> + <item> + <widget class="QComboBox" name="toolChainComboBox"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="manageToolChainPushButton"> + <property name="text"> + <string>Manage</string> + </property> + </widget> + </item> + </layout> </item> <item row="2" column="0"> <widget class="QLabel" name="shadowBuildLabel"> diff --git a/src/plugins/qt4projectmanager/qt4projectmanagerconstants.h b/src/plugins/qt4projectmanager/qt4projectmanagerconstants.h index 8456f32cb1..b796b6ac20 100644 --- a/src/plugins/qt4projectmanager/qt4projectmanagerconstants.h +++ b/src/plugins/qt4projectmanager/qt4projectmanagerconstants.h @@ -128,6 +128,12 @@ const char * const HARMATTAN_DEVICE_TARGET_ID = "Qt4ProjectManager.Target.Harmat const char * const MEEGO_DEVICE_TARGET_ID = "Qt4ProjectManager.Target.MeegoDeviceTarget"; const char * const QT_SIMULATOR_TARGET_ID = "Qt4ProjectManager.Target.QtSimulatorTarget"; +// ToolChains: +const char * const GCCE_TOOLCHAIN_ID = "Qt4ProjectManager.ToolChain.GCCE"; +const char * const MAEMO_TOOLCHAIN_ID = "Qt4ProjectManager.ToolChain.Maemo"; +const char * const RVCT_TOOLCHAIN_ID = "Qt4ProjectManager.ToolChain.RVCT"; +const char * const WINSCW_TOOLCHAIN_ID = "Qt4ProjectManager.ToolChain.WINSCW"; + // ICONS const char * const ICON_QT_PROJECT = ":/qt4projectmanager/images/qt_project.png"; const char * const ICON_WINDOW = ":/qt4projectmanager/images/window.png"; diff --git a/src/plugins/qt4projectmanager/qt4target.cpp b/src/plugins/qt4projectmanager/qt4target.cpp index 72712311ba..1549a670d9 100644 --- a/src/plugins/qt4projectmanager/qt4target.cpp +++ b/src/plugins/qt4projectmanager/qt4target.cpp @@ -43,6 +43,7 @@ #include <projectexplorer/buildsteplist.h> #include <projectexplorer/runconfiguration.h> #include <projectexplorer/customexecutablerunconfiguration.h> +#include <projectexplorer/toolchainmanager.h> #include <projectexplorer/projectexplorerconstants.h> using namespace Qt4ProjectManager; @@ -118,23 +119,32 @@ Qt4Project *Qt4BaseTarget::qt4Project() const return static_cast<Qt4Project *>(project()); } -QList<ProjectExplorer::ToolChainType> Qt4BaseTarget::filterToolChainTypes(const QList<ProjectExplorer::ToolChainType> &candidates) const +QString Qt4BaseTarget::defaultBuildDirectory() const { - return candidates; + Qt4BaseTargetFactory *fac = Qt4BaseTargetFactory::qt4BaseTargetFactoryForId(id()); + return fac->defaultShadowBuildDirectory(qt4Project()->defaultTopLevelBuildDirectory(), id()); } -ProjectExplorer::ToolChainType Qt4BaseTarget::preferredToolChainType(const QList<ProjectExplorer::ToolChainType> &candidates) const +QList<ProjectExplorer::ToolChain *> Qt4BaseTarget::possibleToolChains(ProjectExplorer::BuildConfiguration *bc) const { - ProjectExplorer::ToolChainType preferredType = ProjectExplorer::ToolChain_INVALID; - if (!candidates.isEmpty()) - preferredType = candidates.at(0); - return preferredType; -} + QList<ProjectExplorer::ToolChain *> tmp; + QList<ProjectExplorer::ToolChain *> result; -QString Qt4BaseTarget::defaultBuildDirectory() const -{ - Qt4BaseTargetFactory *fac = Qt4BaseTargetFactory::qt4BaseTargetFactoryForId(id()); - return fac->defaultShadowBuildDirectory(qt4Project()->defaultTopLevelBuildDirectory(), id()); + Qt4BuildConfiguration *qt4bc = qobject_cast<Qt4BuildConfiguration *>(bc); + if (!qt4bc && !qt4bc->qtVersion()->isValid()) + return tmp; + + QList<ProjectExplorer::Abi> abiList = qt4bc->qtVersion()->qtAbis(); + foreach (const ProjectExplorer::Abi &abi, abiList) + tmp.append(ProjectExplorer::ToolChainManager::instance()->findToolChains(abi)); + + foreach (ProjectExplorer::ToolChain *tc, tmp) { + if (result.contains(tc)) + continue; + if (tc->restrictedToTargets().isEmpty() || tc->restrictedToTargets().contains(id())) + result.append(tc); + } + return result; } void Qt4BaseTarget::removeUnconfiguredCustomExectutableRunConfigurations() @@ -191,8 +201,6 @@ Qt4BuildConfiguration *Qt4BaseTarget::addQt4BuildConfiguration(QString displayNa // Finally set the qt version & ToolChain bc->setQtVersion(qtversion); - ProjectExplorer::ToolChainType defaultTc = preferredToolChainType(filterToolChainTypes(bc->qtVersion()->possibleToolChainTypes())); - bc->setToolChainType(defaultTc); if (!directory.isEmpty()) bc->setShadowBuildAndDirectory(directory != project()->projectDirectory(), directory); addBuildConfiguration(bc); diff --git a/src/plugins/qt4projectmanager/qt4target.h b/src/plugins/qt4projectmanager/qt4target.h index 260fa6752c..a50015ceba 100644 --- a/src/plugins/qt4projectmanager/qt4target.h +++ b/src/plugins/qt4projectmanager/qt4target.h @@ -80,11 +80,12 @@ public: QString directory); virtual void createApplicationProFiles() = 0; - virtual QList<ProjectExplorer::ToolChainType> filterToolChainTypes(const QList<ProjectExplorer::ToolChainType> &candidates) const; - virtual ProjectExplorer::ToolChainType preferredToolChainType(const QList<ProjectExplorer::ToolChainType> &candidates) const; virtual QString defaultBuildDirectory() const; virtual QList<ProjectExplorer::RunConfiguration *> runConfigurationsForNode(ProjectExplorer::Node *n) = 0; + + QList<ProjectExplorer::ToolChain *> possibleToolChains(ProjectExplorer::BuildConfiguration *bc) const; + signals: void buildDirectoryInitialized(); /// emitted if the build configuration changed in a way that diff --git a/src/plugins/qt4projectmanager/qtoptionspage.cpp b/src/plugins/qt4projectmanager/qtoptionspage.cpp index bb4b33107b..bb4a3c1d60 100644 --- a/src/plugins/qt4projectmanager/qtoptionspage.cpp +++ b/src/plugins/qt4projectmanager/qtoptionspage.cpp @@ -44,8 +44,8 @@ #include "qmldebugginglibrary.h" #include "debugginghelperbuildtask.h" +#include <projectexplorer/abi.h> #include <projectexplorer/debugginghelper.h> -#include <projectexplorer/toolchaintype.h> #include <coreplugin/coreconstants.h> #include <coreplugin/icore.h> #include <coreplugin/progressmanager/progressmanager.h> @@ -151,15 +151,8 @@ QtOptionsPageWidget::QtOptionsPageWidget(QWidget *parent, QList<QtVersion *> ver m_versionUi->setupUi(versionInfoWidget); m_versionUi->qmakePath->setExpectedKind(Utils::PathChooser::File); m_versionUi->qmakePath->setPromptDialogTitle(tr("Select qmake Executable")); - m_versionUi->mingwPath->setExpectedKind(Utils::PathChooser::Directory); - m_versionUi->mingwPath->setPromptDialogTitle(tr("Select the MinGW Directory")); - m_versionUi->mwcPath->setExpectedKind(Utils::PathChooser::Directory); - m_versionUi->mwcPath->setPromptDialogTitle(tr("Select Carbide Install Directory")); m_versionUi->s60SDKPath->setExpectedKind(Utils::PathChooser::Directory); m_versionUi->s60SDKPath->setPromptDialogTitle(tr("Select S60 SDK Root")); - m_versionUi->gccePath->setExpectedKind(Utils::PathChooser::Directory); - m_versionUi->gccePath->setPromptDialogTitle(tr("Select the CSL ARM Toolchain (GCCE) Directory")); - QWidget *debuggingHelperDetailsWidget = new QWidget(); m_debuggingHelperUi->setupUi(debuggingHelperDetailsWidget); @@ -198,17 +191,10 @@ QtOptionsPageWidget::QtOptionsPageWidget(QWidget *parent, QList<QtVersion *> ver connect(m_versionUi->nameEdit, SIGNAL(textEdited(const QString &)), this, SLOT(updateCurrentQtName())); - connect(m_versionUi->qmakePath, SIGNAL(changed(QString)), this, SLOT(updateCurrentQMakeLocation())); - connect(m_versionUi->mingwPath, SIGNAL(changed(QString)), - this, SLOT(updateCurrentMingwDirectory())); - connect(m_versionUi->mwcPath, SIGNAL(changed(QString)), - this, SLOT(updateCurrentMwcDirectory())); connect(m_versionUi->s60SDKPath, SIGNAL(changed(QString)), this, SLOT(updateCurrentS60SDKDirectory())); - connect(m_versionUi->gccePath, SIGNAL(changed(QString)), - this, SLOT(updateCurrentGcceDirectory())); connect(m_versionUi->sbsV2Path, SIGNAL(changed(QString)), this, SLOT(updateCurrentSbsV2Directory())); @@ -219,13 +205,9 @@ QtOptionsPageWidget::QtOptionsPageWidget(QWidget *parent, QList<QtVersion *> ver connect(m_versionUi->qmakePath, SIGNAL(browsingFinished()), this, SLOT(onQtBrowsed())); - connect(m_versionUi->mingwPath, SIGNAL(browsingFinished()), - this, SLOT(onMingwBrowsed())); connect(m_ui->qtdirList, SIGNAL(currentItemChanged(QTreeWidgetItem *, QTreeWidgetItem *)), this, SLOT(versionChanged(QTreeWidgetItem *, QTreeWidgetItem *))); - connect(m_versionUi->msvcComboBox, SIGNAL(currentIndexChanged(int)), - this, SLOT(msvcVersionChanged())); connect(m_debuggingHelperUi->rebuildButton, SIGNAL(clicked()), this, SLOT(buildDebuggingHelper())); @@ -658,37 +640,17 @@ void QtOptionsPageWidget::updateState() m_ui->delButton->setEnabled(enabled && !isAutodetected); m_versionUi->nameEdit->setEnabled(enabled && !isAutodetected); m_versionUi->qmakePath->setEnabled(enabled && !isAutodetected); - m_versionUi->mingwPath->setEnabled(enabled); - m_versionUi->mwcPath->setEnabled(enabled); bool s60SDKPathEnabled = enabled && (isAutodetected ? version->s60SDKDirectory().isEmpty() : true); m_versionUi->s60SDKPath->setEnabled(s60SDKPathEnabled); - m_versionUi->gccePath->setEnabled(enabled); updateDebuggingHelperUi(); } -void QtOptionsPageWidget::makeMingwVisible(bool visible) -{ - m_versionUi->mingwLabel->setVisible(visible); - m_versionUi->mingwPath->setVisible(visible); -} - -void QtOptionsPageWidget::makeMSVCVisible(bool visible) -{ - m_versionUi->msvcLabel->setVisible(visible); - m_versionUi->msvcComboBox->setVisible(visible); - m_versionUi->msvcNotFoundLabel->setVisible(false); -} - void QtOptionsPageWidget::makeS60Visible(bool visible) { - m_versionUi->mwcLabel->setVisible(visible); - m_versionUi->mwcPath->setVisible(visible); m_versionUi->s60SDKLabel->setVisible(visible); m_versionUi->s60SDKPath->setVisible(visible); - m_versionUi->gcceLabel->setVisible(visible); - m_versionUi->gccePath->setVisible(visible); m_versionUi->sbsV2Label->setVisible(visible); m_versionUi->sbsV2Path->setVisible(visible); } @@ -697,66 +659,28 @@ void QtOptionsPageWidget::showEnvironmentPage(QTreeWidgetItem *item) { if (item) { int index = indexForTreeItem(item); - if (index < 0) { + QSharedPointerQtVersion qtVersion; + if (index >= 0) + qtVersion = m_versions.at(index); + + if (qtVersion.isNull() || !qtVersion->isValid()) { m_versionUi->errorLabel->setText(""); - makeMSVCVisible(false); - makeMingwVisible(false); makeS60Visible(false); return; } - const QSharedPointerQtVersion qtVersion = m_versions.at(index); - QList<ProjectExplorer::ToolChainType> types = qtVersion->possibleToolChainTypes(); - QSet<QString> targets = qtVersion->supportedTargetIds(); - if (types.isEmpty()) { - makeMSVCVisible(false); - makeMingwVisible(false); - makeS60Visible(false); - } else if (types.contains(ProjectExplorer::ToolChain_MinGW)) { - makeMSVCVisible(false); - makeMingwVisible(true); - makeS60Visible(false); - m_versionUi->mingwPath->setPath(m_versions.at(index)->mingwDirectory()); - } else if (types.contains(ProjectExplorer::ToolChain_MSVC) || - types.contains(ProjectExplorer::ToolChain_WINCE)) { - makeMSVCVisible(false); - makeMingwVisible(false); - makeS60Visible(false); - const QStringList msvcEnvironments = ProjectExplorer::ToolChain::availableMSVCVersions(qtVersion->isQt64Bit()); - if (msvcEnvironments.count() == 0) { - m_versionUi->msvcLabel->setVisible(true); - m_versionUi->msvcNotFoundLabel->setVisible(true); - } else { - makeMSVCVisible(true); - bool block = m_versionUi->msvcComboBox->blockSignals(true); - m_versionUi->msvcComboBox->clear(); - foreach(const QString &msvcenv, msvcEnvironments) { - m_versionUi->msvcComboBox->addItem(msvcenv); - if (msvcenv == m_versions.at(index)->msvcVersion()) { - m_versionUi->msvcComboBox->setCurrentIndex(m_versionUi->msvcComboBox->count() - 1); - } - } - m_versionUi->msvcComboBox->blockSignals(block); - } - } else if (targets.contains(Constants::S60_DEVICE_TARGET_ID) || - targets.contains(Constants::S60_EMULATOR_TARGET_ID)) { - makeMSVCVisible(false); - makeMingwVisible(false); + + ProjectExplorer::Abi qtAbi = qtVersion->qtAbis().at(0); + + if (qtAbi.os() == ProjectExplorer::Abi::Symbian) { makeS60Visible(true); - m_versionUi->mwcPath->setPath(QDir::toNativeSeparators(m_versions.at(index)->mwcDirectory())); m_versionUi->s60SDKPath->setPath(QDir::toNativeSeparators(m_versions.at(index)->s60SDKDirectory())); - m_versionUi->gccePath->setPath(QDir::toNativeSeparators(m_versions.at(index)->gcceDirectory())); m_versionUi->sbsV2Path->setPath(m_versions.at(index)->sbsV2Directory()); m_versionUi->sbsV2Path->setEnabled(m_versions.at(index)->isBuildWithSymbianSbsV2()); - } else { //ProjectExplorer::ToolChain::GCC - makeMSVCVisible(false); - makeMingwVisible(false); + } else { makeS60Visible(false); } - m_versionUi->errorLabel->setText(m_versions.at(index)->description()); } else { - makeMSVCVisible(false); - makeMingwVisible(false); makeS60Visible(false); } } @@ -816,16 +740,6 @@ void QtOptionsPageWidget::onQtBrowsed() updateState(); } -void QtOptionsPageWidget::onMingwBrowsed() -{ - const QString dir = m_versionUi->mingwPath->path(); - if (dir.isEmpty()) - return; - - updateCurrentMingwDirectory(); - updateState(); -} - void QtOptionsPageWidget::updateCurrentQtName() { QTreeWidgetItem *currentItem = m_ui->qtdirList->currentItem(); @@ -905,37 +819,6 @@ void QtOptionsPageWidget::updateCurrentQMakeLocation() } } -void QtOptionsPageWidget::updateCurrentMingwDirectory() -{ - QTreeWidgetItem *currentItem = m_ui->qtdirList->currentItem(); - Q_ASSERT(currentItem); - int currentItemIndex = indexForTreeItem(currentItem); - if (currentItemIndex < 0) - return; - m_versions[currentItemIndex]->setMingwDirectory(m_versionUi->mingwPath->path()); -} - -void QtOptionsPageWidget::msvcVersionChanged() -{ - const QString &msvcVersion = m_versionUi->msvcComboBox->currentText(); - QTreeWidgetItem *currentItem = m_ui->qtdirList->currentItem(); - Q_ASSERT(currentItem); - int currentItemIndex = indexForTreeItem(currentItem); - if (currentItemIndex < 0) - return; - m_versions[currentItemIndex]->setMsvcVersion(msvcVersion); -} - -void QtOptionsPageWidget::updateCurrentMwcDirectory() -{ - QTreeWidgetItem *currentItem = m_ui->qtdirList->currentItem(); - Q_ASSERT(currentItem); - int currentItemIndex = indexForTreeItem(currentItem); - if (currentItemIndex < 0) - return; - m_versions[currentItemIndex]->setMwcDirectory( - QDir::fromNativeSeparators(m_versionUi->mwcPath->path())); -} void QtOptionsPageWidget::updateCurrentS60SDKDirectory() { QTreeWidgetItem *currentItem = m_ui->qtdirList->currentItem(); @@ -947,17 +830,6 @@ void QtOptionsPageWidget::updateCurrentS60SDKDirectory() QDir::fromNativeSeparators(m_versionUi->s60SDKPath->path())); } -void QtOptionsPageWidget::updateCurrentGcceDirectory() -{ - QTreeWidgetItem *currentItem = m_ui->qtdirList->currentItem(); - Q_ASSERT(currentItem); - int currentItemIndex = indexForTreeItem(currentItem); - if (currentItemIndex < 0) - return; - m_versions[currentItemIndex]->setGcceDirectory( - QDir::fromNativeSeparators(m_versionUi->gccePath->path())); -} - void QtOptionsPageWidget::updateCurrentSbsV2Directory() { QTreeWidgetItem *currentItem = m_ui->qtdirList->currentItem(); @@ -986,11 +858,7 @@ QString QtOptionsPageWidget::searchKeywords() const QTextStream(&rc) << sep << m_versionUi->versionNameLabel->text() << sep << m_versionUi->pathLabel->text() - << sep << m_versionUi->mingwLabel->text() - << sep << m_versionUi->msvcLabel->text() << sep << m_versionUi->s60SDKLabel->text() - << sep << m_versionUi->gcceLabel->text() - << sep << m_versionUi->mwcLabel->text() << sep << m_versionUi->sbsV2Label->text() << sep << m_debuggingHelperUi->gdbHelperLabel->text() << sep << m_debuggingHelperUi->qmlDumpLabel->text() diff --git a/src/plugins/qt4projectmanager/qtoptionspage.h b/src/plugins/qt4projectmanager/qtoptionspage.h index b87ee99db0..d6b175c0e7 100644 --- a/src/plugins/qt4projectmanager/qtoptionspage.h +++ b/src/plugins/qt4projectmanager/qtoptionspage.h @@ -94,20 +94,13 @@ private slots: void addQtDir(); void removeQtDir(); void updateState(); - void makeMingwVisible(bool visible); - void makeMSVCVisible(bool visible); void makeS60Visible(bool visible); void onQtBrowsed(); - void onMingwBrowsed(); void updateCurrentQtName(); void updateCurrentQMakeLocation(); - void updateCurrentMingwDirectory(); - void updateCurrentMwcDirectory(); void updateCurrentS60SDKDirectory(); - void updateCurrentGcceDirectory(); void updateCurrentSbsV2Directory(); void updateDebuggingHelperUi(); - void msvcVersionChanged(); void buildDebuggingHelper(DebuggingHelperBuildTask::Tools tools = DebuggingHelperBuildTask::AllTools); void buildGdbHelper(); diff --git a/src/plugins/qt4projectmanager/qtparser.h b/src/plugins/qt4projectmanager/qtparser.h index a4296f05fd..f3fb5e402c 100644 --- a/src/plugins/qt4projectmanager/qtparser.h +++ b/src/plugins/qt4projectmanager/qtparser.h @@ -47,7 +47,7 @@ class QtParser : public ProjectExplorer::IOutputParser public: QtParser(); - virtual void stdError(const QString &line); + void stdError(const QString &line); private: QRegExp m_mocRegExp; diff --git a/src/plugins/qt4projectmanager/qtversioninfo.ui b/src/plugins/qt4projectmanager/qtversioninfo.ui index c3d37f6e11..6d77a10899 100644 --- a/src/plugins/qt4projectmanager/qtversioninfo.ui +++ b/src/plugins/qt4projectmanager/qtversioninfo.ui @@ -7,7 +7,7 @@ <x>0</x> <y>0</y> <width>404</width> - <height>197</height> + <height>105</height> </rect> </property> <layout class="QGridLayout"> @@ -34,97 +34,33 @@ <item row="2" column="1"> <widget class="Utils::PathChooser" name="qmakePath" native="true"/> </item> - <item row="3" column="0"> - <widget class="QLabel" name="mingwLabel"> - <property name="text"> - <string>MinGW directory:</string> - </property> - </widget> - </item> - <item row="3" column="1"> - <widget class="Utils::PathChooser" name="mingwPath" native="true"/> - </item> <item row="4" column="0"> - <widget class="QLabel" name="msvcLabel"> - <property name="text"> - <string>Toolchain:</string> - </property> - </widget> - </item> - <item row="6" column="0"> <widget class="QLabel" name="s60SDKLabel"> <property name="text"> <string>S60 SDK:</string> </property> </widget> </item> - <item row="6" column="1"> + <item row="4" column="1"> <widget class="Utils::PathChooser" name="s60SDKPath" native="true"/> </item> - <item row="7" column="0"> - <widget class="QLabel" name="gcceLabel"> - <property name="text"> - <string>CSL/GCCE directory:</string> - </property> - </widget> - </item> - <item row="7" column="1"> - <widget class="Utils::PathChooser" name="gccePath" native="true"/> - </item> - <item row="8" column="0"> - <widget class="QLabel" name="mwcLabel"> - <property name="text"> - <string>Carbide directory:</string> - </property> - </widget> - </item> - <item row="8" column="1"> - <widget class="Utils::PathChooser" name="mwcPath" native="true"/> - </item> - <item row="9" column="0"> + <item row="5" column="0"> <widget class="QLabel" name="sbsV2Label"> <property name="text"> <string>SBS v2 directory:</string> </property> </widget> </item> - <item row="9" column="1"> + <item row="5" column="1"> <widget class="Utils::PathChooser" name="sbsV2Path" native="true"/> </item> - <item row="10" column="0" colspan="2"> + <item row="6" column="0" colspan="2"> <widget class="QLabel" name="errorLabel"> <property name="text"> <string/> </property> </widget> </item> - <item row="4" column="1"> - <layout class="QHBoxLayout" name="msvcHorizontalLayout"> - <item> - <widget class="QComboBox" name="msvcComboBox"> - <property name="sizePolicy"> - <sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - </widget> - </item> - <item> - <widget class="QLabel" name="msvcNotFoundLabel"> - <property name="sizePolicy"> - <sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="text"> - <string>Unable to detect MSVC version.</string> - </property> - </widget> - </item> - </layout> - </item> </layout> </widget> <customwidgets> diff --git a/src/plugins/qt4projectmanager/qtversionmanager.cpp b/src/plugins/qt4projectmanager/qtversionmanager.cpp index 9543c89dac..58e9e457f6 100644 --- a/src/plugins/qt4projectmanager/qtversionmanager.cpp +++ b/src/plugins/qt4projectmanager/qtversionmanager.cpp @@ -43,6 +43,8 @@ #include "qt-s60/s60projectchecker.h" #include "qt-s60/abldparser.h" #include "qt-s60/sbsv2parser.h" +#include "qt-s60/gccetoolchain.h" +#include "qt-s60/winscwtoolchain.h" #include "qmlobservertool.h" #include "qmldumptool.h" @@ -52,7 +54,10 @@ #include <projectexplorer/gnumakeparser.h> #include <projectexplorer/projectexplorer.h> #include <projectexplorer/projectexplorerconstants.h> +#include <projectexplorer/toolchainmanager.h> #include <projectexplorer/cesdkhandler.h> +#include <projectexplorer/gcctoolchain.h> +#include <projectexplorer/toolchainmanager.h> #include <utils/synchronousprocess.h> #include <coreplugin/coreconstants.h> #include <coreplugin/icore.h> @@ -85,6 +90,24 @@ static const char *PATH_AUTODETECTION_SOURCE = "PATH"; enum { debug = 0 }; +template<class T> +static T *createToolChain(const QString &id) +{ + QList<ProjectExplorer::ToolChainFactory *> factories = + ExtensionSystem::PluginManager::instance()->getObjects<ProjectExplorer::ToolChainFactory>(); + foreach (ProjectExplorer::ToolChainFactory *f, factories) { + if (f->id() == id) { + Q_ASSERT(f->canCreate()); + return static_cast<T *>(f->create()); + } + } + return 0; +} + +// -------------------------------------------------------------------------- +// QtVersionManager +// -------------------------------------------------------------------------- + QtVersionManager *QtVersionManager::m_self = 0; QtVersionManager::QtVersionManager() @@ -136,12 +159,40 @@ QtVersionManager::QtVersionManager() id, isAutodetected, autodetectionSource); - version->setMingwDirectory(s->value("MingwDirectory").toString()); - version->setMsvcVersion(s->value("msvcVersion").toString()); - version->setMwcDirectory(s->value("MwcDirectory").toString()); version->setS60SDKDirectory(s->value("S60SDKDirectory").toString()); - version->setGcceDirectory(s->value("GcceDirectory").toString()); version->setSbsV2Directory(s->value(QLatin1String("SBSv2Directory")).toString()); + + // Update from 2.1 or earlier: + QString mingwDir = s->value(QLatin1String("MingwDirectory")).toString(); + if (!mingwDir.isEmpty()) { + ProjectExplorer::MingwToolChain *tc = createToolChain<ProjectExplorer::MingwToolChain>(ProjectExplorer::Constants::MINGW_TOOLCHAIN_ID); + if (tc) { + tc->setCompilerPath(QDir::fromNativeSeparators(mingwDir) + QLatin1String("/bin/gcc.exe")); + tc->setDisplayName(tr("Mingw from %1").arg(version->displayName())); + ProjectExplorer::ToolChainManager::instance()->registerToolChain(tc); + } + } + QString mwcDir = s->value(QLatin1String("MwcDirectory")).toString(); + if (!mwcDir.isEmpty()) { + WinscwToolChain *tc = createToolChain<WinscwToolChain>(Constants::WINSCW_TOOLCHAIN_ID); + if (tc) { + tc->setCompilerPath(QDir::fromNativeSeparators(mwcDir) + + QLatin1String("/x86Build/Symbian_Tools/Command_Line_Tools/mwwinrc.exe")); + tc->setDisplayName(tr("WINSCW from %1").arg(version->displayName())); + ProjectExplorer::ToolChainManager::instance()->registerToolChain(tc); + } + } + QString gcceDir = s->value(QLatin1String("GcceDirectory")).toString(); + if (!gcceDir.isEmpty()) { + GcceToolChain *tc = createToolChain<GcceToolChain>(Constants::GCCE_TOOLCHAIN_ID); + if (tc) { + tc->setCompilerPath(QDir::fromNativeSeparators(gcceDir) + + QLatin1String("/bin/arm-none-symbianelf-g++.exe")); + tc->setDisplayName(tr("GCCE from %1").arg(version->displayName())); + ProjectExplorer::ToolChainManager::instance()->registerToolChain(tc); + } + } + m_versions.append(version); } s->endArray(); @@ -309,14 +360,10 @@ void QtVersionManager::writeVersionsIntoSettings() s->setValue("Path", version->versionInfo().value("QT_INSTALL_DATA")); s->setValue("QMakePath", version->qmakeCommand()); s->setValue("Id", version->uniqueId()); - s->setValue("MingwDirectory", version->mingwDirectory()); - s->setValue("msvcVersion", version->msvcVersion()); s->setValue("isAutodetected", version->isAutodetected()); if (version->isAutodetected()) s->setValue("autodetectionSource", version->autodetectionSource()); - s->setValue("MwcDirectory", version->mwcDirectory()); s->setValue("S60SDKDirectory", version->s60SDKDirectory()); - s->setValue("GcceDirectory", version->gcceDirectory()); s->setValue(QLatin1String("SBSv2Directory"), version->sbsV2Directory()); } s->endArray(); @@ -352,13 +399,14 @@ QtVersion *QtVersionManager::version(int id) const return m_emptyVersion; } +// FIXME: Rework this! void QtVersionManager::addNewVersionsFromInstaller() { // Add new versions which may have been installed by the WB installer in the form: // NewQtVersions="qt 4.3.2=c:\\qt\\qt432\bin\qmake.exe;qt embedded=c:\\qtembedded;" - // or NewQtVersions="qt 4.3.2=c:\\qt\\qt432bin\qmake.exe=c:\\qtcreator\\mingw\\=MSVCName; + // or NewQtVersions="qt 4.3.2=c:\\qt\\qt432bin\qmake.exe; // i.e. - // NewQtVersions="versionname=pathtoversion=mingw=s60sdk=gcce=carbide;" + // NewQtVersions="versionname=pathtoversion=s60sdk;" // Duplicate entries are not added, the first new version is set as default. QSettings *settings = Core::ICore::instance()->settings(); QSettings *globalSettings = Core::ICore::instance()->settings(QSettings::SystemScope); @@ -388,17 +436,9 @@ void QtVersionManager::addNewVersionsFromInstaller() if (QFile::exists(newVersionData[1])) { QtVersion *version = new QtVersion(newVersionData[0], newVersionData[1], m_idcount++ ); if (newVersionData.count() >= 3) - version->setMingwDirectory(newVersionData[2]); + version->setS60SDKDirectory(QDir::fromNativeSeparators(newVersionData[2])); if (newVersionData.count() >= 4) - version->setS60SDKDirectory(QDir::fromNativeSeparators(newVersionData[3])); - if (newVersionData.count() >= 5) - version->setGcceDirectory(QDir::fromNativeSeparators(newVersionData[4])); - if (newVersionData.count() >= 6) - version->setMwcDirectory(QDir::fromNativeSeparators(newVersionData[5])); - if (newVersionData.count() >= 7) - version->setMsvcVersion(newVersionData[6]); - if (newVersionData.count() >= 8) - version->setSbsV2Directory(QDir::fromNativeSeparators(newVersionData[7])); + version->setSbsV2Directory(QDir::fromNativeSeparators(newVersionData[3])); bool versionWasAlreadyInList = false; foreach(const QtVersion * const it, m_versions) { @@ -467,10 +507,6 @@ bool QtVersionManager::equals(QtVersion *a, QtVersion *b) return false; if (a->m_id != b->m_id) return false; - if (a->m_mingwDirectory != b->m_mingwDirectory - || a->m_msvcVersion != b->m_msvcVersion - || a->m_mwcDirectory != b->m_mwcDirectory) - return false; if (a->m_displayName != b->displayName()) return false; return true; @@ -538,9 +574,9 @@ void QtVersionManager::setNewQtVersions(QList<QtVersion *> newVersions) emit qtVersionsChanged(changedVersions); } -/// -/// QtVersion -/// +// -------------------------------------------------------------------------- +// QtVersion +// -------------------------------------------------------------------------- QtVersion::QtVersion(const QString &name, const QString &qmakeCommand, int id, bool isAutodetected, const QString &autodetectionSource) @@ -551,15 +587,14 @@ QtVersion::QtVersion(const QString &name, const QString &qmakeCommand, int id, m_hasQmlDump(false), m_hasQmlDebuggingLibrary(false), m_hasQmlObserver(false), - m_toolChainUpToDate(false), + m_abiUpToDate(false), m_versionInfoUpToDate(false), m_notInstalled(false), m_defaultConfigIsDebug(true), m_defaultConfigIsDebugAndRelease(true), m_hasExamples(false), m_hasDemos(false), - m_hasDocumentation(false), - m_isBuildUsingSbsV2(false) + m_hasDocumentation(false) { if (id == -1) m_id = getUniqueId(); @@ -577,15 +612,14 @@ QtVersion::QtVersion(const QString &name, const QString &qmakeCommand, m_hasQmlDump(false), m_hasQmlDebuggingLibrary(false), m_hasQmlObserver(false), - m_toolChainUpToDate(false), + m_abiUpToDate(false), m_versionInfoUpToDate(false), m_notInstalled(false), m_defaultConfigIsDebug(true), m_defaultConfigIsDebugAndRelease(true), m_hasExamples(false), m_hasDemos(false), - m_hasDocumentation(false), - m_isBuildUsingSbsV2(false) + m_hasDocumentation(false) { m_id = getUniqueId(); setQMakeCommand(qmakeCommand); @@ -599,15 +633,14 @@ QtVersion::QtVersion(const QString &qmakeCommand, bool isAutodetected, const QSt m_hasQmlDump(false), m_hasQmlDebuggingLibrary(false), m_hasQmlObserver(false), - m_toolChainUpToDate(false), + m_abiUpToDate(false), m_versionInfoUpToDate(false), m_notInstalled(false), m_defaultConfigIsDebug(true), m_defaultConfigIsDebugAndRelease(true), m_hasExamples(false), m_hasDemos(false), - m_hasDocumentation(false), - m_isBuildUsingSbsV2(false) + m_hasDocumentation(false) { m_id = getUniqueId(); setQMakeCommand(qmakeCommand); @@ -621,20 +654,18 @@ QtVersion::QtVersion() m_hasQmlDump(false), m_hasQmlDebuggingLibrary(false), m_hasQmlObserver(false), - m_toolChainUpToDate(false), + m_abiUpToDate(false), m_versionInfoUpToDate(false), m_notInstalled(false), m_defaultConfigIsDebug(true), m_defaultConfigIsDebugAndRelease(true), m_hasExamples(false), m_hasDemos(false), - m_hasDocumentation(false), - m_isBuildUsingSbsV2(false) + m_hasDocumentation(false) { setQMakeCommand(QString()); } - QtVersion::~QtVersion() { } @@ -646,30 +677,39 @@ QString QtVersion::toHtml() const str << "<html><body><table>"; str << "<tr><td><b>" << QtVersionManager::tr("Name:") << "</b></td><td>" << displayName() << "</td></tr>"; - str << "<tr><td><b>" << QtVersionManager::tr("Source:") - << "</b></td><td>" << sourcePath() << "</td></tr>"; - str << "<tr><td><b>" << QtVersionManager::tr("mkspec:") - << "</b></td><td>" << mkspec() << "</td></tr>"; - str << "<tr><td><b>" << QtVersionManager::tr("qmake:") - << "</b></td><td>" << m_qmakeCommand << "</td></tr>"; - updateToolChainAndMkspec(); - if (m_defaultConfigIsDebug || m_defaultConfigIsDebugAndRelease) { - str << "<tr><td><b>" << QtVersionManager::tr("Default:") << "</b></td><td>" - << (m_defaultConfigIsDebug ? "debug" : "release"); - if (m_defaultConfigIsDebugAndRelease) - str << " debug_and_release"; - str << "</td></tr>"; - } // default config. - str << "<tr><td><b>" << QtVersionManager::tr("Version:") - << "</b></td><td>" << qtVersionString() << "</td></tr>"; - if (hasDebuggingHelper()) - str << "<tr><td><b>" << QtVersionManager::tr("Debugging helper:") - << "</b></td><td>" << debuggingHelperLibrary() << "</td></tr>"; - const QHash<QString,QString> vInfo = versionInfo(); - if (!vInfo.isEmpty()) { - const QHash<QString,QString>::const_iterator vcend = vInfo.constEnd(); - for (QHash<QString,QString>::const_iterator it = vInfo.constBegin(); it != vcend; ++it) - str << "<tr><td><pre>" << it.key() << "</pre></td><td>" << it.value() << "</td></tr>"; + if (!isValid()) { + str << "<tr><td colspan=2><b>" + QtVersionManager::tr("Invalid Qt version") +"</b></td></tr>"; + } else { + QString prefix = QLatin1String("<tr><td><b>") + QtVersionManager::tr("ABI:") + QLatin1String("</b></td>"); + foreach (const ProjectExplorer::Abi &abi, qtAbis()) { + str << prefix << "<td>" << abi.toString() << "</td></tr>"; + prefix = QLatin1String("<tr><td></td>"); + } + str << "<tr><td><b>" << QtVersionManager::tr("Source:") + << "</b></td><td>" << sourcePath() << "</td></tr>"; + str << "<tr><td><b>" << QtVersionManager::tr("mkspec:") + << "</b></td><td>" << mkspec() << "</td></tr>"; + str << "<tr><td><b>" << QtVersionManager::tr("qmake:") + << "</b></td><td>" << m_qmakeCommand << "</td></tr>"; + updateAbiAndMkspec(); + if (m_defaultConfigIsDebug || m_defaultConfigIsDebugAndRelease) { + str << "<tr><td><b>" << QtVersionManager::tr("Default:") << "</b></td><td>" + << (m_defaultConfigIsDebug ? "debug" : "release"); + if (m_defaultConfigIsDebugAndRelease) + str << " debug_and_release"; + str << "</td></tr>"; + } // default config. + str << "<tr><td><b>" << QtVersionManager::tr("Version:") + << "</b></td><td>" << qtVersionString() << "</td></tr>"; + if (hasDebuggingHelper()) + str << "<tr><td><b>" << QtVersionManager::tr("Debugging helper:") + << "</b></td><td>" << debuggingHelperLibrary() << "</td></tr>"; + const QHash<QString,QString> vInfo = versionInfo(); + if (!vInfo.isEmpty()) { + const QHash<QString,QString>::const_iterator vcend = vInfo.constEnd(); + for (QHash<QString,QString>::const_iterator it = vInfo.constBegin(); it != vcend; ++it) + str << "<tr><td><pre>" << it.key() << "</pre></td><td>" << it.value() << "</td></tr>"; + } } str << "</table></body></html>"; return rc; @@ -768,19 +808,19 @@ QString QtVersion::sourcePath() const QString QtVersion::mkspec() const { - updateToolChainAndMkspec(); + updateAbiAndMkspec(); return m_mkspec; } QString QtVersion::mkspecPath() const { - updateToolChainAndMkspec(); + updateAbiAndMkspec(); return m_mkspecFullPath; } bool QtVersion::isBuildWithSymbianSbsV2() const { - updateToolChainAndMkspec(); + updateAbiAndMkspec(); return m_isBuildUsingSbsV2; } @@ -840,7 +880,7 @@ void QtVersion::setQMakeCommand(const QString& qmakeCommand) m_linguistCommand.clear(); m_qmlviewerCommand.clear(); m_uicCommand.clear(); - m_toolChainUpToDate = false; + m_abiUpToDate = false; // TODO do i need to optimize this? m_versionInfoUpToDate = false; m_qtVersionString = QString(); @@ -1306,15 +1346,50 @@ QString QtVersion::qmlviewerCommand() const return m_qmlviewerCommand; } +QString QtVersion::systemRoot() const +{ + if (m_systemRoot.isNull()) { + if (supportsTargetId(Constants::S60_DEVICE_TARGET_ID) + || supportsTargetId(Constants::S60_EMULATOR_TARGET_ID)) { + S60Devices::Device device = S60Manager::instance()->deviceForQtVersion(this); + + m_systemRoot = device.epocRoot; + if (!m_systemRoot.endsWith(QLatin1Char('/'))) + m_systemRoot.append(QLatin1Char('/')); + + } else if (supportsTargetId(Constants::MAEMO5_DEVICE_TARGET_ID) || + supportsTargetId(Constants::HARMATTAN_DEVICE_TARGET_ID)) { + QFile file(QDir::cleanPath(MaemoGlobal::targetRoot(this)) + + QLatin1String("/information")); + if (file.exists() && file.open(QIODevice::ReadOnly | QIODevice::Text)) { + QTextStream stream(&file); + while (!stream.atEnd()) { + const QString &line = stream.readLine().trimmed(); + const QStringList &list = line.split(QLatin1Char(' ')); + if (list.count() <= 1) + continue; + if (list.at(0) == QLatin1String("sysroot")) { + m_systemRoot = MaemoGlobal::maddeRoot(this) + + QLatin1String("/sysroots/") + list.at(1); + } + } + } + } + if (m_systemRoot.isNull()) + m_systemRoot = QLatin1String(""); + } + return m_systemRoot; +} + bool QtVersion::supportsTargetId(const QString &id) const { - updateToolChainAndMkspec(); + updateAbiAndMkspec(); return m_targetIds.contains(id); } QSet<QString> QtVersion::supportedTargetIds() const { - updateToolChainAndMkspec(); + updateAbiAndMkspec(); return m_targetIds; } @@ -1328,42 +1403,20 @@ bool QtVersion::supportsMobileTarget() const supportsTargetId(Constants::QT_SIMULATOR_TARGET_ID); } -QList<QSharedPointer<ProjectExplorer::ToolChain> > QtVersion::toolChains() const +QList<ProjectExplorer::Abi> QtVersion::qtAbis() const { - updateToolChainAndMkspec(); - return m_toolChains; -} - -ProjectExplorer::ToolChain *QtVersion::toolChain(ProjectExplorer::ToolChainType type) const -{ - foreach(const QSharedPointer<ProjectExplorer::ToolChain> &tcptr, toolChains()) - if (tcptr->type() == type) - return tcptr.data(); - return 0; -} - -QList<ProjectExplorer::ToolChainType> QtVersion::possibleToolChainTypes() const -{ - QList<ProjectExplorer::ToolChainType> types; - foreach(const QSharedPointer<ProjectExplorer::ToolChain> &tc, toolChains()) - types << tc->type(); - return types; + updateAbiAndMkspec(); + return m_abis; } // if none, then it's INVALID everywhere this function is called -void QtVersion::updateToolChainAndMkspec() const +void QtVersion::updateAbiAndMkspec() const { - typedef QSharedPointer<ProjectExplorer::ToolChain> ToolChainPtr; - if (m_toolChainUpToDate) + if (m_id == -1 || m_abiUpToDate) return; - m_toolChains.clear(); m_targetIds.clear(); - - if (!isValid()) { - m_targetIds.insert(Constants::DESKTOP_TARGET_ID); - return; - } + m_abis.clear(); // qDebug()<<"Finding mkspec for"<<qmakeCommand(); @@ -1446,11 +1499,8 @@ void QtVersion::updateToolChainAndMkspec() const } m_mkspec = mkspec; - m_isBuildUsingSbsV2 = false; -// qDebug()<<"mkspec for "<<qmakeCommand()<<" is "<<m_mkspec<<m_mkspecFullPath; - ProFileOption option; option.properties = versionInfo(); ProMessageHandler msgHandler(true); @@ -1467,74 +1517,62 @@ void QtVersion::updateToolChainAndMkspec() const QString makefileGenerator = evaluator.value("MAKEFILE_GENERATOR"); QString ce_sdk = evaluator.values("CE_SDK").join(QLatin1String(" ")); QString ce_arch = evaluator.value("CE_ARCH"); - QString qt_arch = evaluator.value("QT_ARCH"); + + + // Evaluate all the information we have: if (!ce_sdk.isEmpty() && !ce_arch.isEmpty()) { - QString wincePlatformName = ce_sdk + " (" + ce_arch + QLatin1Char(')'); - m_toolChains << ToolChainPtr(ProjectExplorer::ToolChain::createWinCEToolChain(msvcVersion(), wincePlatformName)); + // Treat windows CE as desktop. + m_abis.append(ProjectExplorer::Abi(ProjectExplorer::Abi::ARM, ProjectExplorer::Abi::Windows, + ProjectExplorer::Abi::Windows_ce, ProjectExplorer::Abi::Format_PE, false)); m_targetIds.insert(Constants::DESKTOP_TARGET_ID); } else if (makefileGenerator == QLatin1String("SYMBIAN_ABLD") || makefileGenerator == QLatin1String("SYMBIAN_SBSV2") || makefileGenerator == QLatin1String("SYMBIAN_UNIX")) { m_isBuildUsingSbsV2 = (makefileGenerator == QLatin1String("SYMBIAN_SBSV2")); - if (S60Manager *s60mgr = S60Manager::instance()) { -# ifdef Q_OS_WIN - m_targetIds.insert(QLatin1String(Constants::S60_DEVICE_TARGET_ID)); - m_toolChains << ToolChainPtr(s60mgr->createGCCEToolChain(this)); - if (S60Manager::hasRvct2Compiler()) - m_toolChains << ToolChainPtr(s60mgr->createRVCTToolChain(this, ProjectExplorer::ToolChain_RVCT2_ARMV5)) - << ToolChainPtr(s60mgr->createRVCTToolChain(this, ProjectExplorer::ToolChain_RVCT2_ARMV6)); - if (S60Manager::hasRvct4Compiler()) - m_toolChains << ToolChainPtr(s60mgr->createRVCTToolChain(this, ProjectExplorer::ToolChain_RVCT4_ARMV5)) - << ToolChainPtr(s60mgr->createRVCTToolChain(this, ProjectExplorer::ToolChain_RVCT4_ARMV6)); - if (!mwcDirectory().isEmpty()) { - m_toolChains << ToolChainPtr(s60mgr->createWINSCWToolChain(this)); - m_targetIds.insert(QLatin1String(Constants::S60_EMULATOR_TARGET_ID)); - } -# else - if (S60Manager::hasRvct2Compiler()) - m_toolChains << ToolChainPtr(s60mgr->createRVCTToolChain(this, ProjectExplorer::ToolChain_RVCT_ARMV5_GNUPOC)); - m_toolChains << ToolChainPtr(s60mgr->createGCCE_GnuPocToolChain(this)); + if (S60Manager::instance()) { + m_abis.append(ProjectExplorer::Abi(ProjectExplorer::Abi::ARM, ProjectExplorer::Abi::Symbian, + ProjectExplorer::Abi::UNKNOWN_OSFLAVOUR, + ProjectExplorer::Abi::Format_ELF, + 32)); m_targetIds.insert(QLatin1String(Constants::S60_DEVICE_TARGET_ID)); -# endif + m_targetIds.insert(QLatin1String(Constants::S60_EMULATOR_TARGET_ID)); } } else if (MaemoGlobal::isValidMaemo5QtVersion(this)) { - m_toolChains << ToolChainPtr(MaemoManager::instance().maemo5ToolChain(this)); + m_abis.append(ProjectExplorer::Abi(ProjectExplorer::Abi::ARM, ProjectExplorer::Abi::Linux, + ProjectExplorer::Abi::Linux_maemo, ProjectExplorer::Abi::Format_ELF, + 32)); m_targetIds.insert(QLatin1String(Constants::MAEMO5_DEVICE_TARGET_ID)); } else if (MaemoGlobal::isValidHarmattanQtVersion(this)) { - m_toolChains << ToolChainPtr(MaemoManager::instance().harmattanToolChain(this)); + m_abis.append(ProjectExplorer::Abi(ProjectExplorer::Abi::ARM, ProjectExplorer::Abi::Linux, + ProjectExplorer::Abi::Linux_harmattan, + ProjectExplorer::Abi::Format_ELF, + 32)); m_targetIds.insert(QLatin1String(Constants::HARMATTAN_DEVICE_TARGET_ID)); } else if (MaemoGlobal::isValidMeegoQtVersion(this)) { - m_toolChains << ToolChainPtr(MaemoManager::instance().meegoToolChain(this)); + m_abis.append(ProjectExplorer::Abi(ProjectExplorer::Abi::ARM, ProjectExplorer::Abi::Linux, + ProjectExplorer::Abi::Linux_meego, + ProjectExplorer::Abi::Format_ELF, 32)); m_targetIds.insert(QLatin1String(Constants::MEEGO_DEVICE_TARGET_ID)); - } else if (qmakeCXX == "cl" || qmakeCXX == "icl") { - // TODO proper support for intel cl. Detect matching VC version unless set. - if (m_msvcVersion.isEmpty()) - m_msvcVersion = ProjectExplorer::MSVCToolChain::findInstallationByMkSpec(isQt64Bit(), mkspec).name; - m_toolChains << ToolChainPtr( - ProjectExplorer::ToolChain::createMSVCToolChain(m_msvcVersion, isQt64Bit())); - m_targetIds.insert(QLatin1String(Constants::DESKTOP_TARGET_ID)); - } else if (qmakeCXX == "g++" && makefileGenerator == "MINGW") { - Utils::Environment env = Utils::Environment::systemEnvironment(); - //addToEnvironment(env); - env.prependOrSetPath(mingwDirectory() + "/bin"); - qmakeCXX = env.searchInPath(qmakeCXX); - m_toolChains << ToolChainPtr( - ProjectExplorer::ToolChain::createMinGWToolChain(qmakeCXX, mingwDirectory())); - m_targetIds.insert(QLatin1String(Constants::DESKTOP_TARGET_ID)); - } else if (qmakeCXX.contains("g++")) { // All g++ variants are treated as desktop g++ - // we should try to do a better job, but for now that's good enough - Utils::Environment env = Utils::Environment::systemEnvironment(); - //addToEnvironment(env); - qmakeCXX = env.searchInPath(qmakeCXX); - m_toolChains << ToolChainPtr(ProjectExplorer::ToolChain::createGccToolChain(qmakeCXX)); - m_targetIds.insert(QLatin1String(Constants::DESKTOP_TARGET_ID)); - } else if (qmakeCXX == QLatin1String("icpc")) { - m_toolChains << ToolChainPtr(ProjectExplorer::ToolChain::createLinuxIccToolChain()); + } else if (qmakeCXX.contains("g++") + || qmakeCXX == "cl" || qmakeCXX == "icl" // intel cl + || qmakeCXX == QLatin1String("icpc")) { + m_abis = ProjectExplorer::Abi::abisOfBinary(qtCorePath()); +#if defined (Q_OS_WIN) + if (makefileGenerator == "MINGW") { + QList<ProjectExplorer::Abi> tmp = m_abis; + m_abis.clear(); + foreach (const ProjectExplorer::Abi &abi, tmp) + m_abis.append(ProjectExplorer::Abi(abi.architecture(), abi.os(), ProjectExplorer::Abi::Windows_msys, + abi.binaryFormat(), abi.wordWidth())); + } +#endif m_targetIds.insert(QLatin1String(Constants::DESKTOP_TARGET_ID)); } - if (m_toolChains.isEmpty()) { - qDebug()<<"Could not create ToolChain for"<<m_mkspecFullPath<<qmakeCXX; - qDebug()<<"Qt Creator doesn't know about the system includes, nor the systems defines."; + + if (m_abis.isEmpty()) { + qDebug() << "Could not find ABI for" << m_mkspecFullPath << qmakeCXX; + qDebug() << "Qt Creator doesn't know about the system includes, " + "nor the systems defines."; } QStringList configValues = evaluator.values("CONFIG"); @@ -1554,7 +1592,7 @@ void QtVersion::updateToolChainAndMkspec() const } ProFileCacheManager::instance()->decRefCount(); - m_toolChainUpToDate = true; + m_abiUpToDate = true; } QString QtVersion::resolveLink(const QString &path) const @@ -1568,16 +1606,26 @@ QString QtVersion::resolveLink(const QString &path) const return f.filePath(); } -QString QtVersion::mwcDirectory() const +QString QtVersion::qtCorePath() const { - return m_mwcDirectory; -} + QString path = libraryInstallPath(); -void QtVersion::setMwcDirectory(const QString &directory) -{ - m_mwcDirectory = directory; - m_toolChainUpToDate = false; + QStringList toTest; + toTest << path + QLatin1String("/libQtCore.so.") + qtVersionString(); + toTest << path + QLatin1String("/libQtCore.so"); + toTest << path + QLatin1String("/QtCore.dll"); + toTest << path + QLatin1String("/QtCored.dll"); + toTest << path + QLatin1String("/QtCore4.dll"); + toTest << path + QLatin1String("/QtCored4.dll"); + toTest << path + QLatin1String("/QtCore.framework/QtCore"); + + foreach (const QString &path, toTest) { + if (QFileInfo(path).exists()) + return path; + } + return QString(); } + QString QtVersion::s60SDKDirectory() const { return m_s60SDKDirectory; @@ -1586,18 +1634,7 @@ QString QtVersion::s60SDKDirectory() const void QtVersion::setS60SDKDirectory(const QString &directory) { m_s60SDKDirectory = directory; - m_toolChainUpToDate = false; -} - -QString QtVersion::gcceDirectory() const -{ - return m_gcceDirectory; -} - -void QtVersion::setGcceDirectory(const QString &directory) -{ - m_gcceDirectory = directory; - m_toolChainUpToDate = false; + m_abiUpToDate = false; } QString QtVersion::sbsV2Directory() const @@ -1610,41 +1647,80 @@ void QtVersion::setSbsV2Directory(const QString &directory) m_sbsV2Directory = directory; } -QString QtVersion::mingwDirectory() const +void QtVersion::addToEnvironment(Utils::Environment &env) const { - return m_mingwDirectory; -} + // Generic: + env.set("QTDIR", QDir::toNativeSeparators(versionInfo().value("QT_INSTALL_DATA"))); + env.prependOrSetPath(versionInfo().value("QT_INSTALL_BINS")); -void QtVersion::setMingwDirectory(const QString &directory) -{ - m_mingwDirectory = directory; - m_toolChainUpToDate = false; -} + // Symbian specific: + if (supportsTargetId(Constants::S60_DEVICE_TARGET_ID) + || supportsTargetId(Constants::S60_EMULATOR_TARGET_ID)) { + // Generic Symbian environment: + QString epocRootPath(systemRoot()); + QDir epocDir(epocRootPath); + + if (!epocRootPath.endsWith(QLatin1Char('/'))) + epocRootPath.append(QLatin1Char('/')); + env.set(QLatin1String("EPOCROOT"), QDir::toNativeSeparators(S60Devices::cleanedRootPath(epocRootPath))); + + env.prependOrSetPath(epocDir.filePath(QLatin1String("epoc32/tools"))); // e.g. make.exe + // Windows only: + if (ProjectExplorer::Abi::hostAbi().os() == ProjectExplorer::Abi::Windows) { + QString winDir = QLatin1String(qgetenv("WINDIR")); + if (!winDir.isEmpty()) + env.prependOrSetPath(QDir(winDir).filePath(QLatin1String("system32"))); + + if (epocDir.exists(QLatin1String("epoc32/gcc/bin"))) + env.prependOrSetPath(epocDir.filePath(QLatin1String("epoc32/gcc/bin"))); // e.g. cpp.exe, *NOT* gcc.exe + // Find perl in the special Symbian flavour: + if (epocDir.exists(QLatin1String("../../tools/perl/bin"))) { + epocDir.cd(QLatin1String("../../tools/perl/bin")); + env.prependOrSetPath(epocDir.absolutePath()); + } else { + env.prependOrSetPath(epocDir.filePath(QLatin1String("perl/bin"))); + } + } -QString QtVersion::msvcVersion() const -{ - return m_msvcVersion; + // SBSv2: + if (isBuildWithSymbianSbsV2()) { + QString sbsHome(env.value(QLatin1String("SBS_HOME"))); + if (!m_sbsV2Directory.isEmpty()) { + env.prependOrSetPath(m_sbsV2Directory + QLatin1String("/bin")); + env.unset(QLatin1String("SBS_HOME")); // unset SBS_HOME to prevent SBS from picking it up + } else if (!sbsHome.isEmpty()) { + env.prependOrSetPath(sbsHome + QLatin1Char('/') + QLatin1String("bin")); + } + } + } } -void QtVersion::setMsvcVersion(const QString &version) -{ - m_msvcVersion = version; - m_toolChainUpToDate = false; -} +static const char *S60_EPOC_HEADERS[] = { + "include", "mkspecs/common/symbian", "epoc32/include", + "epoc32/include/osextensions/stdapis", "epoc32/include/osextensions/stdapis/sys", + "epoc32/include/stdapis", "epoc32/include/stdapis/sys", + "epoc32/include/osextensions/stdapis/stlport", "epoc32/include/stdapis/stlport", + "epoc32/include/oem", "epoc32/include/middleware", "epoc32/include/domain/middleware", + "epoc32/include/osextensions", "epoc32/include/domain/osextensions", + "epoc32/include/domain/osextensions/loc", "epoc32/include/domain/middleware/loc", + "epoc32/include/domain/osextensions/loc/sc", "epoc32/include/domain/middleware/loc/sc" +}; -void QtVersion::addToEnvironment(Utils::Environment &env) const -{ - env.set("QTDIR", QDir::toNativeSeparators(versionInfo().value("QT_INSTALL_DATA"))); - if (isBuildWithSymbianSbsV2()) { - QString sbsHome(env.value(QLatin1String("SBS_HOME"))); - if (!m_sbsV2Directory.isEmpty()) { - env.prependOrSetPath(m_sbsV2Directory); - env.unset(QLatin1String("SBS_HOME")); // unset SBS_HOME to prevent SBS from picking it up - } else if (!sbsHome.isEmpty()) { - env.prependOrSetPath(sbsHome + QLatin1Char('/') + QLatin1String("bin")); +QList<ProjectExplorer::HeaderPath> QtVersion::systemHeaderPathes() const +{ + QList<ProjectExplorer::HeaderPath> result; + if (supportsTargetId(Constants::S60_DEVICE_TARGET_ID) + || supportsTargetId(Constants::S60_EMULATOR_TARGET_ID)) { + QString root = systemRoot() + QLatin1Char('/'); + const int count = sizeof(S60_EPOC_HEADERS) / sizeof(const char *); + for (int i = 0; i < count; ++i) { + const QDir dir(root + QLatin1String(S60_EPOC_HEADERS[i])); + if (dir.exists()) + result.append(ProjectExplorer::HeaderPath(dir.absolutePath(), + ProjectExplorer::HeaderPath::GlobalHeaderPath)); } } - env.prependOrSetPath(versionInfo().value("QT_INSTALL_BINS")); + return result; } int QtVersion::uniqueId() const @@ -1660,12 +1736,15 @@ int QtVersion::getUniqueId() bool QtVersion::isValid() const { updateVersionInfo(); + updateAbiAndMkspec(); + return m_id != -1 && !qmakeCommand().isEmpty() && !displayName().isEmpty() && !m_notInstalled && m_versionInfo.contains("QT_INSTALL_BINS") - && (!m_mkspecFullPath.isEmpty() || !m_toolChainUpToDate); + && (!m_mkspecFullPath.isEmpty() || !m_abiUpToDate) + && !m_abis.isEmpty(); } QString QtVersion::invalidReason() const @@ -1681,7 +1760,7 @@ QString QtVersion::invalidReason() const if (!m_versionInfo.contains("QT_INSTALL_BINS")) return QCoreApplication::translate("QtVersion", "Could not determine the path to the binaries of the Qt installation, maybe the qmake path is wrong?"); - if (m_toolChainUpToDate && m_mkspecFullPath.isEmpty()) + if (m_abiUpToDate && m_mkspecFullPath.isEmpty()) return QCoreApplication::translate("QtVersion", "The default mkspec symlink is broken."); return QString(); } @@ -1690,8 +1769,6 @@ QString QtVersion::description() const { if (!isValid()) return invalidReason(); - if (possibleToolChainTypes().isEmpty()) - return QCoreApplication::translate("QtVersion", "This Qt Version has a unknown toolchain."); QSet<QString> targets = supportedTargetIds(); QString envs; if (targets.contains(Constants::DESKTOP_TARGET_ID)) @@ -1715,7 +1792,7 @@ QString QtVersion::description() const QtVersion::QmakeBuildConfigs QtVersion::defaultBuildConfig() const { - updateToolChainAndMkspec(); + updateAbiAndMkspec(); QtVersion::QmakeBuildConfigs result = QtVersion::QmakeBuildConfig(0); if (m_defaultConfigIsDebugAndRelease) @@ -1752,13 +1829,15 @@ bool QtVersion::hasQmlObserver() const Utils::Environment QtVersion::qmlToolsEnvironment() const { + // FIXME: This seems broken! Utils::Environment environment = Utils::Environment::systemEnvironment(); addToEnvironment(environment); // add preferred toolchain, as that is how the tools are built, compare QtVersion::buildDebuggingHelperLibrary - QList<QSharedPointer<ProjectExplorer::ToolChain> > alltc = toolChains(); + QList<ProjectExplorer::ToolChain *> alltc = + ProjectExplorer::ToolChainManager::instance()->findToolChains(qtAbis().at(0)); if (!alltc.isEmpty()) - alltc.first().data()->addToEnvironment(environment); + alltc.first()->addToEnvironment(environment); return environment; } @@ -1805,31 +1884,9 @@ QStringList QtVersion::debuggingHelperLibraryLocations() const bool QtVersion::supportsBinaryDebuggingHelper() const { - foreach (ProjectExplorer::ToolChainType type, possibleToolChainTypes()) - switch (type) { - case ProjectExplorer::ToolChain_GCC: - case ProjectExplorer::ToolChain_LINUX_ICC: - case ProjectExplorer::ToolChain_MinGW: - case ProjectExplorer::ToolChain_MSVC: - case ProjectExplorer::ToolChain_WINCE: - case ProjectExplorer::ToolChain_GCC_MAEMO5: - case ProjectExplorer::ToolChain_GCC_HARMATTAN: - case ProjectExplorer::ToolChain_GCC_MEEGO: - case ProjectExplorer::ToolChain_OTHER: - case ProjectExplorer::ToolChain_UNKNOWN: - return true; - case ProjectExplorer::ToolChain_WINSCW: - case ProjectExplorer::ToolChain_GCCE : - case ProjectExplorer::ToolChain_RVCT2_ARMV5: - case ProjectExplorer::ToolChain_RVCT2_ARMV6: - case ProjectExplorer::ToolChain_RVCT4_ARMV5: - case ProjectExplorer::ToolChain_RVCT4_ARMV6: - case ProjectExplorer::ToolChain_GCCE_GNUPOC: - case ProjectExplorer::ToolChain_RVCT_ARMV5_GNUPOC: - case ProjectExplorer::ToolChain_INVALID: - break; - } - return false; + if (!isValid()) + return false; + return qtAbis().at(0).os() != ProjectExplorer::Abi::Symbian; } bool QtVersion::hasDocumentation() const @@ -1872,6 +1929,12 @@ QString QtVersion::frameworkInstallPath() const #endif } +QString QtVersion::libraryInstallPath() const +{ + updateVersionInfo(); + return m_versionInfo["QT_INSTALL_LIBS"]; +} + bool QtVersion::hasExamples() const { updateVersionInfo(); @@ -1884,16 +1947,6 @@ QString QtVersion::examplesPath() const return m_versionInfo["QT_INSTALL_EXAMPLES"]; } -bool QtVersion::isQt64Bit() const -{ -#ifdef Q_OS_WIN - const QString qmake = qmakeCommand(); - return qmake.isEmpty() ? false : Utils::winIs64BitBinary(qmake); -#else - return false; -#endif -} - void QtVersion::invalidateCache() { m_versionInfoUpToDate = false; diff --git a/src/plugins/qt4projectmanager/qtversionmanager.h b/src/plugins/qt4projectmanager/qtversionmanager.h index 479382ef8e..a2daba6889 100644 --- a/src/plugins/qt4projectmanager/qtversionmanager.h +++ b/src/plugins/qt4projectmanager/qtversionmanager.h @@ -38,18 +38,15 @@ #include <projectexplorer/ioutputparser.h> #include <projectexplorer/taskwindow.h> -#include <projectexplorer/toolchain.h> +#include <projectexplorer/abi.h> #include <projectexplorer/task.h> +#include <projectexplorer/toolchain.h> #include <QtCore/QHash> #include <QtCore/QSet> #include <QtCore/QSharedPointer> #include <QtCore/QFutureInterface> -namespace ProjectExplorer { -class ToolChain; -} - namespace Utils { class Environment; } @@ -88,13 +85,13 @@ public: QString designerCommand() const; QString linguistCommand() const; QString qmlviewerCommand() const; + QString systemRoot() const; bool supportsTargetId(const QString &id) const; QSet<QString> supportedTargetIds() const; bool supportsMobileTarget() const; - QList<ProjectExplorer::ToolChainType> possibleToolChainTypes() const; - ProjectExplorer::ToolChain *toolChain(ProjectExplorer::ToolChainType type) const; + QList<ProjectExplorer::Abi> qtAbis() const; /// @returns the name of the mkspec, which is generally not enough /// to pass to qmake. @@ -114,28 +111,21 @@ public: // Returns the PREFIX, BINPREFIX, DOCPREFIX and similar information QHash<QString,QString> versionInfo() const; - QString mwcDirectory() const; - void setMwcDirectory(const QString &directory); QString s60SDKDirectory() const; void setS60SDKDirectory(const QString &directory); - QString gcceDirectory() const; - void setGcceDirectory(const QString &directory); QString sbsV2Directory() const; void setSbsV2Directory(const QString &directory); - QString mingwDirectory() const; - void setMingwDirectory(const QString &directory); - QString msvcVersion() const; - void setMsvcVersion(const QString &version); void addToEnvironment(Utils::Environment &env) const; + QList<ProjectExplorer::HeaderPath> systemHeaderPathes() const; + bool supportsBinaryDebuggingHelper() const; bool hasDebuggingHelper() const; QString debuggingHelperLibrary() const; QString qmlDebuggingHelperLibrary(bool debugVersion) const; QString qmlDumpTool(bool debugVersion) const; QString qmlObserverTool() const; QStringList debuggingHelperLibraryLocations() const; - bool supportsBinaryDebuggingHelper() const; bool hasQmlDump() const; bool hasQmlDebuggingLibrary() const; @@ -155,10 +145,10 @@ public: QString headerInstallPath() const; QString frameworkInstallPath() const; + QString libraryInstallPath() const; // All valid Ids are >= 0 int uniqueId() const; - bool isQt64Bit() const; enum QmakeBuildConfig { @@ -183,18 +173,17 @@ public: ProjectExplorer::IOutputParser *createOutputParser() const; private: - QList<QSharedPointer<ProjectExplorer::ToolChain> > toolChains() const; static int getUniqueId(); // Also used by QtOptionsPageWidget void updateSourcePath(); void updateVersionInfo() const; QString findQtBinary(const QStringList &possibleName) const; - void updateToolChainAndMkspec() const; + void updateAbiAndMkspec() const; QString resolveLink(const QString &path) const; + QString qtCorePath() const; + QString m_displayName; QString m_sourcePath; - QString m_mingwDirectory; - mutable QString m_msvcVersion; int m_id; bool m_isAutodetected; QString m_autodetectionSource; @@ -203,15 +192,14 @@ private: mutable bool m_hasQmlDebuggingLibrary; // controlled by m_versionInfoUpdate mutable bool m_hasQmlObserver; // controlled by m_versionInfoUpToDate - QString m_mwcDirectory; QString m_s60SDKDirectory; - QString m_gcceDirectory; QString m_sbsV2Directory; + mutable QString m_systemRoot; - mutable bool m_toolChainUpToDate; + mutable bool m_abiUpToDate; mutable QString m_mkspec; // updated lazily mutable QString m_mkspecFullPath; - mutable QList<QSharedPointer<ProjectExplorer::ToolChain> > m_toolChains; + mutable QList<ProjectExplorer::Abi> m_abis; mutable bool m_versionInfoUpToDate; mutable QHash<QString,QString> m_versionInfo; // updated lazily @@ -305,8 +293,7 @@ private: int getUniqueId(); void writeVersionsIntoSettings(); void addNewVersionsFromInstaller(); - void updateSystemVersion(); - void updateDocumentation(); + void updateSystemVersion(); void updateDocumentation(); static int indexOfVersionInList(const QtVersion * const version, const QList<QtVersion *> &list); void updateUniqueIdToIndexMap(); |