summaryrefslogtreecommitdiffstats
path: root/src/tools/list/compile_manager.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/tools/list/compile_manager.cpp')
-rw-r--r--src/tools/list/compile_manager.cpp292
1 files changed, 292 insertions, 0 deletions
diff --git a/src/tools/list/compile_manager.cpp b/src/tools/list/compile_manager.cpp
new file mode 100644
index 0000000..00a4182
--- /dev/null
+++ b/src/tools/list/compile_manager.cpp
@@ -0,0 +1,292 @@
+/***************************************************************************
+ * Copyright (C) 2005-2006 Nicolas Hadacek <hadacek@kde.org> *
+ * Copyright (C) 2003-2004 Alain Gibaud <alain.gibaud@free.fr> *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ ***************************************************************************/
+#include "compile_manager.h"
+
+#include <qtimer.h>
+
+#include "libgui/project.h"
+#include "common/gui/misc_gui.h"
+#include "compile_config.h"
+
+Compile::Manager::Manager(QObject *parent)
+ : QObject(parent, "compile_manager"), _base(0)
+{}
+
+void Compile::Manager::cleanFile(const PURL::Url &url)
+{
+ setupFile(Clean, TodoItem(url, false));
+}
+
+bool Compile::Manager::compileFile(const TodoItem &item)
+{
+ _label = i18n("Compiling file...");
+ return setupFile(Clean | (Main::project() ? CompileOnly : Build), item);
+}
+
+bool Compile::Manager::setupFile(Operations op, const TodoItem &item)
+{
+ Log::Base::clear();
+ clearAll();
+ _operations = op;
+ _type = NormalLinking;
+ _todo.append(item);
+ _action = Compiling;
+ _wholeProject = false;
+ QTimer::singleShot(0, this, SLOT(start()));
+ return true;
+}
+
+void Compile::Manager::cleanProject(LinkType type)
+{
+ setupProject(Clean, type);
+}
+
+bool Compile::Manager::buildProject(LinkType type)
+{
+ _label = i18n("Building project...");
+ return setupProject(Clean | Build, type);
+}
+
+bool Compile::Manager::setupProject(Operations op, LinkType type)
+{
+ Log::Base::clear();
+ clearAll();
+ _operations = op;
+ _type = type;
+ PURL::UrlList files = Main::project()->absoluteFiles();
+ if ( files.count()==0 ) {
+ MessageBox::sorry(i18n("Cannot build empty project."), Log::Show);
+ return false;
+ }
+ PURL::UrlList::const_iterator it;
+ for (it=files.begin(); it!=files.end(); ++it)
+ if ( (*it).data().group==PURL::Source ) _todo.append(TodoItem(*it, false));
+ if ( _todo.count()>1 && Main::toolGroup().compileType()==Tool::SingleFile ) {
+ MessageBox::sorry(i18n("The selected toolchain only supports single-file project."), Log::Show);
+ return false;
+ }
+ _action = Compiling;
+ _wholeProject = true;
+ QTimer::singleShot(0, this, SLOT(start()));
+ return true;
+}
+
+void Compile::Manager::kill()
+{
+ if ( clearAll() ) Log::Base::log(Log::LineType::Error, i18n("*** Aborted ***"), Log::Delayed);
+ emit failure();
+}
+
+bool Compile::Manager::clearAll()
+{
+ bool running = ( _base!=0 );
+ delete _base;
+ _base = 0;
+ _todo.clear();
+ return running;
+}
+
+void Compile::Manager::setup(Tool::Category category)
+{
+ delete _base;
+ Compile::Data data(category, _items, Main::device(), Main::project(), _type);
+ _base = Main::toolGroup().createCompileProcess(data, this);
+}
+
+bool Compile::Manager::setupCompile()
+{
+ PURL::FileType type = Main::toolGroup().implementationType(PURL::ToolType::Compiler);
+ for (uint i=0; i<_items.count(); i++) {
+ if ( _items[i].url.fileType()!=type ) {
+ if ( _operations!=Clean ) {
+ QString e = PURL::extensions(type);
+ MessageBox::detailedSorry(i18n("The selected toolchain (%1) cannot compile file. It only supports files with extensions: %2")
+ .arg(Main::toolGroup().label()).arg(e), i18n("File: %1").arg(_items[i].url.pretty()), Log::Show);
+ Log::Base::log(Log::LineType::Error, i18n("*** Aborted ***"), Log::Delayed);
+ processFailed();
+ }
+ return false;
+ }
+ }
+ if ( !compileOnly() && Main::toolGroup().needs(Main::project(), Tool::Category::Assembler) ) {
+ PURL::FileType type = Main::toolGroup().implementationType(PURL::ToolType::Assembler);
+ for (uint i=0; i<_items.count(); i++)
+ _todo.append(TodoItem(_items[i].url.toFileType(type), true));
+ }
+ setup(Tool::Category::Compiler);
+ return true;
+}
+
+bool Compile::Manager::setupAssemble()
+{
+ PURL::FileType type = Main::toolGroup().implementationType(PURL::ToolType::Assembler);
+ for (uint i=0; i<_items.count(); i++) {
+ if ( _items[i].url.fileType()!=type ) {
+ if ( _operations!=Clean ) {
+ if ( type==PURL::Nb_FileTypes ) type = Main::toolGroup().implementationType(PURL::ToolType::Compiler);
+ QString e = PURL::extensions(type);
+ MessageBox::detailedSorry(i18n("The selected toolchain (%1) cannot assemble file. It only supports files with extensions: %2")
+ .arg(Main::toolGroup().label()).arg(e), i18n("File: %1").arg(_items[i].url.pretty()), Log::Show);
+ Log::Base::log(Log::LineType::Error, i18n("*** Aborted ***"), Log::Delayed);
+ processFailed();
+ }
+ return false;
+ }
+ }
+ setup(Tool::Category::Assembler);
+ return true;
+}
+
+bool Compile::Manager::setupLink()
+{
+ _action = Linking;
+ Tool::Category category = (Main::project() && Main::project()->outputType()==Tool::OutputType::Library ? Tool::Category::Librarian : Tool::Category::Linker);
+ if ( !Main::toolGroup().needs(Main::project(), category) ) {
+ start();
+ return false;
+ }
+ setup(category);
+ return true;
+}
+
+bool Compile::Manager::setupBinToHex()
+{
+ _action = BinToHex;
+ if ( !Main::toolGroup().needs(Main::project(), Tool::Category::BinToHex) ) {
+ start();
+ return false;
+ }
+ setup(Tool::Category::BinToHex);
+ return true;
+}
+
+bool Compile::Manager::prepareAction()
+{
+ switch (_action) {
+ case Compiling:
+ if ( _todo.count()!=0 ) {
+ _items.clear();
+ if ( Main::toolGroup().compileType()==Tool::AllFiles ) {
+ _items = _todo;
+ _todo.clear();
+ } else {
+ _items.append(_todo[0]);
+ _todo.remove(_todo.begin());
+ }
+ PURL::SourceFamily family = _items[0].url.data().sourceFamily;
+ if ( family.data().toolType==PURL::ToolType::Compiler && Main::toolGroup().base(Tool::Category::Compiler) )
+ return setupCompile();
+ return setupAssemble();
+ }
+ if ( !compileOnly() ) return setupLink();
+ break;
+ case Linking: return setupBinToHex();
+ case BinToHex: break;
+ }
+ if ( !(_operations & Clean) ) {
+ Log::Base::log(Log::LineType::Information, i18n("*** Success ***"), Log::Delayed);
+ emit success();
+ } else if ( _operations!=Clean ) {
+ _operations &= ~Clean;
+ if (_wholeProject) setupProject(_operations, _type);
+ else setupFile(_operations, _items[0]);
+ }
+ return false;
+}
+
+void Compile::Manager::start()
+{
+ if ( Main::toolGroup().isCustom() ) {
+ executeCustomCommands();
+ return;
+ }
+ delete _base;
+ _base = 0;
+ if ( !prepareAction() ) return;
+ if ( !_base->check() ) {
+ processFailed();
+ return;
+ }
+ if ( _operations & Clean ) {
+ _base->files(0).onlyExistingFiles().cleanGenerated();
+ QTimer::singleShot(0, this, SLOT(start()));
+ return;
+ }
+ if ( !_base->start() ) {
+ Log::Base::log(Log::LineType::Error, i18n("Failed to execute command: check toolchain configuration."), Log::Delayed);
+ processFailed();
+ }
+}
+
+void Compile::Manager::log(Log::LineType type, const QString &message, const QString &filepath, uint line)
+{
+ if ( type==Log::LineType::Error ) setError(message);
+ static_cast<LogWidget *>(view())->appendLine(type, message, filepath, line);
+}
+
+void Compile::Manager::log(Log::DebugLevel level, const QString &message, const QString &filepath, uint line)
+{
+ static_cast<LogWidget *>(view())->appendLine(level, message, filepath, line);
+}
+
+void Compile::Manager::processDone()
+{
+ if ( hasError() ) {
+ processFailed();
+ return;
+ }
+ if ( Main::toolGroup().isCustom() ) {
+ _customCommandIndex++;
+ startCustomCommand();
+ } else {
+ FileData::List list = _base->files(0).onlyExistingFiles();
+ FileData::List::iterator it;
+ for (it=list.begin(); it!=list.end(); ++it) emit updateFile(*it);
+ QTimer::singleShot(0, this, SLOT(start()));
+ }
+}
+
+void Compile::Manager::processFailed()
+{
+ clearAll();
+ emit failure();
+}
+
+void Compile::Manager::startCustomCommand()
+{
+ delete _base;
+ _base = 0;
+ QStringList commands = Compile::Config::customCommands(Main::project());
+ if ( _customCommandIndex==commands.count() ) {
+ Log::Base::log(Log::LineType::Information, i18n("*** Success ***"), Log::Delayed);
+ emit success();
+ return;
+ }
+ QString command = commands[_customCommandIndex];
+ _base = new CustomProcess(command);
+ Compile::Data data(Tool::Category::Nb_Types, _todo, Main::device(), Main::project(), _type);
+ _base->init(data, this);
+ if ( !_base->start() ) {
+ Log::Base::log(Log::LineType::Error, i18n("Failed to execute custom command #%1.").arg(_customCommandIndex+1), Log::Delayed);
+ processFailed();
+ }
+}
+
+void Compile::Manager::executeCustomCommands()
+{
+ _customCommandIndex = 0;
+ if ( Compile::Config::customCommands(Main::project()).isEmpty() ) {
+ MessageBox::sorry(i18n("No custom commands specified."), Log::Show);
+ emit failure();
+ return;
+ }
+ log(Log::LineType::Information, i18n("Executing custom commands..."));
+ startCustomCommand();
+}