summaryrefslogtreecommitdiffstats
path: root/src/tools/base
diff options
context:
space:
mode:
Diffstat (limited to 'src/tools/base')
-rw-r--r--src/tools/base/Makefile.am6
-rw-r--r--src/tools/base/generic_tool.cpp60
-rw-r--r--src/tools/base/generic_tool.h104
-rw-r--r--src/tools/base/tool_group.cpp140
-rw-r--r--src/tools/base/tool_group.h85
5 files changed, 395 insertions, 0 deletions
diff --git a/src/tools/base/Makefile.am b/src/tools/base/Makefile.am
new file mode 100644
index 0000000..2154bf4
--- /dev/null
+++ b/src/tools/base/Makefile.am
@@ -0,0 +1,6 @@
+INCLUDES = -I$(top_srcdir)/src $(all_includes)
+METASOURCES = AUTO
+
+noinst_LTLIBRARIES = libtoolbase.la
+libtoolbase_la_LDFLAGS = $(all_libraries)
+libtoolbase_la_SOURCES = generic_tool.cpp tool_group.cpp
diff --git a/src/tools/base/generic_tool.cpp b/src/tools/base/generic_tool.cpp
new file mode 100644
index 0000000..d595362
--- /dev/null
+++ b/src/tools/base/generic_tool.cpp
@@ -0,0 +1,60 @@
+/***************************************************************************
+ * Copyright (C) 2005-2007 Nicolas Hadacek <hadacek@kde.org> *
+ * *
+ * 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 "generic_tool.h"
+
+#include "devices/list/device_list.h"
+#include "common/global/process.h"
+#include "tools/list/compile_config.h"
+
+//----------------------------------------------------------------------------
+const Tool::Category::Data Tool::Category::DATA[Nb_Types] = {
+ { "compiler", I18N_NOOP("Compiler:"), I18N_NOOP("Compiler") },
+ { "assembler", I18N_NOOP("Assembler:"), I18N_NOOP("Assembler") },
+ { "linker", I18N_NOOP("Linker:"), I18N_NOOP("Linker") },
+ { "bin_to_hex", I18N_NOOP("Bin to Hex:"), I18N_NOOP("Bin to Hex") },
+ { "librarian", I18N_NOOP("Librarian:"), I18N_NOOP("Librarian") }
+};
+
+const Tool::ExecutableType::Data Tool::ExecutableType::DATA[Nb_Types] = {
+ { "unix", I18N_NOOP("Unix") },
+ { "windows", I18N_NOOP("Windows") }
+};
+
+const Compile::DirectoryType::Data Compile::DirectoryType::DATA[Nb_Types] = {
+ { "executable", I18N_NOOP("Executable directory") },
+ { "include", I18N_NOOP("Header directory") },
+ { "linker_script", I18N_NOOP("Linker Script Directory") },
+ { "library", I18N_NOOP("Library Directory") },
+ { "source", I18N_NOOP("Source Directory") }
+};
+
+const Tool::OutputExecutableType::Data Tool::OutputExecutableType::DATA[Nb_Types] = {
+ { I18N_NOOP("COFF"), "coff", PURL::Coff },
+ { I18N_NOOP("ELF"), "elf", PURL::Elf }
+};
+
+const Tool::OutputType::Data Tool::OutputType::DATA[Nb_Types] = {
+ { "executable", I18N_NOOP("Executable") },
+ { "library", I18N_NOOP("Library") }
+};
+
+//-----------------------------------------------------------------------------
+PURL::Directory Tool::Base::executableDirectory() const
+{
+ return Compile::Config::directory(*_group, Compile::DirectoryType::Executable);
+}
+
+::Process::LineOutput *Tool::Base::checkExecutableProcess(const PURL::Directory &dir, bool withWine, OutputExecutableType type) const
+{
+ ::Process::LineOutput *process = new ::Process::LineOutput;
+ process->setup(dir.path() + baseExecutable(withWine, type), checkExecutableOptions(withWine), withWine);
+ PURL::Directory wdir = checkExecutableWorkingDirectory();
+ if ( !wdir.isEmpty() ) process->setWorkingDirectory(wdir.path());
+ return process;
+}
diff --git a/src/tools/base/generic_tool.h b/src/tools/base/generic_tool.h
new file mode 100644
index 0000000..3b3299d
--- /dev/null
+++ b/src/tools/base/generic_tool.h
@@ -0,0 +1,104 @@
+/***************************************************************************
+ * Copyright (C) 2005-2007 Nicolas Hadacek <hadacek@kde.org> *
+ * *
+ * 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. *
+ ***************************************************************************/
+#ifndef GENERIC_TOOL_H
+#define GENERIC_TOOL_H
+
+#include "common/global/purl.h"
+#include "common/common/key_enum.h"
+namespace Device { class Data; class Memory; }
+namespace Process { class LineOutput; }
+class Project;
+
+namespace Tool
+{
+//----------------------------------------------------------------------------
+ struct CategoryData {
+ const char *key, *label, *title;
+ };
+ BEGIN_DECLARE_ENUM(Category)
+ Compiler = 0, Assembler, Linker, BinToHex, Librarian
+ END_DECLARE_ENUM(Category, CategoryData)
+
+ BEGIN_DECLARE_ENUM(ExecutableType)
+ Unix = 0, Windows
+ END_DECLARE_ENUM_STD(ExecutableType)
+} // namespace
+
+namespace Compile
+{
+ enum LinkType { NormalLinking, Icd2Linking };
+ class Process;
+ class Config;
+
+ class TodoItem {
+ public:
+ TodoItem() {}
+ TodoItem(const PURL::Url &_url, bool _generated) : url(_url), generated(_generated) {}
+ PURL::Url url;
+ bool generated;
+ };
+
+ class Data {
+ public:
+ Data() {}
+ Data(Tool::Category c, const QValueList<TodoItem> &i, const QString &d, const Project *p, LinkType lt)
+ : category(c), items(i), device(d), project(p), linkType(lt) {}
+ Tool::Category category;
+ QValueList<TodoItem> items;
+ QString device;
+ const Project *project;
+ LinkType linkType;
+ };
+
+ BEGIN_DECLARE_ENUM(DirectoryType)
+ Executable = 0, Header, LinkerScript, Library, Source
+ END_DECLARE_ENUM_STD(DirectoryType)
+
+} // namespace
+
+namespace Tool
+{
+ class Group;
+
+ struct OutputExecutableTypeData {
+ const char *label, *key;
+ PURL::FileType type;
+ };
+ BEGIN_DECLARE_ENUM(OutputExecutableType)
+ Coff = 0, Elf
+ END_DECLARE_ENUM(OutputExecutableType, OutputExecutableTypeData)
+
+ BEGIN_DECLARE_ENUM(OutputType)
+ Executable = 0, Library
+ END_DECLARE_ENUM_STD(OutputType)
+
+//-----------------------------------------------------------------------------
+class Base
+{
+public:
+ virtual ~Base() {}
+ const Group &group() const { return *_group; }
+ virtual QString baseExecutable(bool withWine, OutputExecutableType type) const = 0;
+ PURL::Directory executableDirectory() const;
+ virtual bool checkExecutable() const { return true; }
+ virtual QStringList checkExecutableOptions(bool withWine) const = 0;
+ virtual PURL::Directory checkExecutableWorkingDirectory() const { return PURL::Directory(); }
+ virtual ::Process::LineOutput *checkExecutableProcess(const PURL::Directory &dir, bool withWine, OutputExecutableType type) const;
+ virtual bool checkExecutableResult(bool withWine, QStringList &lines) const = 0;
+
+protected:
+ Category _category;
+ const Group *_group;
+
+ friend class Group;
+};
+
+} // namespace
+
+#endif
diff --git a/src/tools/base/tool_group.cpp b/src/tools/base/tool_group.cpp
new file mode 100644
index 0000000..fb347ce
--- /dev/null
+++ b/src/tools/base/tool_group.cpp
@@ -0,0 +1,140 @@
+/***************************************************************************
+ * Copyright (C) 2005-2007 Nicolas Hadacek <hadacek@kde.org> *
+ * *
+ * 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 "tool_group.h"
+
+#include "devices/list/device_list.h"
+#include "devices/base/device_group.h"
+#include "devices/base/generic_memory.h"
+#include "common/global/process.h"
+#include "tools/list/compile_config.h"
+#include "tools/list/compile_process.h"
+#include "libgui/project.h"
+
+//-----------------------------------------------------------------------------
+const char *Tool::Group::CUSTOM_NAME = "custom";
+
+Tool::Group::Group()
+ : _sourceGenerator(0), _checkDevicesError(true)
+{}
+
+void Tool::Group::init()
+{
+ delete _sourceGenerator;
+ _sourceGenerator = sourceGeneratorFactory();
+ FOR_EACH(Category, i) {
+ delete _bases[i].base;
+ _bases[i] = baseFactory(i);
+ if (_bases[i].base) {
+ _bases[i].base->_category = i;
+ _bases[i].base->_group = this;
+ }
+ }
+ ::Group::Base::init();
+ _version = getToolchainVersion();
+}
+
+Compile::Process *Tool::Group::createCompileProcess(const Compile::Data &data, Compile::Manager *manager) const
+{
+ Compile::Process *p = processFactory(data);
+ if (p) p->init(data, manager);
+ return p;
+}
+
+Compile::Config *Tool::Group::createConfig(::Project *project) const
+{
+ Compile::Config *c = configFactory(project);
+ if (c) c->_group = this;
+ return c;
+}
+
+PURL::Directory Tool::Group::autodetectDirectory(Compile::DirectoryType, const PURL::Directory &, bool) const
+{
+ return PURL::Directory();
+}
+
+QString Tool::Group::defaultLinkerScriptFilename(Compile::LinkType type, const QString &device) const
+{
+ QString basename = device.lower();
+ if ( type==Compile::Icd2Linking ) basename += 'i';
+ return basename + '.' + PURL::extension(PURL::Lkr);
+}
+
+bool Tool::Group::hasCustomLinkerScript(const ::Project *project) const
+{
+ return ( project && !project->customLinkerScript().isEmpty() );
+}
+
+PURL::Url Tool::Group::linkerScript(const ::Project *project, Compile::LinkType type) const
+{
+ if ( hasCustomLinkerScript(project) ) return project->customLinkerScript();
+ QString filename = defaultLinkerScriptFilename(type, Compile::Config::device(project));
+ return PURL::Url(Compile::Config::directory(*this, Compile::DirectoryType::LinkerScript), filename);
+}
+
+::Process::LineOutput *Tool::Group::checkDevicesProcess(uint i, const PURL::Directory &dir, bool withWine) const
+{
+ ::Process::LineOutput *process = new ::Process::LineOutput;
+ Tool::Category cat = checkDevicesCategory();
+ QString exec = base(cat)->baseExecutable(withWine, Compile::Config::outputExecutableType(*this));
+ process->setup(dir.path() + exec, checkDevicesOptions(i), withWine);
+ return process;
+}
+
+bool Tool::Group::checkExecutable(Tool::Category category, QStringList &lines)
+{
+ PURL::Directory dir = Compile::Config::directory(*this, Compile::DirectoryType::Executable);
+ bool withWine = Compile::Config::withWine(*this);
+ Tool::OutputExecutableType outputType = Compile::Config::outputExecutableType(*this);
+ ::Process::LineOutput * process = _bases[category].base->checkExecutableProcess(dir, withWine, outputType);
+ ::Process::State state = ::Process::runSynchronously(*process, ::Process::Start, 10000);
+ if ( state!=::Process::Exited ) return false;
+ lines = process->sout() + process->serr();
+ return _bases[category].base->checkExecutableResult(withWine, lines);
+}
+
+void Tool::Group::initSupported()
+{
+ _checkDevicesError = false;
+ Tool::Category cat = checkDevicesCategory();
+ QValueList<const Device::Data *> list;
+ if ( cat==Tool::Category::Nb_Types ) list = getSupportedDevices(QString::null);
+ else {
+ PURL::Directory dir = Compile::Config::directory(*this, Compile::DirectoryType::Executable);
+ for (uint i=0; i<nbCheckDevices(); i++) {
+ QStringList lines;
+ ::Process::LineOutput *process = checkDevicesProcess(i, dir, Compile::Config::withWine(*this));
+ ::Process::State state = ::Process::runSynchronously(*process, ::Process::Start, 10000);
+ if ( state==::Process::Exited ) {
+ QStringList lines = process->sout() + process->serr();
+ list += getSupportedDevices(lines.join("\n"));
+ } else _checkDevicesError = true;
+ delete process;
+ }
+ }
+ QValueList<const Device::Data *>::const_iterator it;
+ for (it=list.begin(); it!=list.end(); ++it) addDevice((*it)->name(), *it, ::Group::Support::Tested);
+}
+
+bool Tool::Group::check(const QString &device, Log::Generic *log) const
+{
+ const_cast<Tool::Group *>(this)->checkInitSupported();
+ if ( hasCheckDevicesError() )
+ return (log ? log->askContinue(i18n("There were errors detecting supported devices for the selected toolchain (%1). Please check the toolchain configuration. Continue anyway?").arg(label())) : false);
+ if ( !device.isEmpty() && device!=Device::AUTO_DATA.name && !isSupported(device) )
+ return (log ? log->askContinue(i18n("The selected toolchain (%1) does not support device %2. Continue anyway?").arg(label()).arg(device)) : false);
+ return true;
+}
+
+bool Tool::Group::needs(bool withProject, Tool::Category category) const
+{
+ if ( _bases[category].base==0 ) return false;
+ if ( withProject && _bases[category].type==StandaloneOnly ) return false;
+ if ( !withProject && _bases[category].type==ProjectOnly ) return false;
+ return true;
+}
diff --git a/src/tools/base/tool_group.h b/src/tools/base/tool_group.h
new file mode 100644
index 0000000..c4adb84
--- /dev/null
+++ b/src/tools/base/tool_group.h
@@ -0,0 +1,85 @@
+/***************************************************************************
+ * Copyright (C) 2005-2007 Nicolas Hadacek <hadacek@kde.org> *
+ * *
+ * 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. *
+ ***************************************************************************/
+#ifndef TOOL_GROUP_H
+#define TOOL_GROUP_H
+
+#include "common/global/purl.h"
+#include "common/common/group.h"
+#include "common/common/version_data.h"
+#include "generic_tool.h"
+#include "coff/base/disassembler.h"
+namespace Compile { class Manager; }
+
+namespace Tool
+{
+enum CompileType { SeparateFiles, AllFiles, SingleFile };
+class SourceGenerator;
+
+//-----------------------------------------------------------------------------
+class Group : public ::Group::Base
+{
+public:
+ static const char *CUSTOM_NAME;
+ Group();
+ bool isCustom() const { return ( name()==CUSTOM_NAME ); }
+ virtual QString comment() const { return QString::null; }
+ virtual void init();
+ virtual const ::Tool::Base *base(Category category) const { return _bases[category].base; }
+ virtual QString informationText() const = 0;
+ virtual ExecutableType preferedExecutableType() const = 0;
+ virtual bool hasDirectory(Compile::DirectoryType) const { return false; }
+ virtual PURL::FileType linkerScriptType() const { return PURL::Nb_FileTypes; }
+ virtual PURL::Directory autodetectDirectory(Compile::DirectoryType type, const PURL::Directory &execDir, bool withWine) const;
+ virtual bool hasOutputExecutableType(Tool::OutputExecutableType type) const { return ( type==Tool::OutputExecutableType::Coff ); }
+ virtual uint nbCheckDevices() const { return 1; }
+ bool hasCheckDevicesError() const { return _checkDevicesError; }
+ virtual Tool::Category checkDevicesCategory() const = 0;
+ virtual QStringList checkDevicesOptions(uint) const { return QStringList(); }
+ ::Process::LineOutput *checkDevicesProcess(uint i, const PURL::Directory &execDir, bool withWine) const;
+ virtual QValueList<const Device::Data *> getSupportedDevices(const QString &s) const = 0;
+ virtual CompileType compileType() const = 0;
+ virtual bool needs(bool withProject, Category category) const;
+ Compile::Process *createCompileProcess(const Compile::Data &data, Compile::Manager *manager) const;
+ Compile::Config *createConfig(::Project *project) const;
+ bool hasCustomLinkerScript(const ::Project *project) const;
+ virtual PURL::Url linkerScript(const ::Project *project, Compile::LinkType type) const;
+ virtual PURL::FileType implementationType(PURL::ToolType type) const = 0;
+ virtual Compile::Process *processFactory(const Compile::Data &data) const = 0;
+ const SourceGenerator *sourceGenerator() const { return _sourceGenerator; }
+ bool check(const QString &device, Log::Generic *log) const;
+ const VersionData &version() const { return _version; }
+ virtual bool generateDebugInformation(const QString &device) const { Q_UNUSED(device); return true; }
+
+protected:
+ enum NeedType { StandaloneOnly, ProjectOnly, Both };
+ class BaseData {
+ public:
+ BaseData() : base(0), type(Both) {}
+ BaseData(::Tool::Base *b, NeedType t) : base(b), type(t) {}
+ ::Tool::Base *base;
+ NeedType type;
+ };
+ virtual void initSupported();
+ virtual BaseData baseFactory(Category category) const = 0;
+ virtual QString defaultLinkerScriptFilename(Compile::LinkType type, const QString &device) const;
+ virtual Compile::Config *configFactory(::Project *project) const = 0;
+ virtual SourceGenerator *sourceGeneratorFactory() const = 0;
+ bool checkExecutable(Tool::Category category, QStringList &lines);
+ virtual VersionData getToolchainVersion() { return VersionData(); }
+
+private:
+ SourceGenerator *_sourceGenerator;
+ QMap<Category, BaseData> _bases;
+ bool _checkDevicesError;
+ VersionData _version;
+};
+
+} // namespace
+
+#endif