remove ltdl to reduce dependencies and because calling dlopen/LoadLibrary is easy

This commit is contained in:
Dane Springmeyer 2013-04-09 19:37:02 -07:00
parent a8e2ef7cc7
commit 79a216f349
6 changed files with 101 additions and 61 deletions

View file

@ -68,7 +68,6 @@ pretty_dep_names = {
'tiff':'TIFF C library | configure with TIFF_LIBS & TIFF_INCLUDES',
'png':'PNG C library | configure with PNG_LIBS & PNG_INCLUDES',
'icuuc':'ICU C++ library | configure with ICU_LIBS & ICU_INCLUDES or use ICU_LIB_NAME to specify custom lib name | more info: http://site.icu-project.org/',
'ltdl':'GNU Libtool | more info: http://www.gnu.org/software/libtool',
'z':'Z compression library | more info: http://www.zlib.net/',
'm':'Basic math library, part of C++ stlib',
'pkg-config':'pkg-config tool | more info: http://pkg-config.freedesktop.org',
@ -309,8 +308,6 @@ opts.AddVariables(
PathVariable('ICU_LIBS','Search path for ICU include files','/usr/' + LIBDIR_SCHEMA_DEFAULT, PathVariable.PathAccept),
('ICU_LIB_NAME', 'The library name for icu (such as icuuc, sicuuc, or icucore)', 'icuuc',
PathVariable.PathAccept),
PathVariable('LTDL_INCLUDES', 'Search path for libltdl (part of libtool) include files', '/usr/include', PathVariable.PathAccept),
PathVariable('LTDL_LIBS','Search path for libltdl (ltdl.h) library files','/usr/' + LIBDIR_SCHEMA_DEFAULT, PathVariable.PathAccept),
BoolVariable('PNG', 'Build Mapnik with PNG read and write support', 'True'),
PathVariable('PNG_INCLUDES', 'Search path for libpng include files', '/usr/include', PathVariable.PathAccept),
PathVariable('PNG_LIBS','Search path for libpng library files','/usr/' + LIBDIR_SCHEMA_DEFAULT, PathVariable.PathAccept),
@ -1115,7 +1112,7 @@ if not preconfigured:
# Adding the required prerequisite library directories to the include path for
# compiling and the library path for linking, respectively.
for required in ('ICU', 'SQLITE', 'LTDL'):
for required in ('ICU', 'SQLITE'):
inc_path = env['%s_INCLUDES' % required]
lib_path = env['%s_LIBS' % required]
env.AppendUnique(CPPPATH = os.path.realpath(inc_path))
@ -1140,7 +1137,6 @@ if not preconfigured:
LIBSHEADERS = [
['z', 'zlib.h', True,'C'],
['ltdl', 'ltdl.h', True,'C'],
[env['ICU_LIB_NAME'],'unicode/unistr.h',True,'C++'],
]

View file

@ -35,8 +35,6 @@
// stl
#include <map>
struct lt__handle;
namespace mapnik {
class PluginInfo;
@ -57,7 +55,6 @@ private:
~datasource_cache();
std::map<std::string,boost::shared_ptr<PluginInfo> > plugins_;
bool registered_;
bool insert(std::string const& name,lt__handle * const module);
std::vector<std::string> plugin_directories_;
};
}

View file

@ -29,21 +29,29 @@
// stl
#include <string>
// ltdl
#include <ltdl.h>
namespace mapnik
{
// Opaque structure for handle
typedef struct _mapnik_lib_t mapnik_lib_t;
class PluginInfo : mapnik::noncopyable
{
private:
std::string name_;
lt_dlhandle module_;
public:
PluginInfo (std::string const& name,const lt_dlhandle module);
typedef const char * name_func();
PluginInfo (std::string const& filename,
std::string const& library_name);
~PluginInfo();
std::string const& name() const;
lt_dlhandle handle() const;
bool valid() const;
std::string get_error() const;
void * get_symbol(std::string const& sym_name) const;
static void init();
static void exit();
private:
std::string filename_;
std::string name_;
mapnik_lib_t * module_;
};
}

View file

@ -57,7 +57,7 @@ regex = 'boost_regex%s' % env['BOOST_APPEND']
system = 'boost_system%s' % env['BOOST_APPEND']
# clear out and re-set libs for this env
lib_env['LIBS'] = ['freetype','ltdl','z',env['ICU_LIB_NAME'],filesystem,system,regex]
lib_env['LIBS'] = ['freetype','z',env['ICU_LIB_NAME'],filesystem,system,regex]
if env['PROJ']:
lib_env['LIBS'].append('proj')

View file

@ -32,12 +32,8 @@
#include <boost/filesystem/operations.hpp>
#include <boost/algorithm/string.hpp>
// ltdl
#include <ltdl.h>
// stl
#include <algorithm>
#include <stdexcept>
#include <map>
namespace mapnik {
@ -49,12 +45,12 @@ bool is_input_plugin(std::string const& filename)
datasource_cache::datasource_cache()
{
if (lt_dlinit()) throw std::runtime_error("lt_dlinit() failed");
PluginInfo::init();
}
datasource_cache::~datasource_cache()
{
lt_dlexit();
PluginInfo::exit();
}
datasource_ptr datasource_cache::create(parameters const& params)
@ -87,23 +83,22 @@ datasource_ptr datasource_cache::create(parameters const& params)
throw config_error(s);
}
if (!itr->second->handle())
if (!itr->second->valid())
{
throw std::runtime_error(std::string("Cannot load library: ") +
lt_dlerror());
itr->second->get_error());
}
// http://www.mr-edd.co.uk/blog/supressing_gcc_warnings
#ifdef __GNUC__
__extension__
#endif
create_ds* create_datasource =
reinterpret_cast<create_ds*>(lt_dlsym(itr->second->handle(), "create"));
create_ds* create_datasource = reinterpret_cast<create_ds*>(itr->second->get_symbol("create"));
if (!create_datasource)
{
throw std::runtime_error(std::string("Cannot load symbols: ") +
lt_dlerror());
itr->second->get_error());
}
#ifdef MAPNIK_LOG
@ -129,12 +124,6 @@ datasource_ptr datasource_cache::create(parameters const& params)
return ds;
}
bool datasource_cache::insert(std::string const& type,const lt_dlhandle module)
{
return plugins_.insert(std::make_pair(type,boost::make_shared<PluginInfo>
(type,module))).second;
}
std::string datasource_cache::plugin_directories()
{
return boost::algorithm::join(plugin_directories_,", ");
@ -185,47 +174,41 @@ void datasource_cache::register_datasources(std::string const& str)
}
}
bool datasource_cache::register_datasource(std::string const& str)
bool datasource_cache::register_datasource(std::string const& filename)
{
bool success = false;
try
{
lt_dlhandle module = lt_dlopen(str.c_str());
if (module)
boost::shared_ptr<PluginInfo> plugin = boost::make_shared<PluginInfo>(filename,"datasource_name");
if (plugin->valid())
{
// http://www.mr-edd.co.uk/blog/supressing_gcc_warnings
#ifdef __GNUC__
__extension__
#endif
datasource_name* ds_name =
reinterpret_cast<datasource_name*>(lt_dlsym(module, "datasource_name"));
if (ds_name && insert(ds_name(),module))
{
MAPNIK_LOG_DEBUG(datasource_cache)
<< "datasource_cache: Registered="
<< ds_name();
success = true;
}
else if (!ds_name)
if (plugin->name().empty())
{
MAPNIK_LOG_ERROR(datasource_cache)
<< "Problem loading plugin library '"
<< str << "' (plugin is lacking compatible interface)";
<< filename << "' (plugin is lacking compatible interface)";
}
else
{
plugins_.insert(std::make_pair(plugin->name(),plugin));
MAPNIK_LOG_DEBUG(datasource_cache)
<< "datasource_cache: Registered="
<< plugin->name();
success = true;
}
}
else
{
MAPNIK_LOG_ERROR(datasource_cache)
<< "Problem loading plugin library: "
<< str << " (dlopen failed - plugin likely has an unsatisfied dependency or incompatible ABI)";
<< filename << " (dlopen failed - plugin likely has an unsatisfied dependency or incompatible ABI)";
}
}
catch (std::exception const& ex)
{
MAPNIK_LOG_ERROR(datasource_cache)
<< "Exception caught while loading plugin library: "
<< str << " (" << ex.what() << ")";
<< filename << " (" << ex.what() << ")";
}
return success;
}

