From 208b5529556824127afcbe91de7870f77fb9209f Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Tue, 1 Feb 2011 05:10:45 +0100 Subject: [PATCH] Demonstration how the application could resolve the module loading location The real application likely will consult the configuration file to search alternative module installation locations. --- SConstruct | 12 +++-- src/common/dummy-func.cpp | 111 +++++++++++++++++++++++++++++++++----- src/common/dummy-func.hpp | 15 ++++++ 3 files changed, 122 insertions(+), 16 deletions(-) diff --git a/SConstruct b/SConstruct index 6eadc765b..c176dd6f3 100644 --- a/SConstruct +++ b/SConstruct @@ -104,8 +104,8 @@ def setupBasicEnvironment(localDefinitions): appendVal(env,'DEBUG', 'CCFLAGS', val=' -ggdb') # setup search path for Lumiera plugins - appendCppDefine(env,'PKGLIBDIR','LUMIERA_PLUGIN_PATH=\\"$PKGLIBDIR/:./modules\\"' - ,'LUMIERA_PLUGIN_PATH=\\"$DESTDIR/lib/lumiera/:./modules\\"') + appendCppDefine(env,'PKGLIBDIR','LUMIERA_PLUGIN_PATH=\\"$PKGLIBDIR/:ORIGIN/modules\\"' + ,'LUMIERA_PLUGIN_PATH=\\"ORIGIN/modules\\"') appendCppDefine(env,'PKGDATADIR','LUMIERA_CONFIG_PATH=\\"$PKGLIBDIR/:.\\"' ,'LUMIERA_CONFIG_PATH=\\"$DESTDIR/share/lumiera/:.\\"') @@ -248,10 +248,14 @@ def configurePlatform(env): if not conf.CheckCXXHeader('boost/config.hpp'): problems.append('We need the C++ boost-libraries.') else: - if not conf.CheckCXXHeader('boost/shared_ptr.hpp'): - problems.append('We need boost::shared_ptr (shared_ptr.hpp).') + if not conf.CheckCXXHeader('boost/scoped_ptr.hpp'): + problems.append('We need boost::scoped_ptr (scoped_ptr.hpp).') + if not conf.CheckCXXHeader('boost/format.hpp'): + problems.append('We need boost::format (header).') if not conf.CheckLibWithHeader('boost_program_options-mt','boost/program_options.hpp','C++'): problems.append('We need boost::program_options (including binary lib for linking).') + if not conf.CheckLibWithHeader('boost_filesystem-mt','boost/filesystem.hpp','C++'): + problems.append('We need the boost::filesystem (including binary lib for linking).') if not conf.CheckLibWithHeader('boost_regex-mt','boost/regex.hpp','C++'): problems.append('We need the boost regular expression lib (incl. binary lib for linking).') diff --git a/src/common/dummy-func.cpp b/src/common/dummy-func.cpp index b6250ee75..3892e6737 100644 --- a/src/common/dummy-func.cpp +++ b/src/common/dummy-func.cpp @@ -1,42 +1,129 @@ /* - dummy-func.cpp - placeholder with dummy functions to demonstrate building shared modules + dummy-func.cpp - placeholder with dummy functions to demonstrate building/loading shared modules -* ******************************************************************************************/ +* *************************************************************************************************/ + + + +#ifndef LUMIERA_PLUGIN_PATH +#error please define the plugin search path as -DLUMIERA_PLUGIN_PATH, e.g. as $INSTALL_PREFIX/lib/lumiera +#endif #include "common/dummy-func.hpp" +extern "C" { +#include +} #include #include - - - +#include +#include +#include namespace lumiera { - - const char * const GUI_MODULE_NAME = "modules/gtk_gui.lum"; - typedef void (*VoidFunc)(void); + using std::string; + using boost::regex; + using boost::smatch; + using boost::regex_search; + + namespace fsys = boost::filesystem; + + namespace { // Implementation helpers + + const size_t STRING_MAX_RELEVANT = 1000; + + const char * const GUI_MODULE_TO_LOAD = "gtk_gui"; + const char * const GET_PATH_TO_EXECUTABLE = "/proc/self/exe"; + + regex EXTRACT_RELATIVE_PATHSPEC ("\\$?ORIGIN/([^:]+)"); + + + /** the real application would throw a custom exception... */ + void + dieHard (string msg) + { + NOBUG_ERROR (NOBUG_ON, "Fatal Error: %s ", msg.c_str()); + abort(); + } + + + /** figure out the absolute path + * of the currently running executable + */ + string + catchMyself () + { + string buff(STRING_MAX_RELEVANT+1, '\0' ); + ssize_t chars_read = readlink (GET_PATH_TO_EXECUTABLE, &buff[0], STRING_MAX_RELEVANT); + + if (0 > chars_read || chars_read == ssize_t(STRING_MAX_RELEVANT)) + dieHard ("unable to discover path of running executable"); + + buff.resize(chars_read); + return buff; + } + + + /** extract from the PLUGIN_PATH a path specification + * given relative to the location of the executable, + * as denoted by the 'ORIGIN' token + */ + string + getRelativeModuleLocation() + { + smatch match; + if (regex_search (string(LUMIERA_PLUGIN_PATH), match, EXTRACT_RELATIVE_PATHSPEC)) + return (match[1]); + else + dieHard ("no valid module loading location relative to executable defined in LUMIERA_PLUGIN_PATH"); + } + }//(End) implementation helpers + + + + + void loadDummyGui() { - void* handle = dlopen (GUI_MODULE_NAME, RTLD_LAZY|RTLD_LOCAL); + string moduleLocation = resolveModulePath (GUI_MODULE_TO_LOAD); + + void* handle = dlopen (moduleLocation.c_str(), RTLD_LAZY|RTLD_LOCAL); if (handle) { + typedef void (*VoidFunc)(void); + VoidFunc entryPoint = (VoidFunc) dlsym (handle, "start_dummy_gui"); if (!entryPoint) - ERROR (lumiera, "unable to resolve the entry point symbol after loading the GUI module."); + dieHard ("unable to resolve the entry point symbol after loading the GUI module."); else - (*entryPoint) (); + (*entryPoint) (); // activate loaded module } else - ERROR (lumiera, "unable to load %s", GUI_MODULE_NAME); + dieHard ("unable to load "+moduleLocation); } + string + resolveModulePath (string moduleName) + { + fsys::path exePathName (catchMyself()); + fsys::path modPathName (exePathName.remove_leaf() / getRelativeModuleLocation() / (moduleName+".lum") ); + + if (!fsys::exists (modPathName)) + dieHard ("Module "+modPathName.string()+" doesn't exist."); + + INFO (config, "found module %s", modPathName.string().c_str()); + return modPathName.string(); + } + + + } // namespace lumiera diff --git a/src/common/dummy-func.hpp b/src/common/dummy-func.hpp index cbf3a96bb..dde394a6b 100644 --- a/src/common/dummy-func.hpp +++ b/src/common/dummy-func.hpp @@ -4,11 +4,18 @@ * ******************************************************************************************/ +#ifndef COMMON_DUMMY_FUNC_H +#define COMMON_DUMMY_FUNC_H + #include "include/nobugcfg.h" +#include + namespace lumiera { + using std::string; + /** this is a function located in the liblumieracore.so, * which attempts to load the "pseudo-gui" as shared module * and invoke the gui-main. The sole purpose of this function @@ -16,5 +23,13 @@ namespace lumiera { */ void loadDummyGui(); + /** helper to establish the location to search for loadable modules. + * This is a simple demonstration of the basic technique used in the + * real application source to establish a plugin search path, based + * on the actual executable position plus compiled in and configured + * relative and absolute path specifications. + */ + string resolveModulePath (string moduleName); } // namespace lumiera +#endif