From: Enar Väikene Date: Wed, 18 May 2011 10:38:53 +0000 (+0300) Subject: First implementation of the Plugin manager library. X-Git-Url: https://vaikene.ee/gitweb/overview.html?a=commitdiff_plain;h=f26e65c1e66cf02eae9aa209acac743e3b04b4f4;p=evaf First implementation of the Plugin manager library. --- diff --git a/etc/eVaf.xml b/etc/eVaf.xml new file mode 100644 index 0000000..f10b14e --- /dev/null +++ b/etc/eVaf.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/src/libs/CMakeLists.txt b/src/libs/CMakeLists.txt index d20916f..918e3ce 100644 --- a/src/libs/CMakeLists.txt +++ b/src/libs/CMakeLists.txt @@ -1,2 +1,2 @@ -#add_subdirectory(Plugins) +add_subdirectory(Plugins) add_subdirectory(Common) diff --git a/src/libs/Plugins/CMakeLists.txt b/src/libs/Plugins/CMakeLists.txt index f0b59ad..0aadd65 100644 --- a/src/libs/Plugins/CMakeLists.txt +++ b/src/libs/Plugins/CMakeLists.txt @@ -13,7 +13,7 @@ add_definitions(-DPLUGINS_LIBRARY) include_directories(${eVaf_INCLUDE}) # Required eVaf libraries -set(eVaf_LIBRARIES) +set(eVaf_LIBRARIES CommonLib) # Source files set(SRCS diff --git a/src/libs/Plugins/ipluginfactory.h b/src/libs/Plugins/ipluginfactory.h new file mode 100644 index 0000000..637aa6b --- /dev/null +++ b/src/libs/Plugins/ipluginfactory.h @@ -0,0 +1,73 @@ +/** + * @file Plugins/ipluginfactory.h + * @brief Common plugin factory interface for all the eVaf modules + * @author Enar Vaikene + * + * Copyright (c) 2011 Enar Vaikene + * + * This file is part of the eVaf C++ cross-platform application development framework. + * + * This file can be used under the terms of the GNU General Public License + * version 3.0 as published by the Free Software Foundation and appearing in + * the file LICENSE included in the packaging of this file. Please review the + * the following information to ensure the GNU General Public License version + * 3.0 requirements will be met: http://www.gnu.org/copyleft/gpl.html. + * + * Alternatively, this file may be used in accordance with the Commercial License + * Agreement provided with the Software. + */ + +#ifndef __PLUGINS_IPLUGINFACTORY_H +#define __PLUGINS_IPLUGINFACTORY_H + +#include "libplugins.h" + +#include +#include + +namespace eVaf { +namespace Plugins { + +/** + * Common plugin factory interface for eVaf modules. + * @code#include + * + * The iPluginFactory interface is implemented by modules that export more than one + * iPlugin interface. + * + * Modules that implement only one iPlugin interface, use the iPlugin interface object + * directly. + */ +class PLUGINS_EXPORT iPluginFactory : public QObject +{ + Q_OBJECT + +public: + + /// Empty constructor + iPluginFactory() : QObject() {} + + /// Empty virtual destructor + virtual ~iPluginFactory() {} + + /** + * Creates the requested iPlugin interface object + * @param name Name of the interface + * @return The requested iPlugin interface object or 0 if failed + * + * This function creates the requested iPlugin interface object. Modules can implement more than + * one iPlugin interface objects and use names to identify them. + * + * If the requested interface object cannot be created, this function returns 0. + * + * The module implementing the iPluginFactory interface is responsible for destroying all the + * created iPlugin interface objects. + */ + virtual QObject * create(const QString & name) = 0; + +}; + +} // namespace eVaf::Plugins +} // namespace eVaf + +#endif // ipluginfactory.h diff --git a/src/libs/Plugins/pluginmanager.cpp b/src/libs/Plugins/pluginmanager.cpp new file mode 100644 index 0000000..c357d11 --- /dev/null +++ b/src/libs/Plugins/pluginmanager.cpp @@ -0,0 +1,543 @@ +/** + * @file plugins/pluginmanager.cpp + * @brief Implementation of the plugin manager + * + * Copyright (c) 2011 Enar Vaikene + * + * This file is part of the eVaf C++ cross-platform application development framework. + * + * This file can be used under the terms of the GNU General Public License + * version 3.0 as published by the Free Software Foundation and appearing in + * the file LICENSE included in the packaging of this file. Please review the + * the following information to ensure the GNU General Public License version + * 3.0 requirements will be met: http://www.gnu.org/copyleft/gpl.html. + * + * Alternatively, this file may be used in accordance with the Commercial License + * Agreement provided with the Software. + */ + +#include "pluginmanager.h" +#include "pluginmanager_p.h" +#include "iplugin.h" +#include "ipluginfactory.h" +#include "version.h" + +#include +#include +#include +#include +#include + +#include + + +namespace eVaf { +namespace Plugins { +namespace Internal { + + // Plugin manager interface implementation + static eVaf::Plugins::PluginManager * mPluginManager = 0; + +} // namespace eVaf::Plugins::Internal +} // namespace eVaf::Plugins +} // namespace eVaf + + +//------------------------------------------------------------------- + +using namespace eVaf; +using namespace eVaf::Plugins; + +PluginManager::PluginManager() + : QObject() +{ + setObjectName(QString("%1-PluginManager").arg(VER_MODULE_NAME_STR)); + + Internal::mPluginManager = this; + + d = new Internal::PluginManagerPrivate; + + EVAF_INFO("%s created", qPrintable(objectName())); +} + +PluginManager::~PluginManager() +{ + delete d; + + Internal::mPluginManager = 0; + + EVAF_INFO("%s destroyed", qPrintable(objectName())); +} + +PluginManager * PluginManager::instance() +{ + return Internal::mPluginManager; +} + +bool PluginManager::init() +{ + // Initialize the internal implementation + if (!d->init()) + return false; + + EVAF_INFO("Loading plugins"); + + // Load and initialize plugins + if (!d->loadPlugins()) + return false; + + EVAF_INFO("Plugins loaded"); + + emit pluginsLoaded(); + + EVAF_INFO("%s initialized", qPrintable(objectName())); + + return true; +} + +void PluginManager::done() +{ + EVAF_INFO("Unloading plugins"); + + // Finalize and unload plugins + d->unloadPlugins(); + + emit pluginsUnloaded(); + + EVAF_INFO("Plugins unloaded"); + + // Finalize the internal implementation + d->done(); + + EVAF_INFO("%s finalized", qPrintable(objectName())); +} + + +//------------------------------------------------------------------- + +using namespace eVaf::Plugins::Internal; + +PluginManagerPrivate::PluginManagerPrivate() + : QObject() +{ + setObjectName(QString("%1-PluginManagerPrivate").arg(VER_MODULE_NAME_STR)); + + EVAF_INFO("%s created", qPrintable(objectName())); +} + +PluginManagerPrivate::~PluginManagerPrivate() +{ + EVAF_INFO("%s destroyed", qPrintable(objectName())); +} + +bool PluginManagerPrivate::init() +{ + EVAF_INFO("%s initialized", qPrintable(objectName())); + + return true; +} + +void PluginManagerPrivate::done() +{ + EVAF_INFO("%s finalized", qPrintable(objectName())); +} + +bool PluginManagerPrivate::loadPlugins() +{ + // Get the name of the application's XML file + QString xmlFileName = Common::iEnv::instance()->etcDir() + Common::iApp::instance()->xmlFileName(); + + // Open the XML file + QFile xmlFile(xmlFileName); + if (!xmlFile.open(QFile::ReadOnly)) { + EVAF_FATAL_ERROR("Failed to open '%s' : %s", qPrintable(xmlFileName), qPrintable(xmlFile.errorString())); + return false; + } + + // Process the XML file + QXmlStreamReader xml(&xmlFile); + bool isValid = false; + bool isPlugins = false; + bool isQtPlugins = false; + bool isPlugin = false; + QString moduleName; + QString pluginName; + QString args; + QStringList qtPlugins; + + while (!xml.atEnd()) { + xml.readNext(); + + // Start element? + if (xml.isStartElement()) { + + // Not a valid XML file yet? + if (!isValid) { + if (xml.name() == "eVaf") { + isValid = true; + } + else { + EVAF_FATAL_ERROR("'%s' is not a valid XML file for eVaf applications", qPrintable(xmlFileName)); + return false; + } + } + + // This is a valid XML file + else { + + // No plugins or qtplugins sections yet? + if (!isPlugins && !isQtPlugins) { + if (xml.name() == "plugins") { + // Check for windows and linux only sections +#ifdef Q_OS_LINUX + if (Common::isTrue(xml.attributes().value("windowsonly").toString())) + continue; +#endif +#ifdef Q_OS_WIN32 + if (Common::isTrue(xml.attributes().value("linuxonly").toString())) + continue; +#endif + isPlugins = true; + } + + else if (xml.name() == "qtplugins") { + // Check for windows and linux only sections +#ifdef Q_OS_LINUX + if (Common::isTrue(xml.attributes().value("windowsonly").toString())) + continue; +#endif +#ifdef Q_OS_WIN32 + if (Common::isTrue(xml.attributes().value("linuxonly").toString())) + continue; +#endif + isQtPlugins = true; + qtPlugins.clear(); + } + } + + // An individual plugin? + else if (isPlugins && xml.name() == "plugin") { + // Check for windows and linux only plugins +#ifdef Q_OS_LINUX + if (Common::isTrue(xml.attributes().value("windowsonly").toString())) { + EVAF_INFO("Plugin '%s' is for Windows only", qPrintable(xml.attributes().value("name").toString())); + continue; + } +#endif +#ifdef Q_OS_WIN32 + if (Common::isTrue(xml.attributes().value("linuxonly").toString())) { + EVAF_INFO("Plugin '%s' is for Linux only", qPrintable(xml.attributes().value("name").toString())); + continue; + } +#endif + + pluginName = xml.attributes().value("name").toString(); + moduleName = xml.attributes().value("filename").toString(); + + /// @TODO: If the file name attribute is empty, loog for the config attribute + if (moduleName.isEmpty()) + continue; + + isPlugin = true; + args.clear(); + } + + // Plugin arguments? + else if (isPlugin) { + args.append("<" + xml.name().toString()); + for (int i = 0; i < xml.attributes().size(); ++i) + args.append(" " + xml.attributes().at(i).name().toString() + "=\"" + xml.attributes().at(i).value().toString() + "\""); + args.append(">"); + } + + // An individual Qt plugin? + else if (isQtPlugins && xml.name() == "plugin") { + // Check for windows and linux only plugins +#ifdef Q_OS_LINUX + if (Common::isTrue(xml.attributes().value("windowsonly").toString())) { + EVAF_INFO("Qt plugin '%s' is for Windows only", qPrintable(xml.attributes().value("name").toString())); + continue; + } +#endif +#ifdef Q_OS_WIN32 + if (Common::isTrue(xml.attributes().value("linuxonly").toString())) { + EVAF_INFO("Qt plugin '%s' is for Linux only", qPrintable(xml.attributes().value("name").toString())); + continue; + } +#endif + QString name = xml.attributes().value("filename").toString(); + if (!name.isEmpty() && !qtPlugins.contains(name)) + qtPlugins.append(name); + } + } + } // Start element? + + // End element? + else if (xml.isEndElement()) { + if (isPlugin && xml.name() == "plugin") { + isPlugin = false; + Module * m = moduleByName(moduleName); + if (!m) + mModules.append(QExplicitlySharedDataPointer(m = new Module(moduleName))); + mPlugins.append(QExplicitlySharedDataPointer(new Plugin(m, pluginName, args))); + } + else if (isPlugin) + args.append(""); + else if (xml.name() == "plugins") + isPlugins = false; + else if (xml.name() == "qtplugins") + isQtPlugins = false; + else if (xml.name() == "eVaf") + isValid = false; + } // End element? + } + + // Load Qt plugins + int i; + for (i = 0; i < qtPlugins.size(); ++i) { + loadQtPlugin(qtPlugins.at(i)); + } + + // Load eVaf plugins + i = 0; + while (i < mPlugins.size()) { + if (!mPlugins.at(i)->load()) { + EVAF_ERROR("Failed to load module '%s'", qPrintable(mPlugins.at(i)->name())); + mPlugins.removeAt(i); + } + else + ++i; + } + + // Initialize eVaf plugins + i = 0; + while (i < mPlugins.size()) { + if (mPlugins.at(i)->init()) { + EVAF_ERROR("Failed to initialize module '%s'", qPrintable(mPlugins.at(i)->name())); + mPlugins.removeAt(i); + } + else + ++i; + } + + return true; +} + +void PluginManagerPrivate::unloadPlugins() +{ + // Finalize all the plugins + for (int i = 0; i < mPlugins.size(); ++i) + mPlugins.at(i)->done(); + while (!mPlugins.isEmpty()) { + QExplicitlySharedDataPointer p = mPlugins.takeLast(); + p->unload(); + } + + // Unload all the modules + while (!mModules.isEmpty()) { + QExplicitlySharedDataPointer m = mModules.takeLast(); + m->unload(); + } +} + +Module * PluginManagerPrivate::moduleByName(QString const & name) const +{ + for (int i = 0; i < mModules.size(); ++i) { + if (mModules.at(i)->name() == name) + return mModules.at(i).data(); + } + return 0; +} + +bool PluginManagerPrivate::loadQtPlugin(QString const & name) const +{ + // Get the Qt plugin file name with the full path + QString fileName; + +#ifdef Q_OS_LINUX + fileName = QString("%1libq%2.so").arg(Common::iEnv::instance()->qtPluginsDir()).arg(name); +# ifndef QT_NO_DEBUG + QString t = QString("%1libq%2.so.debug").arg(Common::iEnv::instance()->qtPluginsDir()).arg(name); + if (QFile::exists(t)) + fileName = t; +# endif +#endif + +#ifdef Q_OS_WIN32 + fileName = QString("%2q%2%3").arg(Common::iEnv::instance()->qtPluginsDir()).arg(name).arg("4.dll"); +# ifndef QT_NO_DEBUG + QString t = QString(%1q%2%3).arg(Common::iEnv::instance()->qtPluginsDir()).arg(name).arg(d4.dll); + if (!QFile::exists(t)) + fileName = t; +# endif +#endif + + if (fileName.isEmpty()) { + EVAF_ERROR("Don\'t know how to load Qt plugin '%s'", qPrintable(name)); + return false; + } + + EVAF_INFO("Loading Qt plugin '%s'", qPrintable(fileName)); + + QLibrary lib(fileName); + void * fn = lib.resolve("qt_plugin_instance"); + if (fn) { + qRegisterStaticPluginInstanceFunction(QtPluginInstanceFunction(fn)); + return true; + } + else { + EVAF_ERROR("Failed to load Qt plugin '%s' : %s", qPrintable(fileName), qPrintable(lib.errorString())); + return false; + } +} + + +//------------------------------------------------------------------- + +Module::Module(QString const & name) + : QSharedData() + , mName(name) + , mLoader(0) + , mRoot(0) + , mPlugin(0) + , mPluginFactory(0) +{} + +Module::~Module() +{ + if (mPluginFactory) + delete mPluginFactory; + if (mLoader) + delete mLoader; +} + +bool Module::load() +{ + // The real file name with path + QString fileName = Common::iEnv::instance()->binDir() + expandPluginName(mName); + + // Try to load the module + QScopedPointer p(new QPluginLoader(fileName)); + if (!p->load()) { + EVAF_FATAL_ERROR("Failed to load '%s' : %s", qPrintable(mName), qPrintable(p->errorString())); + return false; + } + + // Get the root component + QObject * root = p->instance(); + + // Does the module implement the iPluginFactory interface? + if ((mPluginFactory = qobject_cast(root)) == 0) { + + // If not, then it has to implement the iPlugin interface + if ((mPlugin = qobject_cast(root)) == 0) { + EVAF_FATAL_ERROR("Module '%s' is not a valid eVaf module", qPrintable(mName)); + return false; + } + } + + mRoot = root; + mLoader = p.take(); + return true; +} + +void Module::unload() +{ + mRoot = 0; + + if (mPluginFactory) { + delete mPluginFactory; + mPluginFactory = 0; + } + mPlugin = 0; + if (mLoader) { + delete mLoader; + mLoader = 0; + } +} + +iPlugin * Module::create(QString const & name) +{ + // If the module is not loaded, load it now + if (!mLoader) { + if (!load()) + return false; + } + + iPlugin * i = 0; + + // Does the module implement the iPluginFactory interface? + if (mPluginFactory) { + // Use the iPluginFactory interface to create the requested interface + i = qobject_cast(mPluginFactory->create(name)); + if (i == 0) { + EVAF_FATAL_ERROR("Module '%s' failed to create the iPlugin interface with name '%s'", qPrintable(mName), qPrintable(name)); + return 0; + } + } + + // Otherwise use the root component, but only once + else { + if (mPlugin) { + EVAF_FATAL_ERROR("Module '%s' can implement only one iPlugin interface and one with the name '%s' is already created", + qPrintable(mName), qPrintable(mPlugin->objectName())); + return 0; + } + + i = qobject_cast(mRoot); + if (i == 0) { + EVAF_FATAL_ERROR("Module '%s' does not implement the iPlugin interface", qPrintable(mName)); + return 0; + } + + mPlugin = i; + } + + return i; +} + + +//------------------------------------------------------------------- + +Plugin::Plugin(Module * module, QString const & name, QString const & args) + : QSharedData() + , mModule(module) + , mName(name) + , mArgs(args) + , mPlugin(0) +{} + +Plugin::~Plugin() +{ + if (mPlugin) + delete mPlugin; +} + +bool Plugin::load() +{ + mPlugin = mModule->create(mName); + if (mPlugin && !mPlugin->objectName().isEmpty()) + mName = mPlugin->objectName(); + return mPlugin != 0; +} + +void Plugin::unload() +{ + if (mPlugin) { + delete mPlugin; + mPlugin = 0; + } +} + +bool Plugin::init() +{ + if (!mPlugin) + return false; + return mPlugin->init(mArgs); +} + +void Plugin::done() +{ + if (mPlugin) + mPlugin->done(); +} diff --git a/src/libs/Plugins/pluginmanager.h b/src/libs/Plugins/pluginmanager.h index 2f320f9..f79193c 100644 --- a/src/libs/Plugins/pluginmanager.h +++ b/src/libs/Plugins/pluginmanager.h @@ -1,5 +1,5 @@ /** - * @file plugins/pluginmanager.h + * @file Plugins/pluginmanager.h * @brief Manager for loadable modules (plugins) * * Copyright (c) 2011 Enar Vaikene @@ -24,6 +24,9 @@ #include #include +#include + +namespace eVaf { /** * Library for managing loadable modules (plugins). @@ -44,6 +47,25 @@ namespace Internal { class PluginManagerPrivate; } +/** + * Expands plugin names for the selected platform. + * @param name Name of the plugin + * @return Expanded plugin name + * + * This function expands the plugin name so that it becomes valid for the selected platform. + * For example, on Linux it adds the prefix "lib" to the beginning and extension ".so" to the end. + */ +inline QString expandPluginName(QString const & name) +{ +#ifdef Q_OS_WIN32 + return name + ".dll"; +#elif defined Q_OS_LINUX + return "lib" + name + ".so"; +#else + return name; +#endif +} + /** * Plugin manager for eVaf applications. */ @@ -101,11 +123,11 @@ signals: private: - Internal::PluginManagerPrivate * dl; + Internal::PluginManagerPrivate * d; }; -} // namespace Plugins - +} // namespace eVaf::Plugins +} // namespace eVaf #endif // pluginmanager.h diff --git a/src/libs/Plugins/pluginmanager_p.h b/src/libs/Plugins/pluginmanager_p.h new file mode 100644 index 0000000..1fbdad0 --- /dev/null +++ b/src/libs/Plugins/pluginmanager_p.h @@ -0,0 +1,228 @@ +/** + * @file plugins/pluginmanager_p.h + * @brief Private implementation of the plugin manager + * + * Copyright (c) 2011 Enar Vaikene + * + * This file is part of the eVaf C++ cross-platform application development framework. + * + * This file can be used under the terms of the GNU General Public License + * version 3.0 as published by the Free Software Foundation and appearing in + * the file LICENSE included in the packaging of this file. Please review the + * the following information to ensure the GNU General Public License version + * 3.0 requirements will be met: http://www.gnu.org/copyleft/gpl.html. + * + * Alternatively, this file may be used in accordance with the Commercial License + * Agreement provided with the Software. + */ + +#ifndef __PLUGINS_PLUGINMANAGER_P_H +#define __PLUGINS_PLUGINMANAGER_P_H + +#include +#include +#include +#include + +namespace eVaf { +namespace Plugins { + +class iPlugin; +class iPluginFactory; + +namespace Internal { + +class Plugin; +class Module; + +/** + * Internal implementation of the plugin manager + */ +class PluginManagerPrivate : public QObject +{ + Q_OBJECT + +public: + + /// Ctr. + PluginManagerPrivate(); + + /// Dtr. + virtual ~PluginManagerPrivate(); + + /** + * Initializes the private plugin manager object + * @return True; false if failed + */ + bool init(); + + /** + * Finalizes the private plugin manager object + */ + void done(); + + /** + * Loads and initializes plugins + * @return True; false if failed + */ + bool loadPlugins(); + + /** + * Finalizes and unloads plugins + */ + void unloadPlugins(); + + +private: // Members + + /// List of all the modules + QList > mModules; + + /// List of all the plugins + QList > mPlugins; + + +private: // Methods + + /** + * Returns the module object by its name + * @param name Name of the module + * @return Module object or 0 if not found + */ + Module * moduleByName(QString const & name) const; + + /** + * Loads the Qt plugin + * @param Name of the Qt plugin + * @return True; false if failed + */ + bool loadQtPlugin(QString const & name) const; + +}; + +/** + * One external module implementing the iPluginFactory or the iPlugin interfaces. + * + * This class is a wrapper around the external module. + */ +class Module : public QSharedData +{ +public: + + /** + * Ctr. + * @param name Name of the module + */ + Module(QString const & name); + + /// Dtr. + ~Module(); + + /// Returns true if the module is loaded + bool isLoaded() const { return mLoader != 0; } + + /// The name of the module + QString const & name() const { return mName; } + + /** + * Loads the module + * @return True; false if failed + */ + bool load(); + + /// Unloads the module + void unload(); + + /** + * Creates the requested iPlugin interface object + * @param name Name of the interface + * @return The iPlugin interface object or 0 if failed + */ + iPlugin * create(QString const & name); + + +private: // Members + + /// Name of the module + QString mName; + + /// Plugin loader + QPluginLoader * mLoader; + + /// Plugin's root component + QObject * mRoot; + + /// The iPlugin interface object if the module implements only one iPlugin interface + iPlugin * mPlugin; + + /// The iPluginFactory interface object if the module implements more than one iPluginFactory interface + iPluginFactory * mPluginFactory; + +}; + +/** + * One iPlugin interface object. + * + * This class is a wrapper around the plugin. + */ +class Plugin : public QSharedData +{ +public: + + /** + * Ctr. + * @param module The Module implementing this iPlugin interface + * @param name Name of the plugin + * @param args Arguments for the plugin initialization + */ + Plugin(Module * module, QString const & name, QString const & args); + + /// Dtr. + ~Plugin(); + + /// The iPlugin interface + iPlugin * plugin() const { return mPlugin; } + + /// The name of the plugin + QString const & name() const { return mName; } + + /** + * Loads the plugin + * @return True; false if failed + */ + bool load(); + + /// Unloads the plugin + void unload(); + + /** + * Initializes the plugin + * @return True; false if failed + */ + bool init(); + + /// Uninitializes the plugin + void done(); + + +private: // Members + + /// Module implementing this iPlugin interface + Module * mModule; + + /// Name of the plugin + QString mName; + + /// Arguments for the initialization + QString mArgs; + + /// The iPlugin interface object + iPlugin * mPlugin; + +}; + +} // namespace eVaf::Plugins::Internal +} // namespace eVaf::Plugins +} // namespace eVaf + +#endif // pluginmanager_p.h diff --git a/src/libs/Plugins/version.h b/src/libs/Plugins/version.h new file mode 100644 index 0000000..f114e5a --- /dev/null +++ b/src/libs/Plugins/version.h @@ -0,0 +1,60 @@ +/** + * @file Plugins/version.h + * @brief Version information for eVaf modules + * @author Enar Vaikene + * + * Copyright (c) 2011 Enar Vaikene + * + * This file is part of the eVaf C++ cross-platform application development framework. + * + * This file can be used under the terms of the GNU General Public License + * version 3.0 as published by the Free Software Foundation and appearing in + * the file LICENSE included in the packaging of this file. Please review the + * the following information to ensure the GNU General Public License version + * 3.0 requirements will be met: http://www.gnu.org/copyleft/gpl.html. + * + * Alternatively, this file may be used in accordance with the Commercial License + * Agreement provided with the Software. + */ + +#ifndef __PLUGINS_VERSION_H +#define __PLUGINS_VERSION_H + +#include + +/** + * Module/library version number in the form major,minor,release,build + */ +#define VER_FILE_VERSION 0,1,1,1 + +/** + * Module/library version number in the string format (shall end with \0) + */ +#define VER_FILE_VERSION_STR "0.1.1.1\0" + +/** + * Module/library name (shall end with \0) + */ +#define VER_MODULE_NAME_STR "PluginsLib\0" + +/** + * Module type (see version_rc.h for all the types) + */ +#define VER_MODULE_TYPE MT_GENERIC + +/** + * Module type in the string format (see version_rc for all the types) + */ +#define VER_MODULE_TYPE_STR MT_GENERIC + +/** + * Original file name for windows (shall end with \0) + */ +#define VER_ORIGINAL_FILE_NAME_STR "PluginsLib.dll\0" + +/** + * Description of the module/library (shall end with \0) + */ +#define VER_FILE_DESCRIPTION_STR "Library for eVaf applications that loads external modules into the application.\0" + +#endif // version.h diff --git a/src/libs/Plugins/version.rc b/src/libs/Plugins/version.rc new file mode 100644 index 0000000..04ed2f8 --- /dev/null +++ b/src/libs/Plugins/version.rc @@ -0,0 +1,54 @@ +/** + * @file Common/version.rc + * @brief Windows resource file with module/library version information. + * @author Enar Vaikene + * + * Copyright (c) 2011 Enar Vaikene + * + * This file is part of the eVaf C++ cross-platform application development framework. + * + * This file can be used under the terms of the GNU General Public License + * version 3.0 as published by the Free Software Foundation and appearing in + * the file LICENSE included in the packaging of this file. Please review the + * the following information to ensure the GNU General Public License version + * 3.0 requirements will be met: http://www.gnu.org/copyleft/gpl.html. + * + * Alternatively, this file may be used in accordance with the Commercial License + * Agreement provided with the Software. + */ + +#include "version.h" +#include +#include + + +VS_VERSION_INFO VERSIONINFO + FILEVERSION VER_FILE_VERSION + PRODUCTVERSION VER_PRODUCT_VERSION + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS VS_FF_DEBUG +#else + FILEFLAGS 0x0L +#endif + FILEOS VOS__WINDOWS32 + FILETYPE VFT_DLL + FILESUBTYPE 0x0L + BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904B0" + BEGIN + VALUE "CompanyName", VER_COMPANY_NAME_STR + VALUE "FileDescription", VER_FILE_DESCRIPTION_STR + VALUE "FileVersion", VER_FILE_VERSION_STR + VALUE "LegalCopyright", VER_LEGAL_COPYRIGHT_STR + VALUE "OriginalFilename", VER_ORIGINAL_FILE_NAME_STR + VALUE "ProductName", VER_PRODUCT_NAME_STR + VALUE "ProductVersion", VER_PRODUCT_VERSION_STR + VALUE "Build Date", VER_PRODUCT_DATE_STR + VALUE "Module Name", VER_MODULE_NAME_STR + VALUE "Module Type", VER_MODULE_TYPE_STR + END + END + END