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.
This commit is contained in:
Fischlurch 2011-02-01 05:10:45 +01:00
parent 29e2233e6a
commit 208b552955
3 changed files with 122 additions and 16 deletions

View file

@ -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).')

View file

@ -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 <unistd.h>
}
#include <dlfcn.h>
#include <nobug.h>
#include <boost/filesystem.hpp>
#include <boost/regex.hpp>
#include <string>
namespace lumiera {
const char * const GUI_MODULE_NAME = "modules/gtk_gui.lum";
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
typedef void (*VoidFunc)(void);
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

View file

@ -4,11 +4,18 @@
* ******************************************************************************************/
#ifndef COMMON_DUMMY_FUNC_H
#define COMMON_DUMMY_FUNC_H
#include "include/nobugcfg.h"
#include <string>
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