diff options
Diffstat (limited to 'src/tools/base')
-rw-r--r-- | src/tools/base/Makefile.am | 6 | ||||
-rw-r--r-- | src/tools/base/generic_tool.cpp | 60 | ||||
-rw-r--r-- | src/tools/base/generic_tool.h | 104 | ||||
-rw-r--r-- | src/tools/base/tool_group.cpp | 140 | ||||
-rw-r--r-- | src/tools/base/tool_group.h | 85 |
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 |