Merge pull request #1804 from mapnik/drop-ltdl-dependency

remove ltdl
This commit is contained in:
Artem Pavlenko 2013-04-10 02:30:29 -07:00
commit 06e629112d
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', 'tiff':'TIFF C library | configure with TIFF_LIBS & TIFF_INCLUDES',
'png':'PNG C library | configure with PNG_LIBS & PNG_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/', '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/', 'z':'Z compression library | more info: http://www.zlib.net/',
'm':'Basic math library, part of C++ stlib', 'm':'Basic math library, part of C++ stlib',
'pkg-config':'pkg-config tool | more info: http://pkg-config.freedesktop.org', '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), 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', ('ICU_LIB_NAME', 'The library name for icu (such as icuuc, sicuuc, or icucore)', 'icuuc',
PathVariable.PathAccept), 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'), 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_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), 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 # Adding the required prerequisite library directories to the include path for
# compiling and the library path for linking, respectively. # 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] inc_path = env['%s_INCLUDES' % required]
lib_path = env['%s_LIBS' % required] lib_path = env['%s_LIBS' % required]
env.AppendUnique(CPPPATH = os.path.realpath(inc_path)) env.AppendUnique(CPPPATH = os.path.realpath(inc_path))
@ -1140,7 +1137,6 @@ if not preconfigured:
LIBSHEADERS = [ LIBSHEADERS = [
['z', 'zlib.h', True,'C'], ['z', 'zlib.h', True,'C'],
['ltdl', 'ltdl.h', True,'C'],
[env['ICU_LIB_NAME'],'unicode/unistr.h',True,'C++'], [env['ICU_LIB_NAME'],'unicode/unistr.h',True,'C++'],
] ]

View file

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

View file

@ -29,21 +29,29 @@
// stl // stl
#include <string> #include <string>
// ltdl
#include <ltdl.h>
namespace mapnik namespace mapnik
{ {
// Opaque structure for handle
typedef struct _mapnik_lib_t mapnik_lib_t;
class PluginInfo : mapnik::noncopyable class PluginInfo : mapnik::noncopyable
{ {
private:
std::string name_;
lt_dlhandle module_;
public: 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(); ~PluginInfo();
std::string const& name() const; 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'] system = 'boost_system%s' % env['BOOST_APPEND']
# clear out and re-set libs for this env # 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']: if env['PROJ']:
lib_env['LIBS'].append('proj') lib_env['LIBS'].append('proj')

View file

@ -32,12 +32,8 @@
#include <boost/filesystem/operations.hpp> #include <boost/filesystem/operations.hpp>
#include <boost/algorithm/string.hpp> #include <boost/algorithm/string.hpp>
// ltdl
#include <ltdl.h>
// stl // stl
#include <algorithm> #include <algorithm>
#include <stdexcept>
#include <map> #include <map>
namespace mapnik { namespace mapnik {
@ -49,12 +45,12 @@ bool is_input_plugin(std::string const& filename)
datasource_cache::datasource_cache() datasource_cache::datasource_cache()
{ {
if (lt_dlinit()) throw std::runtime_error("lt_dlinit() failed"); PluginInfo::init();
} }
datasource_cache::~datasource_cache() datasource_cache::~datasource_cache()
{ {
lt_dlexit(); PluginInfo::exit();
} }
datasource_ptr datasource_cache::create(parameters const& params) datasource_ptr datasource_cache::create(parameters const& params)
@ -87,23 +83,22 @@ datasource_ptr datasource_cache::create(parameters const& params)
throw config_error(s); throw config_error(s);
} }
if (!itr->second->handle()) if (!itr->second->valid())
{ {
throw std::runtime_error(std::string("Cannot load library: ") + 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 // http://www.mr-edd.co.uk/blog/supressing_gcc_warnings
#ifdef __GNUC__ #ifdef __GNUC__
__extension__ __extension__
#endif #endif
create_ds* create_datasource = create_ds* create_datasource = reinterpret_cast<create_ds*>(itr->second->get_symbol("create"));
reinterpret_cast<create_ds*>(lt_dlsym(itr->second->handle(), "create"));
if (!create_datasource) if (!create_datasource)
{ {
throw std::runtime_error(std::string("Cannot load symbols: ") + throw std::runtime_error(std::string("Cannot load symbols: ") +
lt_dlerror()); itr->second->get_error());
} }
#ifdef MAPNIK_LOG #ifdef MAPNIK_LOG
@ -129,12 +124,6 @@ datasource_ptr datasource_cache::create(parameters const& params)
return ds; 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() std::string datasource_cache::plugin_directories()
{ {
return boost::algorithm::join(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; bool success = false;
try try
{ {
lt_dlhandle module = lt_dlopen(str.c_str()); boost::shared_ptr<PluginInfo> plugin = boost::make_shared<PluginInfo>(filename,"datasource_name");
if (module) if (plugin->valid())
{ {
// http://www.mr-edd.co.uk/blog/supressing_gcc_warnings if (plugin->name().empty())
#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)
{ {
MAPNIK_LOG_ERROR(datasource_cache) MAPNIK_LOG_ERROR(datasource_cache)
<< "Problem loading plugin library '" << "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 else
{ {
MAPNIK_LOG_ERROR(datasource_cache) MAPNIK_LOG_ERROR(datasource_cache)
<< "Problem loading plugin library: " << "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) catch (std::exception const& ex)
{ {
MAPNIK_LOG_ERROR(datasource_cache) MAPNIK_LOG_ERROR(datasource_cache)
<< "Exception caught while loading plugin library: " << "Exception caught while loading plugin library: "
<< str << " (" << ex.what() << ")"; << filename << " (" << ex.what() << ")";
} }
return success; return success;
} }

View file

@ -21,30 +21,86 @@
*****************************************************************************/ *****************************************************************************/
#include <mapnik/plugin.hpp> #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 namespace mapnik
{ {
PluginInfo::PluginInfo (std::string const& name,const lt_dlhandle module) struct _mapnik_lib_t {
:name_(name),module_(module) {} 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() PluginInfo::~PluginInfo()
{ {
if (module_) 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 std::string const& PluginInfo::name() const
{ {
return name_; 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
}
} }