diff --git a/src/plugins/cmakeprojectmanager/cmakeproject.cpp b/src/plugins/cmakeprojectmanager/cmakeproject.cpp index 5569c900f2b49dbbe8c269f49a888c4d3f6e4f12..6e4cdfa59ecb625b1a1d479d5613cd9a991abc97 100644 --- a/src/plugins/cmakeprojectmanager/cmakeproject.cpp +++ b/src/plugins/cmakeprojectmanager/cmakeproject.cpp @@ -36,10 +36,13 @@ #include "cmakeprojectnodes.h" #include "cmakestep.h" #include "makestep.h" +#include "cmakerunconfiguration.h" #include <extensionsystem/pluginmanager.h> #include <cpptools/cppmodelmanagerinterface.h> +#include <QProcess> +#include <QDir> #include <QtCore/QDebug> using namespace CMakeProjectManager; @@ -48,20 +51,31 @@ using namespace CMakeProjectManager::Internal; CMakeProject::CMakeProject(CMakeManager *manager, const QString &fileName) : m_manager(manager), m_fileName(fileName), m_rootNode(new CMakeProjectNode(m_fileName)) { - //TODO + m_file = new CMakeFile(this, fileName); QDir dir = QFileInfo(m_fileName).absoluteDir(); QString cbpFile = findCbpFile(dir); if (cbpFile.isEmpty()) cbpFile = createCbpFile(dir); + //TODO move this parsing to a seperate method, which is also called if the CMakeList.txt is updated CMakeCbpParser cbpparser; if (cbpparser.parseCbpFile(cbpFile)) { + // TODO do a intelligent updating of the tree buildTree(m_rootNode, cbpparser.fileList()); foreach(ProjectExplorer::FileNode *fn, cbpparser.fileList()) m_files.append(fn->path()); m_files.sort(); + m_targets = cbpparser.targets(); + qDebug()<<"Printing targets"; + foreach(CMakeTarget ct, m_targets) { + qDebug()<<ct.title<<" with executable:"<<ct.executable; + qDebug()<<"WD:"<<ct.workingDirectory; + qDebug()<<ct.makeCommand<<ct.makeCleanCommand; + qDebug()<<""; + } + CppTools::CppModelManagerInterface *modelmanager = ExtensionSystem::PluginManager::instance()->getObject<CppTools::CppModelManagerInterface>(); if (modelmanager) { CppTools::CppModelManagerInterface::ProjectInfo pinfo = modelmanager->projectInfo(this); @@ -69,6 +83,7 @@ CMakeProject::CMakeProject(CMakeManager *manager, const QString &fileName) // TODO we only want C++ files, not all other stuff that might be in the project pinfo.sourceFiles = m_files; // TODO defines + // TODO gcc preprocessor files modelmanager->updateProjectInfo(pinfo); } } else { @@ -96,16 +111,20 @@ QString CMakeProject::findCbpFile(const QDir &directory) return QString::null; } - -QString CMakeProject::createCbpFile(const QDir &) +QString CMakeProject::createCbpFile(const QDir &directory) { - // TODO create a cbp file. - // Issue: Where to create it? We want to do that in the build directory - // but at this stage we don't know the build directory yet - // So create it in a temp directory? - // Issue: We want to reuse whatever CMakeCache.txt that is alread there, which - // would indicate, creating it in the build directory - // Or we could use a temp directory and use -C builddirectory + // We create a cbp file, only if we didn't find a cbp file in the base directory + // Yet that can still override cbp files in subdirectories + // And we are creating tons of files in the source directories + // All of that is not really nice. + // The mid term plan is to move away from the CodeBlocks Generator and use our own + // QtCreator generator, which actually can be very similar to the CodeBlock Generator + + // TODO we need to pass on the same paremeters as the cmakestep + QProcess cmake; + cmake.setWorkingDirectory(directory.absolutePath()); + cmake.start("cmake", QStringList() << "-GCodeBlocks - Unix Makefiles"); + return QString::null; } @@ -227,27 +246,35 @@ QStringList CMakeProject::files(FilesMode fileMode) const void CMakeProject::saveSettingsImpl(ProjectExplorer::PersistentSettingsWriter &writer) { // TODO - Q_UNUSED(writer); + Project::saveSettingsImpl(writer); } void CMakeProject::restoreSettingsImpl(ProjectExplorer::PersistentSettingsReader &reader) { // TODO - Q_UNUSED(reader); + Project::restoreSettingsImpl(reader); if (buildConfigurations().isEmpty()) { // No build configuration, adding those - - // TODO do we want to create one build configuration per target? - // or how do we want to handle that? - CMakeStep *cmakeStep = new CMakeStep(this); MakeStep *makeStep = new MakeStep(this); insertBuildStep(0, cmakeStep); insertBuildStep(1, makeStep); - addBuildConfiguration("all"); + // Create build configurations of m_targets + qDebug()<<"Create build configurations of m_targets"; + foreach(const CMakeTarget &ct, m_targets) { + addBuildConfiguration(ct.title); + makeStep->setValue(ct.title, "makeCommand", ct.makeCommand); + makeStep->setValue(ct.title, "makeCleanCommand", ct.makeCleanCommand); + + QSharedPointer<ProjectExplorer::RunConfiguration> rc(new CMakeRunConfiguration(this, ct.executable, ct.workingDirectory)); + // TODO set build configuration to build before it can be run + addRunConfiguration(rc); + setActiveRunConfiguration(rc); // TODO what exactly shall be the active run configuration? + } setActiveBuildConfiguration("all"); + } // Restoring is fine } @@ -394,14 +421,16 @@ void CMakeCbpParser::parseBuild() void CMakeCbpParser::parseTarget() { - m_targetOutput.clear(); m_targetType = false; + m_target.clear(); + + if (attributes().hasAttribute("title")) + m_target.title = attributes().value("title").toString(); while(!atEnd()) { readNext(); if (isEndElement()) { - if (m_targetType && !m_targetOutput.isEmpty()) { - qDebug()<<"found target "<<m_targetOutput; - m_targets.insert(m_targetOutput); + if (m_targetType || m_target.title == "all") { + m_targets.append(m_target); } return; } else if (name() == "Compiler") { @@ -417,9 +446,57 @@ void CMakeCbpParser::parseTarget() void CMakeCbpParser::parseTargetOption() { if (attributes().hasAttribute("output")) - m_targetOutput = attributes().value("output").toString(); + m_target.executable = attributes().value("output").toString(); else if (attributes().hasAttribute("type") && attributes().value("type") == "1") m_targetType = true; + else if (attributes().hasAttribute("working_dir")) + m_target.workingDirectory = attributes().value("working_dir").toString(); + while(!atEnd()) { + readNext(); + if (isEndElement()) { + return; + } else if (name() == "MakeCommand") { + parseMakeCommand(); + } else if (isStartElement()) { + parseUnknownElement(); + } + } +} + +void CMakeCbpParser::parseMakeCommand() +{ + while(!atEnd()) { + readNext(); + if (isEndElement()) { + return; + } else if (name() == "Build") { + parseTargetBuild(); + } else if (name() == "Clean") { + parseTargetClean(); + } else if (isStartElement()) { + parseUnknownElement(); + } + } +} + +void CMakeCbpParser::parseTargetBuild() +{ + if (attributes().hasAttribute("command")) + m_target.makeCommand = attributes().value("command").toString(); + while(!atEnd()) { + readNext(); + if (isEndElement()) { + return; + } else if (isStartElement()) { + parseUnknownElement(); + } + } +} + +void CMakeCbpParser::parseTargetClean() +{ + if (attributes().hasAttribute("command")) + m_target.makeCleanCommand = attributes().value("command").toString(); while(!atEnd()) { readNext(); if (isEndElement()) { @@ -497,3 +574,18 @@ QStringList CMakeCbpParser::includeFiles() { return m_includeFiles; } + +QList<CMakeTarget> CMakeCbpParser::targets() +{ + return m_targets; +} + +void CMakeTarget::clear() +{ + executable = QString::null; + makeCommand = QString::null; + makeCleanCommand = QString::null; + workingDirectory = QString::null; + title = QString::null; +} + diff --git a/src/plugins/cmakeprojectmanager/cmakeproject.h b/src/plugins/cmakeprojectmanager/cmakeproject.h index a0c821ada5ebbe5e61267fa3f41824fdbac9d119..2a0314fda1a2676c74d5190dc69ca8b50c728c2c 100644 --- a/src/plugins/cmakeprojectmanager/cmakeproject.h +++ b/src/plugins/cmakeprojectmanager/cmakeproject.h @@ -49,6 +49,16 @@ namespace Internal{ class CMakeFile; +struct CMakeTarget +{ + QString title; + QString executable; + QString workingDirectory; + QString makeCommand; + QString makeCleanCommand; + void clear(); +}; + class CMakeProject : public ProjectExplorer::Project { Q_OBJECT @@ -105,6 +115,7 @@ private: // TODO probably need a CMake specific node structure CMakeProjectNode* m_rootNode; QStringList m_files; + QList<CMakeTarget> m_targets; protected: virtual void saveSettingsImpl(ProjectExplorer::PersistentSettingsWriter &writer); @@ -118,23 +129,27 @@ public: bool parseCbpFile(const QString &fileName); QList<ProjectExplorer::FileNode *> fileList(); QStringList includeFiles(); + QList<CMakeTarget> targets(); private: void parseCodeBlocks_project_file(); void parseProject(); void parseBuild(); void parseTarget(); void parseTargetOption(); + void parseMakeCommand(); + void parseTargetBuild(); + void parseTargetClean(); void parseCompiler(); void parseAdd(); void parseUnit(); void parseUnknownElement(); - QSet<QString> m_targets; QList<ProjectExplorer::FileNode *> m_fileList; QStringList m_includeFiles; - QString m_targetOutput; + CMakeTarget m_target; bool m_targetType; + QList<CMakeTarget> m_targets; }; class CMakeFile : public Core::IFile diff --git a/src/plugins/cmakeprojectmanager/cmakeprojectconstants.h b/src/plugins/cmakeprojectmanager/cmakeprojectconstants.h index 4832f17f26383d9deab8e48d2f9820068e95fa0e..713005899155864cacd987ade0c869d71ca17296 100644 --- a/src/plugins/cmakeprojectmanager/cmakeprojectconstants.h +++ b/src/plugins/cmakeprojectmanager/cmakeprojectconstants.h @@ -41,6 +41,7 @@ const char * const PROJECTCONTEXT = "CMakeProject.ProjectContext"; const char * const CMAKEMIMETYPE = "text/x-cmake"; // TOOD check that this is correct const char * const CMAKESTEP = "CMakeProjectManager.CMakeStep"; const char * const MAKESTEP = "CMakeProjectManager.MakeStep"; +const char * const CMAKERUNCONFIGURATION = "CMakeProjectManager.CMakeRunConfiguration"; } // namespace Constants diff --git a/src/plugins/cmakeprojectmanager/cmakeprojectmanager.pro b/src/plugins/cmakeprojectmanager/cmakeprojectmanager.pro index afca26b265b2d355d643d0c9c3f4ad7d385372da..74f69fea4abb6116609bb704cc399e52259369b2 100644 --- a/src/plugins/cmakeprojectmanager/cmakeprojectmanager.pro +++ b/src/plugins/cmakeprojectmanager/cmakeprojectmanager.pro @@ -8,11 +8,13 @@ HEADERS = cmakeproject.h \ cmakeprojectconstants.h \ cmakeprojectnodes.h \ cmakestep.h \ - makestep.h + makestep.h \ + cmakerunconfiguration.h SOURCES = cmakeproject.cpp \ cmakeprojectplugin.cpp \ cmakeprojectmanager.cpp \ cmakeprojectnodes.cpp \ cmakestep.cpp \ - makestep.cpp + makestep.cpp \ + cmakerunconfiguration.cpp RESOURCES += cmakeproject.qrc diff --git a/src/plugins/cmakeprojectmanager/cmakeprojectplugin.cpp b/src/plugins/cmakeprojectmanager/cmakeprojectplugin.cpp index 2b59a47c8e277669a9c11afab67776a6457e328e..932278a32c0c381567bb804ddc7e973b858e7e9a 100644 --- a/src/plugins/cmakeprojectmanager/cmakeprojectplugin.cpp +++ b/src/plugins/cmakeprojectmanager/cmakeprojectplugin.cpp @@ -33,6 +33,7 @@ #include "cmakeprojectplugin.h" #include "cmakeprojectmanager.h" +#include "cmakerunconfiguration.h" #include <coreplugin/icore.h> #include <coreplugin/mimedatabase.h> @@ -57,6 +58,7 @@ bool CMakeProjectPlugin::initialize(const QStringList & /*arguments*/, QString * if (!core->mimeDatabase()->addMimeTypes(QLatin1String(":cmakeproject/CMakeProject.mimetypes.xml"), errorMessage)) return false; addAutoReleasedObject(new CMakeManager()); + addAutoReleasedObject(new CMakeRunConfigurationFactory()); return true; } diff --git a/src/plugins/cmakeprojectmanager/cmakestep.cpp b/src/plugins/cmakeprojectmanager/cmakestep.cpp index 0c267ca2c4cea394333b0a6bf4b1bb6d59fbbf47..adbfe59b6cc6484143dbad3708f1a16215f442b0 100644 --- a/src/plugins/cmakeprojectmanager/cmakestep.cpp +++ b/src/plugins/cmakeprojectmanager/cmakestep.cpp @@ -61,6 +61,11 @@ bool CMakeStep::init(const QString &buildConfiguration) void CMakeStep::run(QFutureInterface<bool> &fi) { + // TODO we want to only run cmake if the command line arguments or + // the CmakeLists.txt has actually changed + // And we want all of them to share the SAME command line arguments + // Shadow building ruins this, hmm, hmm + // AbstractProcessStep::run(fi); } diff --git a/src/plugins/projectexplorer/runconfiguration.h b/src/plugins/projectexplorer/runconfiguration.h index 8d2e7b45d6a9a6c32b58841f0efff13e8ba65242..def848765d0bdaac89e7a83b7d33e46f94b72ba9 100644 --- a/src/plugins/projectexplorer/runconfiguration.h +++ b/src/plugins/projectexplorer/runconfiguration.h @@ -80,6 +80,7 @@ public: void setName(const QString &name); // Returns the widget used to configure this run configuration. Ownership is transferred to the caller + // rename to createConfigurationWidget virtual QWidget *configurationWidget() = 0; virtual void save(PersistentSettingsWriter &writer) const; @@ -112,7 +113,6 @@ public: // used to translate the types to names to display to the user virtual QString nameForType(const QString &type) const = 0; virtual QSharedPointer<RunConfiguration> create(Project *project, const QString &type) = 0; - }; class PROJECTEXPLORER_EXPORT IRunConfigurationRunner : public QObject