View file

@ -21,30 +21,86 @@
*****************************************************************************/
#include <mapnik/plugin.hpp>
#include <ltdl.h>
#include <stdexcept>
#ifdef _WINDOWS
#include <windows.h>
#define handle HMODULE
#define dlsym GetProcAddress
#define dlclose FreeLibrary
#define dlerror GetLastError
#else
#include <dlfcn.h>
#define handle void *
#endif
// TODO - handle/report dlerror
namespace mapnik
{
PluginInfo::PluginInfo (std::string const& name,const lt_dlhandle module)
:name_(name),module_(module) {}
struct _mapnik_lib_t {
handle dl;
};
PluginInfo::PluginInfo(std::string const& filename,
std::string const& library_name)
: filename_(filename),
name_(),
module_(new mapnik_lib_t)
{
#ifdef _WINDOWS
if (module_) module_->dl = LoadLibraryA(filename.c_str());
#else
if (module_) module_->dl = dlopen(filename.c_str(),RTLD_LAZY);
#endif
if (module_ && module_->dl)
{
name_func* name = reinterpret_cast<name_func*>(dlsym(module_->dl, library_name.c_str()));
if (name) name_ = name();
}
}
PluginInfo::~PluginInfo()
{
if (module_)
{
lt_dlclose(module_),module_=0;
if (module_->dl) dlclose(module_->dl),module_->dl=0;
delete module_;
}
}
void * PluginInfo::get_symbol(std::string const& sym_name) const
{
return dlsym(module_->dl, sym_name.c_str());
}
std::string const& PluginInfo::name() const
{
return name_;
}
lt_dlhandle PluginInfo::handle() const
bool PluginInfo::valid() const
{
return module_;
if (module_ && module_->dl && !name_.empty()) return true;
return false;
}
std::string PluginInfo::get_error() const
{
return std::string("could not open: '") + name_ + "'";
}
void PluginInfo::init()
{
// do any initialization needed
}
void PluginInfo::exit()
{
// do any shutdown needed
}
}