← Back to team overview

yade-dev team mailing list archive

[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;