You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
293 lines
9.0 KiB
293 lines
9.0 KiB
/***************************************************************************
|
|
* 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 <tqtimer.h>
|
|
|
|
#include "libgui/project.h"
|
|
#include "common/gui/misc_gui.h"
|
|
#include "compile_config.h"
|
|
|
|
Compile::Manager::Manager(TQObject *parent)
|
|
: TQObject(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;
|
|
TQTimer::singleShot(0, this, TQT_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;
|
|
TQTimer::singleShot(0, this, TQT_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 ) {
|
|
TQString e = PURL::extensions(type);
|
|
MessageBox::detailedSorry(i18n("The selected toolchain (%1) cannot compile file. It only supports files with extensions: %2")
|
|
.tqarg(Main::toolGroup().label()).tqarg(e), i18n("File: %1").tqarg(_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);
|
|
TQString e = PURL::extensions(type);
|
|
MessageBox::detailedSorry(i18n("The selected toolchain (%1) cannot assemble file. It only supports files with extensions: %2")
|
|
.tqarg(Main::toolGroup().label()).tqarg(e), i18n("File: %1").tqarg(_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();
|
|
TQTimer::singleShot(0, this, TQT_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 TQString &message, const TQString &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 TQString &message, const TQString &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);
|
|
TQTimer::singleShot(0, this, TQT_SLOT(start()));
|
|
}
|
|
}
|
|
|
|
void Compile::Manager::processFailed()
|
|
{
|
|
clearAll();
|
|
emit failure();
|
|
}
|
|
|
|
void Compile::Manager::startCustomCommand()
|
|
{
|
|
delete _base;
|
|
_base = 0;
|
|
TQStringList commands = Compile::Config::customCommands(Main::project());
|
|
if ( _customCommandIndex==commands.count() ) {
|
|
Log::Base::log(Log::LineType::Information, i18n("*** Success ***"), Log::Delayed);
|
|
emit success();
|
|
return;
|
|
}
|
|
TQString 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.").tqarg(_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();
|
|
}
|