yade-dev team mailing list archive
-
yade-dev team
-
Mailing list archive
-
Message #01744
[Branch ~yade-dev/yade/trunk] Rev 1703: 1. Clen the plugin loading logic a little (no nominal win32 support), support YADE_PREFIX for cha...
------------------------------------------------------------
revno: 1703
committer: Václav Šmilauer <vaclav@flux>
branch nick: trunk
timestamp: Wed 2009-08-19 12:48:06 +0200
message:
1. Clen the plugin loading logic a little (no nominal win32 support), support YADE_PREFIX for changing prefix (should be runtime-detected inthe future, anyway)
2. Use $ORIGIN in rpath to make yade relocatable; it can be fragile, let me know if there are troubles!
3. Add make check to the debian package (will be tested soon)
modified:
SConstruct
core/Omega.cpp
core/Omega.hpp
core/yade.cpp
debian/rules
gui/py/PythonUI.cpp
lib/factory/ClassFactory.cpp
lib/factory/ClassFactory.hpp
lib/factory/DynLibManager.cpp
lib/factory/DynLibManager.hpp
--
lp:yade
https://code.launchpad.net/~yade-dev/yade/trunk
Your team Yade developers is subscribed to branch lp:yade.
To unsubscribe from this branch go to https://code.launchpad.net/~yade-dev/yade/trunk/+edit-subscription.
=== modified file 'SConstruct'
--- SConstruct 2009-08-11 10:37:21 +0000
+++ SConstruct 2009-08-19 10:48:06 +0000
@@ -178,10 +178,10 @@
###########################################
import yadeSCons
## ALL generated stuff should go here - therefore we must determine it very early!!
-env['realVersion']=yadeSCons.getRealVersion()
if not env.has_key('version'):
+ env['realVersion']=yadeSCons.getRealVersion()
env['version']=env['realVersion']
-if not env['realVersion']: env['realVersion']=env['version']
+if not env.has_key('realVersion') or not env['realVersion']: env['realVersion']=env['version']
env['SUFFIX']='-'+env['version']+env['variant']
print "Yade version is `%s', installed files will be suffixed with `%s'."%(env['version'],env['SUFFIX'])
@@ -395,8 +395,9 @@
libDirs=('extra','gui','lib','py','plugins')
# where are we going to be installed... pkg/dem becomes pkg-dem
instLibDirs=[os.path.join('$PREFIX','lib','yade$SUFFIX',x) for x in libDirs]
-# where are we going to be run - may be different (packaging)
-runtimeLibDirs=[os.path.join('$runtimePREFIX','lib','yade$SUFFIX',x) for x in libDirs]
+## runtime library search directories; there can be up to 2 levels of libs, so we do in in quite a crude way here:
+## FIXME: find some better way to do that?
+runtimeLibDirs=[os.path.join(r"'$$$$ORIGIN'/../",x) for x in libDirs]+[os.path.join(r"'$$$$ORIGIN'/../../",x) for x in libDirs]
### PREPROCESSOR FLAGS
=== modified file 'core/Omega.cpp'
--- core/Omega.cpp 2009-08-03 10:02:11 +0000
+++ core/Omega.cpp 2009-08-19 10:48:06 +0000
@@ -182,16 +182,18 @@
}
void Omega::scanPlugins(string baseDir){
+ // silently skip non-existent plugin directories
+ if(!filesystem::exists(baseDir)) return;
try{
filesystem::recursive_directory_iterator Iend;
for(filesystem::recursive_directory_iterator I(baseDir); I!=Iend; ++I){
filesystem::path pth=I->path();
- if(filesystem::is_directory(pth) || ClassFactory::instance().libNameToSystemName(ClassFactory::instance().systemNameToLibName(filesystem::basename(pth)))!=(pth.leaf())){ LOG_DEBUG("File not considered a plugin: "<<pth.leaf()<<"."); continue; }
+ if(filesystem::is_directory(pth) || !algorithm::starts_with(pth.leaf(),"lib") || !algorithm::ends_with(pth.leaf(),".so")) { LOG_DEBUG("File not considered a plugin: "<<pth.leaf()<<"."); continue; }
LOG_DEBUG("Trying "<<pth.leaf());
filesystem::path name(filesystem::basename(pth));
if(name.leaf().length()<1) continue; // filter out 0-length filenames
string plugin=name.leaf();
- if(!ClassFactory::instance().load(ClassFactory::instance().systemNameToLibName(plugin))){
+ if(!ClassFactory::instance().load(pth.string())){
string err=ClassFactory::instance().lastError();
if(err.find(": undefined symbol: ")!=std::string::npos){
size_t pos=err.rfind(":"); assert(pos!=std::string::npos);
=== modified file 'core/Omega.hpp'
--- core/Omega.hpp 2009-08-03 10:02:11 +0000
+++ core/Omega.hpp 2009-08-19 10:48:06 +0000
@@ -99,7 +99,7 @@
shared_ptr<Preferences> preferences;
string yadeConfigPath; // FIXME - must be private and more clean
string yadeVersionName; // FIXME - public ?
-
+
// FIXME this is a hack. See GLViewer:86
// problem is that currently there is no way to transmit arguments between UI and GLDraw* methods.
// Omega will be deleted anyway, so, uh.. I am polluting it now :/
=== modified file 'core/yade.cpp'
--- core/yade.cpp 2009-08-06 21:05:28 +0000
+++ core/yade.cpp 2009-08-19 10:48:06 +0000
@@ -165,6 +165,9 @@
;
if(!isnan(std::numeric_limits<double>::quiet_NaN())) cerr<<
" -ffast-math? WARNING: NaN's will not work"<<endl;
+ if(getenv("YADE_PREFIX")){
+ cerr<<"\n** Using env variable YADE_PREFIX="<<getenv("YADE_PREFIX")<<" instead of compiled-in PREFIX="<<PREFIX<<" **\n";
+ }
}
@@ -260,9 +263,18 @@
LOG_INFO("Loading "<<yadeConfigFile.string()); IOFormatManager::loadFromFile("XMLFormatManager",yadeConfigFile.string(),"preferences",Omega::instance().preferences);
LOG_INFO("Loading plugins");
+
+ // set YADE_PREFIX to use prefix different from the one compiled-in; used for testing deb package when not installed
+ if(!getenv("YADE_PREFIX")){
Omega::instance().scanPlugins(string(PREFIX "/lib/yade" SUFFIX "/plugins" ));
Omega::instance().scanPlugins(string(PREFIX "/lib/yade" SUFFIX "/gui" ));
Omega::instance().scanPlugins(string(PREFIX "/lib/yade" SUFFIX "/extra" ));
+ } else {
+ string otherPREFIX(getenv("YADE_PREFIX"));
+ Omega::instance().scanPlugins(otherPREFIX+"/lib/yade" SUFFIX "/plugins");
+ Omega::instance().scanPlugins(otherPREFIX+"/lib/yade" SUFFIX "/gui");
+ Omega::instance().scanPlugins(otherPREFIX+"/lib/yade" SUFFIX "/extra");
+ }
Omega::instance().init();
// make directory for temporaries
=== modified file 'debian/rules'
--- debian/rules 2009-07-27 17:08:23 +0000
+++ debian/rules 2009-08-19 10:48:06 +0000
@@ -58,13 +58,17 @@
### (a) use fakeroot-tcp instead of fakeroot
### (b) use just 1 job
#debug build
- NO_SCONS_GET_RECENT= scons buildPrefix=debian runtimePREFIX=/usr version=${VERSION} linkStrategy=monolithic features=GTS,python,log4cxx,openGL openmp=True exclude=realtime-rigidbody,mass-spring,snow,fem PREFIX=debian/yade${_VERSION}-dbg/usr variant=-dbg optimize=0 debug=1
+ NO_SCONS_GET_RECENT= scons buildPrefix=debian runtimePREFIX=/usr version=${VERSION} pretty=0 linkStrategy=monolithic features=GTS,python,log4cxx,openGL openmp=True exclude=realtime-rigidbody,mass-spring,snow,fem PREFIX=debian/yade${_VERSION}-dbg/usr variant=-dbg optimize=0 debug=1
#optimized build
NO_SCONS_GET_RECENT= scons PREFIX=debian/yade${_VERSION}/usr variant='' optimize=1 debug=0
#install platform-independent files (docs, scripts, examples)
NO_SCONS_GET_RECENT= scons PREFIX=debian/yade${_VERSION}/usr debian/yade${_VERSION}/usr/share/doc/yade${_VERSION}-doc
-
+check: install
+ dh_testdir
+ dh_testroot
+ LD_PRELOAD= LD_LIBRARY_PATH=debian/yade${_VERSION}-dbg/usr/lib/yade${_VERSION}-dbg/lib YADE_PREFIX=debian/yade${_VERSION}-dbg/usr debian/yade${_VERSION}-dbg/usr/bin/yade${_VERSION}-dbg -x -N PythonUI -- -n -x scripts/regression-tests.py
+ LD_PRELOAD= LD_LIBRARY_PATH=debian/yade${_VERSION}/usr/lib/yade${_VERSION}/lib YADE_PREFIX=debian/yade${_VERSION}/usr debian/yade${_VERSION}/usr/bin/yade${_VERSION} -x -N PythonUI -- -n -x scripts/regression-tests.py
# Build architecture-independent files here.
binary-indep: build install
=== modified file 'gui/py/PythonUI.cpp'
--- gui/py/PythonUI.cpp 2009-07-18 07:35:07 +0000
+++ gui/py/PythonUI.cpp 2009-08-19 10:48:06 +0000
@@ -79,14 +79,15 @@
PyGILState_STATE pyState = PyGILState_Ensure();
LOG_DEBUG("Got Global Interpreter Lock, good.");
/* import yade (for startUI()) and yade.runtime (initially empty) namespaces */
- PyRun_SimpleString("import sys; sys.path.insert(0,'" PREFIX "/lib/yade" SUFFIX "/py')");
+ string prefix=getenv("YADE_PREFIX")?getenv("YADE_PREFIX"):PREFIX;
+ PyRun_SimpleString(("import sys; sys.path.insert(0,'"+prefix+"/lib/yade" SUFFIX "/py')").c_str());
PyRun_SimpleString("import yade");
PyRun_SimpleString("from __future__ import division");
#define PYTHON_DEFINE_STRING(pyName,cxxName) PyRun_SimpleString((string("yade.runtime." pyName "='")+cxxName+"'").c_str())
#define PYTHON_DEFINE_BOOL(pyName,cxxName) PyRun_SimpleString((string("yade.runtime." pyName "=")+(cxxName?"True":"False")).c_str())
// wrap those in python::handle<> ??
- PYTHON_DEFINE_STRING("prefix",PREFIX);
+ PYTHON_DEFINE_STRING("prefix",prefix);
PYTHON_DEFINE_STRING("suffix",SUFFIX);
PYTHON_DEFINE_STRING("executable",Omega::instance().origArgv[0]);
PYTHON_DEFINE_STRING("simulation",Omega::instance().getSimulationFileName());
@@ -96,7 +97,7 @@
{ ostringstream oss; oss<<"yade.runtime.argv=["; if(scriptArgs.size()>0){ FOREACH(string s, scriptArgs) oss<<"'"<<s<<"',"; } oss<<"]"; PyRun_SimpleString(oss.str().c_str()); }
#undef PYTHON_DEFINE_STRING
#undef PYTHON_DEFINE_BOOL
- execScript(PREFIX "/lib/yade" SUFFIX "/gui/PythonUI_rc.py");
+ execScript((prefix+"/lib/yade" SUFFIX "/gui/PythonUI_rc.py").c_str());
PyGILState_Release(pyState);
}
=== modified file 'lib/factory/ClassFactory.cpp'
--- lib/factory/ClassFactory.cpp 2009-05-24 17:22:30 +0000
+++ lib/factory/ClassFactory.cpp 2009-08-19 10:48:06 +0000
@@ -108,16 +108,6 @@
return dlm.lastError();
}
-string ClassFactory::libNameToSystemName(const string& name)
-{
- return dlm.libNameToSystemName(name);
-}
-
-string ClassFactory::systemNameToLibName(const string& name)
-{
- return dlm.systemNameToLibName(name);
-}
-
void ClassFactory::registerPluginClasses(const char* fileAndClasses[]){
assert(fileAndClasses[0]!=NULL); // must be file name
=== modified file 'lib/factory/ClassFactory.hpp'
--- lib/factory/ClassFactory.hpp 2009-08-03 14:25:05 +0000
+++ lib/factory/ClassFactory.hpp 2009-08-19 10:48:06 +0000
@@ -160,15 +160,12 @@
*/
bool isFactorable(const type_info& tp,bool& fundamental);
- bool load(const string& name);
+ bool load(const string& fullFileName);
std::string lastError();
void registerPluginClasses(const char* fileAndClasses[]);
list<string> pluginClasses;
- string libNameToSystemName(const string& name);
- string systemNameToLibName(const string& name);
-
virtual string getClassName() const { return "Factorable"; };
virtual string getBaseClassName(int ) const { return "";};
=== modified file 'lib/factory/DynLibManager.cpp'
--- lib/factory/DynLibManager.cpp 2009-05-24 17:22:30 +0000
+++ lib/factory/DynLibManager.cpp 2009-08-19 10:48:06 +0000
@@ -11,6 +11,7 @@
#include<fstream>
+#include<stdexcept>
#include<boost/filesystem/operations.hpp>
#include<boost/filesystem/convenience.hpp>
#include<string.h>
@@ -35,48 +36,28 @@
if(autoUnload) unloadAll();
}
-
-bool DynLibManager::load (const string& fullLibName, const string& libName )
-{
- if (libName.empty() || fullLibName.empty()){
- LOG_ERROR("Empty filename for library `"<<libName<<"'.");
- return false;
- }
-#ifdef WIN32
- if (isLoaded(libName)) return true;
- HINSTANCE handle = LoadLibraryA(fullLibName.c_str());
-#else
- void * handle = dlopen(fullLibName.data(), RTLD_NOW);
-#endif
+// load plugin with given filename
+bool DynLibManager::load (const string& lib){
+ if (lib.empty()) throw std::runtime_error(__FILE__ ": got empty library name to load.");
+ void* handle = dlopen(lib.c_str(),RTLD_NOW);
if (!handle) return !error();
- handles[libName] = handle;
+ handles[lib] = handle;
return true;
}
-
-bool DynLibManager::unload (const string libName)
+// unload plugin, given full filename
+bool DynLibManager::unload (const string& libName)
{
if (isLoaded(libName))
- #ifdef WIN32
- return FreeLibrary(handles[libName]);
- #else
- return closeLib(libName);
- #endif
- else
- return false;
+ return closeLib(libName);
+ else return false;
}
bool DynLibManager::unloadAll ()
{
- #ifdef WIN32
- std::map<const string, HINSTANCE>::iterator ith = handles.begin();
- std::map<const string, HINSTANCE>::iterator ithEnd = handles.end();
- #else
- std::map<const string, void *>::iterator ith = handles.begin();
- std::map<const string, void *>::iterator ithEnd = handles.end();
- #endif
-
+ std::map<const string, void *>::iterator ith = handles.begin();
+ std::map<const string, void *>::iterator ithEnd = handles.end();
for( ; ith!=ithEnd ; ++ith)
if ((*ith).first.length()!=0)
unload((*ith).first);
@@ -84,17 +65,10 @@
}
-bool DynLibManager::isLoaded (const string libName)
+bool DynLibManager::isLoaded (const string& libName)
{
-
- #ifdef WIN32
- std::map<const string, HINSTANCE>::iterator ith = handles.find(libName);
- #else
- std::map<const string, void *>::iterator ith = handles.find(libName);
- #endif
-
+ std::map<const string, void *>::iterator ith = handles.find(libName);
return (ith!= handles.end() && (*ith).second!=NULL);
-
}
@@ -106,13 +80,8 @@
bool DynLibManager::closeLib(const string libName)
{
- #ifdef WIN32
- FreeLibrary(handles[libName]);
- return !error();
- #else
- dlclose(handles[libName]);
- return !error();
- #endif
+ dlclose(handles[libName]);
+ return !error();
}
@@ -123,59 +92,9 @@
bool DynLibManager::error()
{
- #ifdef WIN32
- char* lpMsgBuf;
- const DWORD lastError = GetLastError();
-
- FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, lastError, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR) &lpMsgBuf, 0, NULL);
-
- std::string errMsg(lpMsgBuf);
- LocalFree(lpMsgBuf); // mind the FORMAT_MESSAGE_ALLOCATE_BUFFER !
-
- if (lastError != ERROR_SUCCESS)
- {
- lastError_ = errMsg;
- return true;
- }
-
- return false;
- #else
- char * error = dlerror();
- if (error != NULL)
- {
- lastError_ = error;
- }
- return (error!=NULL);
- #endif
-}
-
-
-string DynLibManager::libNameToSystemName(const string& name)
-{
- string systemName;
- #ifdef WIN32
- systemName = name + ".dll";
- #else
- systemName = "lib" + name + ".so";
- #endif
- return systemName;
-}
-
-
-string DynLibManager::systemNameToLibName(const string& name)
-{
- string libName;
- if(name.length()<=3){ // this arbitrary value may disappear once the logic below is dumped...
- // LOG_WARN("Filename `"<<name<<"' too short, returning empty string (cross thumbs).");
- return "[Garbage plugin file `"+name+"']";
- }
-
- #ifdef WIN32
- libName = name.substr(0,name.size()-4);
- #else
- libName = name.substr(3,name.size()-3);
- #endif
-
- return libName;
-}
+ char * error = dlerror();
+ if (error != NULL) { lastError_ = error; }
+ return (error!=NULL);
+}
+
=== modified file 'lib/factory/DynLibManager.hpp'
--- lib/factory/DynLibManager.hpp 2009-05-24 17:22:30 +0000
+++ lib/factory/DynLibManager.hpp 2009-08-19 10:48:06 +0000
@@ -9,14 +9,7 @@
#pragma once
-#ifdef WIN32
- #define OS "Windows"
- #define WIN32_LEAN_AND_MEAN
- #include <windows.h>
-#else
- #include <dlfcn.h>
- #define OS "Linux"
-#endif
+#include <dlfcn.h>
#include <string>
#include <iostream>
@@ -31,11 +24,7 @@
class DynLibManager
{
private :
- #ifdef WIN32
- std::map<const std::string, HINSTANCE> handles;
- #else
std::map<const std::string, void *> handles;
- #endif
bool autoUnload;
public :
@@ -43,17 +32,13 @@
~DynLibManager ();
void addBaseDirectory(const std::string& dir);
- bool load(const std::string& libName, const std::string& libName2);
- bool load(const std::string& pluginName){return load(libNameToSystemName(pluginName),pluginName);}
-
-
- bool unload (const string libName);
- bool isLoaded (const string libName);
+ bool load(const std::string& libName);
+
+ bool unload (const string& libName);
+ bool isLoaded (const string& libName);
bool unloadAll ();
void setAutoUnload ( bool enabled );
- string libNameToSystemName(const string& name);
- string systemNameToLibName(const string& name);
string lastError();
DECLARE_LOGGER;