From 3fbf4df67d78dbf7f69bd05fe7d0bc199f73d632 Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Thu, 16 May 2013 11:33:23 -0700 Subject: [PATCH] add support for statically linking datasource input plugins - closes #1810 and #1821 - refs #249 --- CHANGELOG.md | 2 + SConstruct | 34 +++--- bindings/python/build.py | 2 +- include/mapnik/datasource.hpp | 30 +++--- plugins/input/csv/build.py | 63 +++++++---- plugins/input/gdal/build.py | 52 +++++---- plugins/input/geojson/build.py | 50 ++++++--- plugins/input/occi/build.py | 46 +++++--- plugins/input/ogr/build.py | 67 +++++++----- plugins/input/osm/build.py | 47 ++++++--- plugins/input/postgis/build.py | 57 ++++++---- plugins/input/python/build.py | 110 ++++++++++++-------- plugins/input/raster/build.py | 48 ++++++--- plugins/input/rasterlite/build.py | 47 ++++++--- plugins/input/shape/build.py | 70 ++++++++----- plugins/input/sqlite/build.py | 51 +++++---- plugins/input/templates/helloworld/build.py | 87 +++++++++------- src/build.py | 43 ++++++-- src/datasource_cache.cpp | 70 ++++++++----- utils/mapnik-config/build.py | 1 + 20 files changed, 622 insertions(+), 355 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b54510ea5..327177a4b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -68,6 +68,8 @@ For a complete change history, see the git log. now the combined layer extents will be again respected: they will be clipped to the maximum-extent if possible and only when back-projecting fails for all layers will the maximum-extent be used as a fallback (#1473) +- Compile time flag called `PLUGIN_LINKING` to allow input datasource plugins to be statically linked with the mapnik library (#249) + ## Mapnik 2.1.0 Released Aug 23, 2012 diff --git a/SConstruct b/SConstruct index e6e3ac62f..73a650874 100644 --- a/SConstruct +++ b/SConstruct @@ -313,8 +313,8 @@ opts.AddVariables( ('XML2_CONFIG', 'The path to the xml2-config executable.', 'xml2-config'), PathVariable('ICU_INCLUDES', 'Search path for ICU include files', '/usr/include', 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', -PathVariable.PathAccept), + ('ICU_LIB_NAME', 'The library name for icu (such as icuuc, sicuuc, or icucore)', 'icuuc', 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), @@ -357,6 +357,9 @@ PathVariable.PathAccept), BoolVariable('ENABLE_STATS', 'Enable global statistics during map processing', 'False'), ('DEFAULT_LOG_SEVERITY', 'The default severity of the logger (eg. ' + ', '.join(severities) + ')', 'error'), + # Plugin linking + EnumVariable('PLUGIN_LINKING', "Set plugin linking with libmapnik", 'shared', ['shared','static']), + # Other variables BoolVariable('SHAPE_MEMORY_MAPPED_FILE', 'Utilize memory-mapped files in Shapefile Plugin (higher memory usage, better performance)', 'True'), ('SYSTEM_FONTS','Provide location for python bindings to register fonts (if provided then the bundled DejaVu fonts are not installed)',''), @@ -439,7 +442,7 @@ pickle_store = [# Scons internal variables 'LIBMAPNIK_DEFINES', 'LIBMAPNIK_CXXFLAGS', 'CAIRO_LIBPATHS', - 'CAIRO_LINKFLAGS', + 'CAIRO_ALL_LIBS', 'CAIRO_CPPPATHS', 'SVG_RENDERER', 'SQLITE_LINKFLAGS', @@ -1039,11 +1042,12 @@ if not preconfigured: env['SKIPPED_DEPS'] = [] env['HAS_CAIRO'] = False env['CAIRO_LIBPATHS'] = [] - env['CAIRO_LINKFLAGS'] = [] + env['CAIRO_ALL_LIBS'] = [] env['CAIRO_CPPPATHS'] = [] env['HAS_PYCAIRO'] = False env['HAS_LIBXML2'] = False env['LIBMAPNIK_LIBS'] = [] + env['LIBMAPNIK_LINKFLAGS'] = [] env['LIBMAPNIK_CPPATHS'] = [] env['LIBMAPNIK_DEFINES'] = [] env['LIBMAPNIK_CXXFLAGS'] = [] @@ -1401,9 +1405,9 @@ if not preconfigured: #os.path.join(c_inc,'include/libpng'), ] ) - env["CAIRO_LINKFLAGS"] = ['cairo'] + env["CAIRO_ALL_LIBS"] = ['cairo'] if env['RUNTIME_LINK'] == 'static': - env["CAIRO_LINKFLAGS"].extend( + env["CAIRO_ALL_LIBS"].extend( ['pixman-1','expat','fontconfig','iconv'] ) # todo - run actual checkLib? @@ -1426,7 +1430,7 @@ if not preconfigured: cairo_env.ParseConfig(cmd) for lib in cairo_env['LIBS']: if not lib in env['LIBS']: - env["CAIRO_LINKFLAGS"].append(lib) + env["CAIRO_ALL_LIBS"].append(lib) for lpath in cairo_env['LIBPATH']: if not lpath in env['LIBPATH']: env["CAIRO_LIBPATHS"].append(lpath) @@ -1794,7 +1798,8 @@ if not HELP_REQUESTED: for plugin in env['REQUESTED_PLUGINS']: details = env['PLUGINS'][plugin] if details['lib'] in env['LIBS']: - SConscript('plugins/input/%s/build.py' % plugin) + if env['PLUGIN_LINKING'] == 'shared': + SConscript('plugins/input/%s/build.py' % plugin) if plugin == 'ogr': OGR_BUILT = True if plugin == 'gdal': GDAL_BUILT = True if plugin == 'ogr' or plugin == 'gdal': @@ -1803,8 +1808,9 @@ if not HELP_REQUESTED: else: env['LIBS'].remove(details['lib']) elif not details['lib']: - # build internal shape and raster plugins - SConscript('plugins/input/%s/build.py' % plugin) + if env['PLUGIN_LINKING'] == 'shared': + # build internal datasource input plugins + SConscript('plugins/input/%s/build.py' % plugin) else: color_print(1,"Notice: dependencies not met for plugin '%s', not building..." % plugin) # also clear out locally built target @@ -1818,11 +1824,11 @@ if not HELP_REQUESTED: # installed plugins that we are no longer building if 'install' in COMMAND_LINE_TARGETS: for plugin in PLUGINS.keys(): - if plugin not in env['REQUESTED_PLUGINS']: - plugin_path = os.path.join(env['MAPNIK_INPUT_PLUGINS_DEST'],'%s.input' % plugin) - if os.path.exists(plugin_path): + plugin_path = os.path.join(env['MAPNIK_INPUT_PLUGINS_DEST'],'%s.input' % plugin) + if os.path.exists(plugin_path): + if plugin not in env['REQUESTED_PLUGINS'] or env['PLUGIN_LINKING'] == 'static': color_print(3,"Notice: removing out of date plugin: '%s'" % plugin_path) - os.unlink(plugin_path) + os.unlink(plugin_path) # Build the c++ rundemo app if requested if env['DEMO']: diff --git a/bindings/python/build.py b/bindings/python/build.py index 40bc6c254..44d8c1376 100644 --- a/bindings/python/build.py +++ b/bindings/python/build.py @@ -177,7 +177,7 @@ if 'uninstall' not in COMMAND_LINE_TARGETS: py_env.Append(CPPPATH = env['CAIRO_CPPPATHS']) py_env.Append(CPPDEFINES = '-DHAVE_CAIRO') if env['PLATFORM'] == 'Darwin': - py_env.Append(LIBS=env['CAIRO_LINKFLAGS']) + py_env.Append(LIBS=env['CAIRO_ALL_LIBS']) if env['HAS_PYCAIRO']: py_env.ParseConfig('pkg-config --cflags pycairo') diff --git a/include/mapnik/datasource.hpp b/include/mapnik/datasource.hpp index 2967cb5bb..b2edb91d4 100644 --- a/include/mapnik/datasource.hpp +++ b/include/mapnik/datasource.hpp @@ -134,19 +134,23 @@ public: typedef boost::shared_ptr datasource_ptr; -#define DATASOURCE_PLUGIN(classname) \ - extern "C" MAPNIK_EXP const char * datasource_name() \ - { \ - return classname::name(); \ - } \ - extern "C" MAPNIK_EXP datasource* create(parameters const& params) \ - { \ - return new classname(params); \ - } \ - extern "C" MAPNIK_EXP void destroy(datasource *ds) \ - { \ - delete ds; \ - } +#ifdef MAPNIK_STATIC_PLUGINS + #define DATASOURCE_PLUGIN(classname) +#else + #define DATASOURCE_PLUGIN(classname) \ + extern "C" MAPNIK_EXP const char * datasource_name() \ + { \ + return classname::name(); \ + } \ + extern "C" MAPNIK_EXP datasource* create(parameters const& params) \ + { \ + return new classname(params); \ + } \ + extern "C" MAPNIK_EXP void destroy(datasource *ds) \ + { \ + delete ds; \ + } +#endif } diff --git a/plugins/input/csv/build.py b/plugins/input/csv/build.py index ae41bf6d1..d3dfdea12 100644 --- a/plugins/input/csv/build.py +++ b/plugins/input/csv/build.py @@ -1,37 +1,62 @@ -#!/usr/bin/env python +# +# This file is part of Mapnik (c++ mapping toolkit) +# +# Copyright (C) 2013 Artem Pavlenko +# +# Mapnik is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# +# -import os Import ('plugin_base') Import ('env') PLUGIN_NAME = 'csv' -install_dest = env['MAPNIK_INPUT_PLUGINS_DEST'] plugin_env = plugin_base.Clone() plugin_sources = Split( """ %(PLUGIN_NAME)s_datasource.cpp """ % locals() - ) +) +# Link Library to Dependencies libraries = [] -libraries.append('mapnik') libraries.append('boost_system%s' % env['BOOST_APPEND']) libraries.append(env['ICU_LIB_NAME']) - -TARGET = plugin_env.SharedLibrary( - '../%s' % PLUGIN_NAME, - SHLIBPREFIX='', - SHLIBSUFFIX='.input', - source=plugin_sources, - LIBS=libraries, - LINKFLAGS=env.get('CUSTOM_LDFLAGS') - ) -# if the plugin links to libmapnik ensure it is built first -Depends(TARGET, env.subst('../../../src/%s' % env['MAPNIK_LIB_NAME'])) +if env['PLUGIN_LINKING'] == 'shared': + libraries.append('mapnik') -if 'uninstall' not in COMMAND_LINE_TARGETS: - env.Install(install_dest, TARGET) - env.Alias('install', install_dest) + TARGET = plugin_env.SharedLibrary('../%s' % PLUGIN_NAME, + SHLIBPREFIX='', + SHLIBSUFFIX='.input', + source=plugin_sources, + LIBS=libraries, + LINKFLAGS=env.get('CUSTOM_LDFLAGS')) + + # if the plugin links to libmapnik ensure it is built first + Depends(TARGET, env.subst('../../../src/%s' % env['MAPNIK_LIB_NAME'])) + + if 'uninstall' not in COMMAND_LINE_TARGETS: + env.Install(env['MAPNIK_INPUT_PLUGINS_DEST'], TARGET) + env.Alias('install', env['MAPNIK_INPUT_PLUGINS_DEST']) + +plugin_obj = { + 'LIBS': libraries, + 'SOURCES': plugin_sources, +} + +Return('plugin_obj') diff --git a/plugins/input/gdal/build.py b/plugins/input/gdal/build.py index 501ff089f..2f2f535e2 100644 --- a/plugins/input/gdal/build.py +++ b/plugins/input/gdal/build.py @@ -1,7 +1,7 @@ # # This file is part of Mapnik (c++ mapping toolkit) # -# Copyright (C) 2007 Artem Pavlenko, Jean-Francois Doyon +# Copyright (C) 2013 Artem Pavlenko # # Mapnik is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public @@ -22,35 +22,47 @@ Import ('plugin_base') Import ('env') -prefix = env['PREFIX'] +PLUGIN_NAME = 'gdal' plugin_env = plugin_base.Clone() -gdal_src = Split( +plugin_sources = Split( """ - gdal_datasource.cpp - gdal_featureset.cpp - """ - ) - -# clear out and rebuild libs -plugin_env['LIBS'] = [env['PLUGINS']['gdal']['lib']] + %(PLUGIN_NAME)s_datasource.cpp + %(PLUGIN_NAME)s_featureset.cpp + """ % locals() +) # Link Library to Dependencies -plugin_env['LIBS'].append('mapnik') -plugin_env['LIBS'].append('boost_system%s' % env['BOOST_APPEND']) -plugin_env['LIBS'].append(env['ICU_LIB_NAME']) +libraries = [env['PLUGINS']['gdal']['lib']] +libraries.append('boost_system%s' % env['BOOST_APPEND']) +libraries.append(env['ICU_LIB_NAME']) if env['RUNTIME_LINK'] == 'static': cmd = 'gdal-config --dep-libs' plugin_env.ParseConfig(cmd) - plugin_env['LIBS'].append('proj') + libraries.append('proj') -input_plugin = plugin_env.SharedLibrary('../gdal', source=gdal_src, SHLIBPREFIX='', SHLIBSUFFIX='.input', LINKFLAGS=env['CUSTOM_LDFLAGS']) +if env['PLUGIN_LINKING'] == 'shared': + libraries.append('mapnik') -# if the plugin links to libmapnik ensure it is built first -Depends(input_plugin, env.subst('../../../src/%s' % env['MAPNIK_LIB_NAME'])) + TARGET = plugin_env.SharedLibrary('../%s' % PLUGIN_NAME, + SHLIBPREFIX='', + SHLIBSUFFIX='.input', + source=plugin_sources, + LIBS=libraries, + LINKFLAGS=env['CUSTOM_LDFLAGS']) -if 'uninstall' not in COMMAND_LINE_TARGETS: - env.Install(env['MAPNIK_INPUT_PLUGINS_DEST'], input_plugin) - env.Alias('install', env['MAPNIK_INPUT_PLUGINS_DEST']) + # if the plugin links to libmapnik ensure it is built first + Depends(TARGET, env.subst('../../../src/%s' % env['MAPNIK_LIB_NAME'])) + + if 'uninstall' not in COMMAND_LINE_TARGETS: + env.Install(env['MAPNIK_INPUT_PLUGINS_DEST'], TARGET) + env.Alias('install', env['MAPNIK_INPUT_PLUGINS_DEST']) + +plugin_obj = { + 'LIBS': libraries, + 'SOURCES': plugin_sources, +} + +Return('plugin_obj') diff --git a/plugins/input/geojson/build.py b/plugins/input/geojson/build.py index f463862a1..73aeb125f 100644 --- a/plugins/input/geojson/build.py +++ b/plugins/input/geojson/build.py @@ -1,7 +1,7 @@ # # This file is part of Mapnik (c++ mapping toolkit) # -# Copyright (C) 2012 Artem Pavlenko +# Copyright (C) 2013 Artem Pavlenko # # Mapnik is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public @@ -17,7 +17,7 @@ # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # - +# Import ('env') @@ -32,27 +32,45 @@ if not can_build: print 'WARNING: skipping building the optional geojson datasource plugin which requires boost >= 1.47' else: Import ('plugin_base') - prefix = env['PREFIX'] + + PLUGIN_NAME = 'geojson' + plugin_env = plugin_base.Clone() - geojson_src = Split( + + plugin_sources = Split( """ - geojson_datasource.cpp - geojson_featureset.cpp - """ - ) - libraries = [] + %(PLUGIN_NAME)s_datasource.cpp + %(PLUGIN_NAME)s_featureset.cpp + """ % locals() + ) + # Link Library to Dependencies - libraries.append('mapnik') + libraries = [] libraries.append(env['ICU_LIB_NAME']) libraries.append('boost_system%s' % env['BOOST_APPEND']) if env['THREADING'] == 'multi': libraries.append('boost_thread%s' % env['BOOST_APPEND']) - input_plugin = plugin_env.SharedLibrary('../geojson', source=geojson_src, SHLIBPREFIX='', SHLIBSUFFIX='.input', LIBS=libraries, LINKFLAGS=env['CUSTOM_LDFLAGS']) + if env['PLUGIN_LINKING'] == 'shared': + libraries.append('mapnik') - # if the plugin links to libmapnik ensure it is built first - Depends(input_plugin, env.subst('../../../src/%s' % env['MAPNIK_LIB_NAME'])) + TARGET = plugin_env.SharedLibrary('../%s' % PLUGIN_NAME, + SHLIBPREFIX='', + SHLIBSUFFIX='.input', + source=plugin_sources, + LIBS=libraries, + LINKFLAGS=env['CUSTOM_LDFLAGS']) - if 'uninstall' not in COMMAND_LINE_TARGETS: - env.Install(env['MAPNIK_INPUT_PLUGINS_DEST'], input_plugin) - env.Alias('install', env['MAPNIK_INPUT_PLUGINS_DEST']) + # if the plugin links to libmapnik ensure it is built first + Depends(TARGET, env.subst('../../../src/%s' % env['MAPNIK_LIB_NAME'])) + + if 'uninstall' not in COMMAND_LINE_TARGETS: + env.Install(env['MAPNIK_INPUT_PLUGINS_DEST'], TARGET) + env.Alias('install', env['MAPNIK_INPUT_PLUGINS_DEST']) + + plugin_obj = { + 'LIBS': libraries, + 'SOURCES': plugin_sources, + } + + Return('plugin_obj') diff --git a/plugins/input/occi/build.py b/plugins/input/occi/build.py index 050cbce9b..946d32dbb 100644 --- a/plugins/input/occi/build.py +++ b/plugins/input/occi/build.py @@ -1,7 +1,7 @@ # # This file is part of Mapnik (c++ mapping toolkit) # -# Copyright (C) 2007 Artem Pavlenko, Jean-Francois Doyon +# Copyright (C) 2013 Artem Pavlenko # # Mapnik is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public @@ -17,35 +17,49 @@ # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # -# +# Import ('plugin_base') Import ('env') -prefix = env['PREFIX'] +PLUGIN_NAME = 'occi' plugin_env = plugin_base.Clone() -occi_src = Split( +plugin_sources = Split( """ - occi_types.cpp - occi_datasource.cpp - occi_featureset.cpp + %(PLUGIN_NAME)s_types.cpp + %(PLUGIN_NAME)s_datasource.cpp + %(PLUGIN_NAME)s_featureset.cpp spatial_classesm.cpp spatial_classeso.cpp - """ - ) + """ % locals() +) libraries = [ 'occi', 'ociei' ] -libraries.append('mapnik') libraries.append('boost_system%s' % env['BOOST_APPEND']) libraries.append(env['ICU_LIB_NAME']) -input_plugin = plugin_env.SharedLibrary('../occi', source=occi_src, SHLIBPREFIX='', SHLIBSUFFIX='.input', LIBS=libraries, LINKFLAGS=env['CUSTOM_LDFLAGS']) +if env['PLUGIN_LINKING'] == 'shared': + libraries.append('mapnik') -# if the plugin links to libmapnik ensure it is built first -Depends(input_plugin, env.subst('../../../src/%s' % env['MAPNIK_LIB_NAME'])) + TARGET = plugin_env.SharedLibrary('../%s' % PLUGIN_NAME, + SHLIBPREFIX='', + SHLIBSUFFIX='.input', + source=plugin_sources, + LIBS=libraries, + LINKFLAGS=env['CUSTOM_LDFLAGS']) -if 'uninstall' not in COMMAND_LINE_TARGETS: - env.Install(env['MAPNIK_INPUT_PLUGINS_DEST'], input_plugin) - env.Alias('install', env['MAPNIK_INPUT_PLUGINS_DEST']) + # if the plugin links to libmapnik ensure it is built first + Depends(TARGET, env.subst('../../../src/%s' % env['MAPNIK_LIB_NAME'])) + + if 'uninstall' not in COMMAND_LINE_TARGETS: + env.Install(env['MAPNIK_INPUT_PLUGINS_DEST'], TARGET) + env.Alias('install', env['MAPNIK_INPUT_PLUGINS_DEST']) + +plugin_obj = { + 'LIBS': libraries, + 'SOURCES': plugin_sources, +} + +Return('plugin_obj') diff --git a/plugins/input/ogr/build.py b/plugins/input/ogr/build.py index 26512b856..881d20006 100644 --- a/plugins/input/ogr/build.py +++ b/plugins/input/ogr/build.py @@ -1,7 +1,7 @@ # # This file is part of Mapnik (c++ mapping toolkit) # -# Copyright (C) 2007 Artem Pavlenko, Jean-Francois Doyon +# Copyright (C) 2013 Artem Pavlenko # # Mapnik is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public @@ -17,50 +17,67 @@ # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # -# - +# Import ('plugin_base') Import ('env') -prefix = env['PREFIX'] +PLUGIN_NAME = 'ogr' plugin_env = plugin_base.Clone() -ogr_src = Split( +plugin_sources = Split( """ - ogr_converter.cpp - ogr_datasource.cpp - ogr_featureset.cpp - ogr_index_featureset.cpp - """ - ) - -plugin_env['LIBS'] = [env['PLUGINS']['ogr']['lib']] + %(PLUGIN_NAME)s_converter.cpp + %(PLUGIN_NAME)s_datasource.cpp + %(PLUGIN_NAME)s_featureset.cpp + %(PLUGIN_NAME)s_index_featureset.cpp + """ % locals() +) # Link Library to Dependencies -plugin_env['LIBS'].append('mapnik') -plugin_env['LIBS'].append(env['ICU_LIB_NAME']) -plugin_env['LIBS'].append('boost_system%s' % env['BOOST_APPEND']) -plugin_env['LIBS'].append('boost_filesystem%s' % env['BOOST_APPEND']) +libraries = [env['PLUGINS']['ogr']['lib']] +libraries.append(env['ICU_LIB_NAME']) +libraries.append('boost_system%s' % env['BOOST_APPEND']) +libraries.append('boost_filesystem%s' % env['BOOST_APPEND']) + +cxxflags = [] if env['RUNTIME_LINK'] == 'static': cmd = 'gdal-config --dep-libs' plugin_env.ParseConfig(cmd) - plugin_env['LIBS'].append('proj') + libraries.append('proj') if env.get('BOOST_LIB_VERSION_FROM_HEADER'): boost_version_from_header = int(env['BOOST_LIB_VERSION_FROM_HEADER'].split('_')[1]) if boost_version_from_header < 46: # avoid ubuntu issue with boost interprocess: # https://github.com/mapnik/mapnik/issues/1082 - plugin_env.Append(CXXFLAGS = '-fpermissive') + cxxflags.Append('-fpermissive') -input_plugin = plugin_env.SharedLibrary('../ogr', source=ogr_src, SHLIBPREFIX='', SHLIBSUFFIX='.input', LINKFLAGS=env['CUSTOM_LDFLAGS']) +plugin_env.Append(CXXFLAGS=cxxflags) -# if the plugin links to libmapnik ensure it is built first -Depends(input_plugin, env.subst('../../../src/%s' % env['MAPNIK_LIB_NAME'])) +if env['PLUGIN_LINKING'] == 'shared': + libraries.append('mapnik') -if 'uninstall' not in COMMAND_LINE_TARGETS: - env.Install(env['MAPNIK_INPUT_PLUGINS_DEST'], input_plugin) - env.Alias('install', env['MAPNIK_INPUT_PLUGINS_DEST']) + TARGET = plugin_env.SharedLibrary('../%s' % PLUGIN_NAME, + SHLIBPREFIX='', + SHLIBSUFFIX='.input', + source=plugin_sources, + LIBS=libraries, + LINKFLAGS=env['CUSTOM_LDFLAGS']) + + # if the plugin links to libmapnik ensure it is built first + Depends(TARGET, env.subst('../../../src/%s' % env['MAPNIK_LIB_NAME'])) + + if 'uninstall' not in COMMAND_LINE_TARGETS: + env.Install(env['MAPNIK_INPUT_PLUGINS_DEST'], TARGET) + env.Alias('install', env['MAPNIK_INPUT_PLUGINS_DEST']) + +plugin_obj = { + 'CXXFLAGS': cxxflags, + 'LIBS': libraries, + 'SOURCES': plugin_sources, +} + +Return('plugin_obj') diff --git a/plugins/input/osm/build.py b/plugins/input/osm/build.py index 4cff88aea..f48a930d4 100644 --- a/plugins/input/osm/build.py +++ b/plugins/input/osm/build.py @@ -1,7 +1,7 @@ # # This file is part of Mapnik (c++ mapping toolkit) # -# Copyright (C) 2007 Artem Pavlenko, Jean-Francois Doyon +# Copyright (C) 2013 Artem Pavlenko # # Mapnik is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public @@ -17,38 +17,53 @@ # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # -# +# Import ('plugin_base') Import ('env') -prefix = env['PREFIX'] +PLUGIN_NAME = 'osm' plugin_env = plugin_base.Clone() -osm_src = Split( +plugin_sources = Split( """ + %(PLUGIN_NAME)s.cpp + %(PLUGIN_NAME)s_datasource.cpp + %(PLUGIN_NAME)s_featureset.cpp osmparser.cpp - osm.cpp - osm_datasource.cpp - osm_featureset.cpp dataset_deliverer.cpp basiccurl.cpp - """ - ) + """ % locals() +) +# Link Library to Dependencies libraries = [ 'xml2' ] libraries.append('curl') -libraries.append('mapnik') libraries.append(env['ICU_LIB_NAME']) libraries.append('boost_system%s' % env['BOOST_APPEND']) libraries.append('boost_filesystem%s' % env['BOOST_APPEND']) -input_plugin = plugin_env.SharedLibrary('../osm', source=osm_src, SHLIBPREFIX='', SHLIBSUFFIX='.input', LIBS=libraries, LINKFLAGS=env['CUSTOM_LDFLAGS']) +if env['PLUGIN_LINKING'] == 'shared': + libraries.append('mapnik') -# if the plugin links to libmapnik ensure it is built first -Depends(input_plugin, env.subst('../../../src/%s' % env['MAPNIK_LIB_NAME'])) + TARGET = plugin_env.SharedLibrary('../%s' % PLUGIN_NAME, + SHLIBPREFIX='', + SHLIBSUFFIX='.input', + source=plugin_sources, + LIBS=libraries, + LINKFLAGS=env['CUSTOM_LDFLAGS']) -if 'uninstall' not in COMMAND_LINE_TARGETS: - env.Install(env['MAPNIK_INPUT_PLUGINS_DEST'], input_plugin) - env.Alias('install', env['MAPNIK_INPUT_PLUGINS_DEST']) + # if the plugin links to libmapnik ensure it is built first + Depends(TARGET, env.subst('../../../src/%s' % env['MAPNIK_LIB_NAME'])) + + if 'uninstall' not in COMMAND_LINE_TARGETS: + env.Install(env['MAPNIK_INPUT_PLUGINS_DEST'], TARGET) + env.Alias('install', env['MAPNIK_INPUT_PLUGINS_DEST']) + +plugin_obj = { + 'LIBS': libraries, + 'SOURCES': plugin_sources, +} + +Return('plugin_obj') diff --git a/plugins/input/postgis/build.py b/plugins/input/postgis/build.py index 271de7caf..2d31a3dc6 100644 --- a/plugins/input/postgis/build.py +++ b/plugins/input/postgis/build.py @@ -1,7 +1,7 @@ # # This file is part of Mapnik (c++ mapping toolkit) # -# Copyright (C) 2006 Artem Pavlenko, Jean-Francois Doyon +# Copyright (C) 2013 Artem Pavlenko # # Mapnik is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public @@ -17,44 +17,57 @@ # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # -# +# Import ('plugin_base') Import ('env') -prefix = env['PREFIX'] +PLUGIN_NAME = 'postgis' plugin_env = plugin_base.Clone() -postgis_src = Split( +plugin_sources = Split( """ - postgis_datasource.cpp - postgis_featureset.cpp - """ - ) - -# clear out and rebuild libs -plugin_env['LIBS'] = ['pq'] + %(PLUGIN_NAME)s_datasource.cpp + %(PLUGIN_NAME)s_featureset.cpp + """ % locals() +) # Link Library to Dependencies -plugin_env['LIBS'].append('mapnik') -plugin_env['LIBS'].append('boost_system%s' % env['BOOST_APPEND']) -plugin_env['LIBS'].append(env['ICU_LIB_NAME']) +libraries = ['pq'] +libraries.append('boost_system%s' % env['BOOST_APPEND']) +libraries.append(env['ICU_LIB_NAME']) + if env['THREADING'] == 'multi': - plugin_env['LIBS'].append('boost_thread%s' % env['BOOST_APPEND']) + libraries.append('boost_thread%s' % env['BOOST_APPEND']) if env['RUNTIME_LINK'] == 'static': #cmd = 'pg_config --libs' #plugin_env.ParseConfig(cmd) # pg_config does not seem to report correct deps of libpq # so resort to hardcoding for now - plugin_env['LIBS'].extend(['ldap','pam','ssl','crypto','krb5']) + libraries.extend(['ldap', 'pam', 'ssl', 'crypto', 'krb5']) -input_plugin = plugin_env.SharedLibrary('../postgis', source=postgis_src, SHLIBPREFIX='', SHLIBSUFFIX='.input', LINKFLAGS=env['CUSTOM_LDFLAGS']) +if env['PLUGIN_LINKING'] == 'shared': + libraries.append('mapnik') -# if the plugin links to libmapnik ensure it is built first -Depends(input_plugin, env.subst('../../../src/%s' % env['MAPNIK_LIB_NAME'])) + TARGET = plugin_env.SharedLibrary('../%s' % PLUGIN_NAME, + SHLIBPREFIX='', + SHLIBSUFFIX='.input', + source=plugin_sources, + LIBS=libraries, + LINKFLAGS=env['CUSTOM_LDFLAGS']) -if 'uninstall' not in COMMAND_LINE_TARGETS: - env.Install(env['MAPNIK_INPUT_PLUGINS_DEST'], input_plugin) - env.Alias('install', env['MAPNIK_INPUT_PLUGINS_DEST']) + # if the plugin links to libmapnik ensure it is built first + Depends(TARGET, env.subst('../../../src/%s' % env['MAPNIK_LIB_NAME'])) + + if 'uninstall' not in COMMAND_LINE_TARGETS: + env.Install(env['MAPNIK_INPUT_PLUGINS_DEST'], TARGET) + env.Alias('install', env['MAPNIK_INPUT_PLUGINS_DEST']) + +plugin_obj = { + 'LIBS': libraries, + 'SOURCES': plugin_sources, +} + +Return('plugin_obj') diff --git a/plugins/input/python/build.py b/plugins/input/python/build.py index 78636adfc..bf5313eb4 100644 --- a/plugins/input/python/build.py +++ b/plugins/input/python/build.py @@ -1,13 +1,29 @@ -#!/usr/bin/env python +# +# This file is part of Mapnik (c++ mapping toolkit) +# +# Copyright (C) 2013 Artem Pavlenko +# +# Mapnik is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# +# import os - -PLUGIN_NAME = 'python' - Import ('plugin_base') Import ('env') -install_dest = env['MAPNIK_INPUT_PLUGINS_DEST'] +PLUGIN_NAME = 'python' plugin_env = plugin_base.Clone() @@ -17,26 +33,32 @@ plugin_sources = Split( %(PLUGIN_NAME)s_featureset.cpp %(PLUGIN_NAME)s_utils.cpp """ % locals() - ) +) -boost_system = 'boost_system%s' % env['BOOST_APPEND'] -libraries = ['mapnik',env['BOOST_PYTHON_LIB'],boost_system,env['ICU_LIB_NAME']] +# Link Library to Dependencies +libraries = [] +libraries.append('boost_system%s' % env['BOOST_APPEND']) +libraries.append(env['BOOST_PYTHON_LIB']) +libraries.append(env['ICU_LIB_NAME']) +python_cpppath = env['PYTHON_INCLUDES'] +allcpp_paths = env['CPPPATH'] +allcpp_paths.extend(python_cpppath) # NOTE: explicit linking to libpython is uneeded on most linux version if the # python plugin is used by a app in python using mapnik's python bindings # we explicitly link to libpython here so that this plugin # can be used from a pure C++ calling application or a different binding language if env['PLATFORM'] == 'Darwin' and env['FRAMEWORK_PYTHON']: - if env['FRAMEWORK_SEARCH_PATH']: - python_link_flag = '-F%s -framework Python -Z' % env['FRAMEWORK_SEARCH_PATH'] + if env['FRAMEWORK_SEARCH_PATH']: + python_link_flag = '-F%s -framework Python -Z' % env['FRAMEWORK_SEARCH_PATH'] + else: + link_prefix = env['PYTHON_SYS_PREFIX'] + if '.framework' in link_prefix: + python_link_flag = '-F%s -framework Python -Z' % os.path.dirname(link_prefix.split('.')[0]) + elif '/System' in link_prefix: + python_link_flag = '-F/System/Library/Frameworks/ -framework Python -Z' else: - link_prefix = env['PYTHON_SYS_PREFIX'] - if '.framework' in link_prefix: - python_link_flag = '-F%s -framework Python -Z' % os.path.dirname(link_prefix.split('.')[0]) - elif '/System' in link_prefix: - python_link_flag = '-F/System/Library/Frameworks/ -framework Python -Z' - else: - python_link_flag = '-F/ -framework Python' + python_link_flag = '-F/ -framework Python' else: # on linux the linkflags end up to early in the compile flags to work correctly python_link_flag = '-L%s' % env['PYTHON_SYS_PREFIX'] + os.path.sep + env['LIBDIR_SCHEMA'] @@ -48,33 +70,31 @@ if env['CUSTOM_LDFLAGS']: else: linkflags = python_link_flag -plugin_env.Append(CPPPATH = env['PYTHON_INCLUDES']) - -TARGET = plugin_env.SharedLibrary( - # the name of the target to build, eg 'sqlite.input' - '../%s' % PLUGIN_NAME, - # prefix - normally none used - SHLIBPREFIX='', - # extension, mapnik expects '.input' - SHLIBSUFFIX='.input', - # list of source files to compile - source=plugin_sources, - # libraries to link to - LIBS=libraries, - # any custom linkflags, eg. LDFLAGS - # in this case CUSTOM_LDFLAGS comes - # from Mapnik's main SConstruct file - # and can be removed here if you do - # not need it - LINKFLAGS=linkflags - ) +if env['PLUGIN_LINKING'] == 'shared': + libraries.append('mapnik') + TARGET = plugin_env.SharedLibrary('../%s' % PLUGIN_NAME, + SHLIBPREFIX='', + SHLIBSUFFIX='.input', + source=plugin_sources, + CPPPATH=allcpp_paths, + LIBS=libraries, + LINKFLAGS=linkflags) -# if the plugin links to libmapnik ensure it is built first -Depends(TARGET, env.subst('../../../src/%s' % env['MAPNIK_LIB_NAME'])) + # if the plugin links to libmapnik ensure it is built first + Depends(TARGET, env.subst('../../../src/%s' % env['MAPNIK_LIB_NAME'])) -# if 'uninstall' is not passed on the command line -# then we actually create the install targets that -# scons will install if 'install' is passed as an arg -if 'uninstall' not in COMMAND_LINE_TARGETS: - env.Install(install_dest, TARGET) - env.Alias('install', install_dest) + # if 'uninstall' is not passed on the command line + # then we actually create the install targets that + # scons will install if 'install' is passed as an arg + if 'uninstall' not in COMMAND_LINE_TARGETS: + env.Install(env['MAPNIK_INPUT_PLUGINS_DEST'], TARGET) + env.Alias('install', env['MAPNIK_INPUT_PLUGINS_DEST']) + +plugin_obj = { + 'LIBS': libraries, + 'SOURCES': plugin_sources, + 'CPPPATH': python_cpppath, + 'LINKFLAGS': linkflags.replace('-Z','').split(' '), +} + +Return('plugin_obj') diff --git a/plugins/input/raster/build.py b/plugins/input/raster/build.py index 2a3c7dd41..b16028f68 100644 --- a/plugins/input/raster/build.py +++ b/plugins/input/raster/build.py @@ -1,7 +1,7 @@ # # This file is part of Mapnik (c++ mapping toolkit) # -# Copyright (C) 2006 Artem Pavlenko, Jean-Francois Doyon +# Copyright (C) 2013 Artem Pavlenko # # Mapnik is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public @@ -17,35 +17,49 @@ # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # -# +# Import ('plugin_base') Import ('env') -prefix = env['PREFIX'] +PLUGIN_NAME = 'raster' plugin_env = plugin_base.Clone() -raster_src = Split( +plugin_sources = Split( """ - raster_datasource.cpp - raster_featureset.cpp - raster_info.cpp - """ - ) + %(PLUGIN_NAME)s_datasource.cpp + %(PLUGIN_NAME)s_featureset.cpp + %(PLUGIN_NAME)s_info.cpp + """ % locals() +) -libraries = [] # Link Library to Dependencies -libraries.append('mapnik') +libraries = [] libraries.append(env['ICU_LIB_NAME']) libraries.append('boost_system%s' % env['BOOST_APPEND']) libraries.append('boost_filesystem%s' % env['BOOST_APPEND']) -input_plugin = plugin_env.SharedLibrary('../raster', source=raster_src, SHLIBPREFIX='', SHLIBSUFFIX='.input', LIBS=libraries, LINKFLAGS=env['CUSTOM_LDFLAGS']) +if env['PLUGIN_LINKING'] == 'shared': + libraries.append('mapnik') -# if the plugin links to libmapnik ensure it is built first -Depends(input_plugin, env.subst('../../../src/%s' % env['MAPNIK_LIB_NAME'])) + TARGET = plugin_env.SharedLibrary('../%s' % PLUGIN_NAME, + SHLIBPREFIX='', + SHLIBSUFFIX='.input', + source=plugin_sources, + LIBS=libraries, + LINKFLAGS=env['CUSTOM_LDFLAGS']) -if 'uninstall' not in COMMAND_LINE_TARGETS: - env.Install(env['MAPNIK_INPUT_PLUGINS_DEST'], input_plugin) - env.Alias('install', env['MAPNIK_INPUT_PLUGINS_DEST']) + # if the plugin links to libmapnik ensure it is built first + Depends(TARGET, env.subst('../../../src/%s' % env['MAPNIK_LIB_NAME'])) + + if 'uninstall' not in COMMAND_LINE_TARGETS: + env.Install(env['MAPNIK_INPUT_PLUGINS_DEST'], TARGET) + env.Alias('install', env['MAPNIK_INPUT_PLUGINS_DEST']) + +plugin_obj = { + 'LIBS': libraries, + 'SOURCES': plugin_sources, +} + +Return('plugin_obj') diff --git a/plugins/input/rasterlite/build.py b/plugins/input/rasterlite/build.py index cee50da27..b3e6a834b 100644 --- a/plugins/input/rasterlite/build.py +++ b/plugins/input/rasterlite/build.py @@ -1,7 +1,7 @@ # # This file is part of Mapnik (c++ mapping toolkit) # -# Copyright (C) 2007 Artem Pavlenko, Jean-Francois Doyon +# Copyright (C) 2013 Artem Pavlenko # # Mapnik is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public @@ -17,35 +17,48 @@ # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # -# +# Import ('plugin_base') Import ('env') -prefix = env['PREFIX'] +PLUGIN_NAME = 'rasterlite' plugin_env = plugin_base.Clone() -rasterlite_src = Split( +plugin_sources = Split( """ - rasterlite_datasource.cpp - rasterlite_featureset.cpp - """ - ) - -libraries = [env['PLUGINS']['rasterlite']['lib']] + %(PLUGIN_NAME)s_datasource.cpp + %(PLUGIN_NAME)s_featureset.cpp + """ % locals() +) # Link Library to Dependencies -libraries.append('mapnik') +libraries = [env['PLUGINS']['rasterlite']['lib']] libraries.append(env['ICU_LIB_NAME']) libraries.append('boost_system%s' % env['BOOST_APPEND']) libraries.append('boost_filesystem%s' % env['BOOST_APPEND']) -input_plugin = plugin_env.SharedLibrary('../rasterlite', source=rasterlite_src, SHLIBPREFIX='', SHLIBSUFFIX='.input', LIBS=libraries, LINKFLAGS=env['CUSTOM_LDFLAGS']) +if env['PLUGIN_LINKING'] == 'shared': + libraries.append('mapnik') -# if the plugin links to libmapnik ensure it is built first -Depends(input_plugin, env.subst('../../../src/%s' % env['MAPNIK_LIB_NAME'])) + TARGET = plugin_env.SharedLibrary('../%s' % PLUGIN_NAME, + SHLIBPREFIX='', + SHLIBSUFFIX='.input', + source=plugin_sources, + LIBS=libraries, + LINKFLAGS=env['CUSTOM_LDFLAGS']) -if 'uninstall' not in COMMAND_LINE_TARGETS: - env.Install(env['MAPNIK_INPUT_PLUGINS_DEST'], input_plugin) - env.Alias('install', env['MAPNIK_INPUT_PLUGINS_DEST']) + # if the plugin links to libmapnik ensure it is built first + Depends(TARGET, env.subst('../../../src/%s' % env['MAPNIK_LIB_NAME'])) + + if 'uninstall' not in COMMAND_LINE_TARGETS: + env.Install(env['MAPNIK_INPUT_PLUGINS_DEST'], TARGET) + env.Alias('install', env['MAPNIK_INPUT_PLUGINS_DEST']) + +plugin_obj = { + 'LIBS': libraries, + 'SOURCES': plugin_sources, +} + +Return('plugin_obj') diff --git a/plugins/input/shape/build.py b/plugins/input/shape/build.py index 5dd9995ac..d837b7fc8 100644 --- a/plugins/input/shape/build.py +++ b/plugins/input/shape/build.py @@ -1,7 +1,7 @@ - +# # This file is part of Mapnik (c++ mapping toolkit) # -# Copyright (C) 2006 Artem Pavlenko, Jean-Francois Doyon +# Copyright (C) 2013 Artem Pavlenko # # Mapnik is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public @@ -17,50 +17,70 @@ # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # -# - +# Import ('plugin_base') Import ('env') -prefix = env['PREFIX'] +PLUGIN_NAME = 'shape' plugin_env = plugin_base.Clone() -shape_src = Split( +plugin_sources = Split( """ - dbfile.cpp - shape_datasource.cpp - shape_featureset.cpp - shape_index_featureset.cpp - shape_io.cpp - shape_utils.cpp - """ - ) - -libraries = [] + %(PLUGIN_NAME)s_datasource.cpp + %(PLUGIN_NAME)s_featureset.cpp + %(PLUGIN_NAME)s_index_featureset.cpp + %(PLUGIN_NAME)s_io.cpp + %(PLUGIN_NAME)s_utils.cpp + dbfile.cpp + """ % locals() +) # Link Library to Dependencies -libraries.append('mapnik') +libraries = [] libraries.append(env['ICU_LIB_NAME']) libraries.append('boost_system%s' % env['BOOST_APPEND']) libraries.append('boost_filesystem%s' % env['BOOST_APPEND']) +cppdefines = [] +cxxflags = [] + if env['SHAPE_MEMORY_MAPPED_FILE']: - plugin_env.Append(CPPDEFINES = '-DSHAPE_MEMORY_MAPPED_FILE') + cppdefines.append('-DSHAPE_MEMORY_MAPPED_FILE') if env.get('BOOST_LIB_VERSION_FROM_HEADER'): boost_version_from_header = int(env['BOOST_LIB_VERSION_FROM_HEADER'].split('_')[1]) if boost_version_from_header < 46: # avoid ubuntu issue with boost interprocess: # https://github.com/mapnik/mapnik/issues/1082 - plugin_env.Append(CXXFLAGS = '-fpermissive') + cxxflags.append('-fpermissive') -input_plugin = plugin_env.SharedLibrary('../shape', SHLIBSUFFIX='.input', source=shape_src, SHLIBPREFIX='', LIBS = libraries, LINKFLAGS=env['CUSTOM_LDFLAGS']) +plugin_env.Append(CXXFLAGS=cxxflags) +plugin_env.Append(CPPDEFINES=cppdefines) -# if the plugin links to libmapnik ensure it is built first -Depends(input_plugin, env.subst('../../../src/%s' % env['MAPNIK_LIB_NAME'])) +if env['PLUGIN_LINKING'] == 'shared': + libraries.append('mapnik') -if 'uninstall' not in COMMAND_LINE_TARGETS: - env.Install(env['MAPNIK_INPUT_PLUGINS_DEST'], input_plugin) - env.Alias('install', env['MAPNIK_INPUT_PLUGINS_DEST']) + TARGET = plugin_env.SharedLibrary('../shape', + SHLIBSUFFIX='.input', + SHLIBPREFIX='', + source=plugin_sources, + LIBS=libraries, + LINKFLAGS=env['CUSTOM_LDFLAGS']) + + # if the plugin links to libmapnik ensure it is built first + Depends(TARGET, env.subst('../../../src/%s' % env['MAPNIK_LIB_NAME'])) + + if 'uninstall' not in COMMAND_LINE_TARGETS: + env.Install(env['MAPNIK_INPUT_PLUGINS_DEST'], TARGET) + env.Alias('install', env['MAPNIK_INPUT_PLUGINS_DEST']) + +plugin_obj = { + 'LIBS': libraries, + 'SOURCES': plugin_sources, + 'CXXFLAGS': cxxflags, + 'CPPDEFINES': cppdefines, +} + +Return('plugin_obj') diff --git a/plugins/input/sqlite/build.py b/plugins/input/sqlite/build.py index 458a885ad..e6de86d2c 100644 --- a/plugins/input/sqlite/build.py +++ b/plugins/input/sqlite/build.py @@ -1,7 +1,7 @@ # # This file is part of Mapnik (c++ mapping toolkit) # -# Copyright (C) 2007 Artem Pavlenko, Jean-Francois Doyon +# Copyright (C) 2013 Artem Pavlenko # # Mapnik is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public @@ -17,39 +17,54 @@ # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # -# +# Import ('plugin_base') Import ('env') -prefix = env['PREFIX'] +PLUGIN_NAME = 'sqlite' plugin_env = plugin_base.Clone() -sqlite_src = Split( +plugin_sources = Split( """ - sqlite_datasource.cpp - sqlite_featureset.cpp - """ - ) - -libraries = [ 'sqlite3' ] + %(PLUGIN_NAME)s_datasource.cpp + %(PLUGIN_NAME)s_featureset.cpp + """ % locals() +) # Link Library to Dependencies -libraries.append('mapnik') +libraries = [ 'sqlite3' ] libraries.append(env['ICU_LIB_NAME']) libraries.append('boost_system%s' % env['BOOST_APPEND']) libraries.append('boost_filesystem%s' % env['BOOST_APPEND']) -linkflags = env['CUSTOM_LDFLAGS'] +linkflags = [] if env['SQLITE_LINKFLAGS']: linkflags.append(env['SQLITE_LINKFLAGS']) -input_plugin = plugin_env.SharedLibrary('../sqlite', source=sqlite_src, SHLIBPREFIX='', SHLIBSUFFIX='.input', LIBS=libraries, LINKFLAGS=linkflags) +if env['PLUGIN_LINKING'] == 'shared': + libraries.append('mapnik') + linkflags.append(env['CUSTOM_LDFLAGS']) -# if the plugin links to libmapnik ensure it is built first -Depends(input_plugin, env.subst('../../../src/%s' % env['MAPNIK_LIB_NAME'])) + TARGET = plugin_env.SharedLibrary('../%s' % PLUGIN_NAME, + SHLIBPREFIX='', + SHLIBSUFFIX='.input', + source=plugin_sources, + LIBS=libraries, + LINKFLAGS=linkflags) -if 'uninstall' not in COMMAND_LINE_TARGETS: - env.Install(env['MAPNIK_INPUT_PLUGINS_DEST'], input_plugin) - env.Alias('install', env['MAPNIK_INPUT_PLUGINS_DEST']) + # if the plugin links to libmapnik ensure it is built first + Depends(TARGET, env.subst('../../../src/%s' % env['MAPNIK_LIB_NAME'])) + + if 'uninstall' not in COMMAND_LINE_TARGETS: + env.Install(env['MAPNIK_INPUT_PLUGINS_DEST'], TARGET) + env.Alias('install', env['MAPNIK_INPUT_PLUGINS_DEST']) + +plugin_obj = { + 'LIBS': libraries, + 'SOURCES': plugin_sources, + 'LINKFLAGS': linkflags, +} + +Return('plugin_obj') diff --git a/plugins/input/templates/helloworld/build.py b/plugins/input/templates/helloworld/build.py index 5a974dd4b..d90efa26e 100644 --- a/plugins/input/templates/helloworld/build.py +++ b/plugins/input/templates/helloworld/build.py @@ -11,21 +11,17 @@ import os -# Give this plugin a name -# here this happens to be the same as the directory -PLUGIN_NAME = 'hello' - # Here we pull from the SCons environment exported from the main instance Import ('plugin_base') Import ('env') +# Give this plugin a name +# here this happens to be the same as the directory +PLUGIN_NAME = 'hello' + # the below install details are also pulled from the # main SConstruct file where configuration happens -# plugins can go anywhere, and be registered in custom locations by Mapnik -# but the standard location is '/usr/local/lib/mapnik/input' -install_dest = env['MAPNIK_INPUT_PLUGINS_DEST'] - # clone the environment here # so that if we modify the env it in this file # those changes to not pollute other builds later on... @@ -35,7 +31,7 @@ plugin_env = plugin_base.Clone() plugin_sources = Split( """ %(PLUGIN_NAME)s_datasource.cpp - %(PLUGIN_NAME)s_featureset.cpp + %(PLUGIN_NAME)s_featureset.cpp """ % locals() ) @@ -43,37 +39,54 @@ plugin_sources = Split( # directly link to libraries = [ '' ] # eg 'libfoo' -libraries.append('mapnik') libraries.append('boost_system%s' % env['BOOST_APPEND']) # link libicuuc, but ICU_LIB_NAME is used custom builds of icu can # have different library names like osx which offers /usr/lib/libicucore.dylib libraries.append(env['ICU_LIB_NAME']) - -TARGET = plugin_env.SharedLibrary( - # the name of the target to build, eg 'sqlite.input' - '../%s' % PLUGIN_NAME, - # prefix - normally none used - SHLIBPREFIX='', - # extension, mapnik expects '.input' - SHLIBSUFFIX='.input', - # list of source files to compile - source=plugin_sources, - # libraries to link to - LIBS=libraries, - # any custom linkflags, eg. LDFLAGS - # in this case CUSTOM_LDFLAGS comes - # from Mapnik's main SConstruct file - # and can be removed here if you do - # not need it - LINKFLAGS=env.get('CUSTOM_LDFLAGS') - ) -# if the plugin links to libmapnik ensure it is built first -Depends(TARGET, env.subst('../../../../src/%s' % env['MAPNIK_LIB_NAME'])) +# this is valid if we are building an external plugin as shared library +if env['PLUGIN_LINKING'] == 'shared': + # plugins can go anywhere, and be registered in custom locations by Mapnik + # but the standard location is '/usr/local/lib/mapnik/input' + install_dest = env['MAPNIK_INPUT_PLUGINS_DEST'] -# if 'uninstall' is not passed on the command line -# then we actually create the install targets that -# scons will install if 'install' is passed as an arg -if 'uninstall' not in COMMAND_LINE_TARGETS: - env.Install(install_dest, TARGET) - env.Alias('install', install_dest) + # only link mapnik if we are build an external shared object + libraries.append('mapnik') + + TARGET = plugin_env.SharedLibrary( + # the name of the target to build, eg 'sqlite.input' + '../%s' % PLUGIN_NAME, + # prefix - normally none used + SHLIBPREFIX='', + # extension, mapnik expects '.input' + SHLIBSUFFIX='.input', + # list of source files to compile + source=plugin_sources, + # libraries to link to + LIBS=libraries, + # any custom linkflags, eg. LDFLAGS + # in this case CUSTOM_LDFLAGS comes + # from Mapnik's main SConstruct file + # and can be removed here if you do + # not need it + LINKFLAGS=env.get('CUSTOM_LDFLAGS') + ) + + # if the plugin links to libmapnik ensure it is built first + Depends(TARGET, env.subst('../../../../src/%s' % env['MAPNIK_LIB_NAME'])) + + # if 'uninstall' is not passed on the command line + # then we actually create the install targets that + # scons will install if 'install' is passed as an arg + if 'uninstall' not in COMMAND_LINE_TARGETS: + env.Install(install_dest, TARGET) + env.Alias('install', install_dest) + +# Return the plugin building options to scons +# This is used when statically linking the plugin with mapnik) +plugin_obj = { + 'LIBS': libraries, + 'SOURCES': plugin_sources, +} + +Return('plugin_obj') diff --git a/src/build.py b/src/build.py index e6b9b9b8f..ecaa0f0d9 100644 --- a/src/build.py +++ b/src/build.py @@ -81,7 +81,6 @@ lib_env['LIBS'].append('xml2') if env['THREADING'] == 'multi': lib_env['LIBS'].append('boost_thread%s' % env['BOOST_APPEND']) - if env['RUNTIME_LINK'] == 'static': if 'icuuc' in env['ICU_LIB_NAME']: lib_env['LIBS'].append('icudata') @@ -124,6 +123,7 @@ source = Split( box2d.cpp building_symbolizer.cpp datasource_cache.cpp + datasource_cache_static.cpp debug.cpp deepcopy.cpp expression_node.cpp @@ -207,9 +207,31 @@ source = Split( """ ) +if env['PLUGIN_LINKING'] == 'static': + lib_env.Append(CPPDEFINES = '-DMAPNIK_STATIC_PLUGINS') + for plugin in env['REQUESTED_PLUGINS']: + details = env['PLUGINS'][plugin] + if details['lib'] in env['LIBS'] or not details['lib']: + lib_env.Append(CPPDEFINES = '-DMAPNIK_STATIC_PLUGIN_%s' % plugin.upper()) + plugin_env = SConscript('../plugins/input/%s/build.py' % plugin) + if plugin_env.has_key('SOURCES') and plugin_env['SOURCES']: + source += ['../plugins/input/%s/%s' % (plugin, src) for src in plugin_env['SOURCES']] + if plugin_env.has_key('CPPDEFINES') and plugin_env['CPPDEFINES']: + lib_env.AppendUnique(CPPDEFINES=plugin_env['CPPDEFINES']) + if plugin_env.has_key('CXXFLAGS') and plugin_env['CXXFLAGS']: + lib_env.AppendUnique(CXXFLAGS=plugin_env['CXXFLAGS']) + if plugin_env.has_key('LINKFLAGS') and plugin_env['LINKFLAGS']: + lib_env.AppendUnique(LINKFLAGS=plugin_env['LINKFLAGS']) + if plugin_env.has_key('CPPPATH') and plugin_env['CPPPATH']: + lib_env.AppendUnique(CPPPATH=copy(plugin_env['CPPPATH'])) + if plugin_env.has_key('LIBS') and plugin_env['LIBS']: + lib_env.AppendUnique(LIBS=plugin_env['LIBS']) + else: + print("Notice: dependencies not met for plugin '%s', not building..." % plugin) + if env['HAS_CAIRO']: lib_env.AppendUnique(LIBPATH=env['CAIRO_LIBPATHS']) - lib_env.Append(LIBS=env['CAIRO_LINKFLAGS']) + lib_env.Append(LIBS=env['CAIRO_ALL_LIBS']) lib_env.Append(CPPDEFINES = '-DHAVE_CAIRO') libmapnik_defines.append('-DHAVE_CAIRO') lib_env.AppendUnique(CPPPATH=copy(env['CAIRO_CPPPATHS'])) @@ -350,13 +372,17 @@ if env['RENDERING_STATS']: else: source.insert(0,processor_cpp); +# clone the env one more time to isolate mapnik_lib_link_flag +lib_env_final = lib_env.Clone() + if env['CUSTOM_LDFLAGS']: - linkflags = '%s %s' % (env['CUSTOM_LDFLAGS'], mapnik_lib_link_flag) + lib_env_final.Prepend(LINKFLAGS='%s %s' % (env['CUSTOM_LDFLAGS'], mapnik_lib_link_flag)) else: - linkflags = mapnik_lib_link_flag + lib_env_final.Prepend(LINKFLAGS=mapnik_lib_link_flag) # cache library values for other builds to use env['LIBMAPNIK_LIBS'] = copy(lib_env['LIBS']) +env['LIBMAPNIK_LINKFLAGS'] = copy(lib_env['LINKFLAGS']) env['LIBMAPNIK_CXXFLAGS'] = libmapnik_cxxflags env['LIBMAPNIK_DEFINES'] = libmapnik_defines @@ -366,9 +392,9 @@ if env['PLATFORM'] == 'Darwin': target_path = env['MAPNIK_LIB_BASE_DEST'] if 'uninstall' not in COMMAND_LINE_TARGETS: if env['LINKING'] == 'static': - mapnik = lib_env.StaticLibrary('mapnik', source, LINKFLAGS=linkflags) + mapnik = lib_env_final.StaticLibrary('mapnik', source) else: - mapnik = lib_env.SharedLibrary('mapnik', source, LINKFLAGS=linkflags) + mapnik = lib_env_final.SharedLibrary('mapnik', source) result = env.Install(target_path, mapnik) env.Alias(target='install', source=result) @@ -390,15 +416,14 @@ else: if 'uninstall' not in COMMAND_LINE_TARGETS: if env['LINKING'] == 'static': - mapnik = lib_env.StaticLibrary('mapnik', source, LINKFLAGS=linkflags) + mapnik = lib_env_final.StaticLibrary('mapnik', source) else: - mapnik = lib_env.SharedLibrary('mapnik', source, LINKFLAGS=linkflags) + mapnik = lib_env_final.SharedLibrary('mapnik', source) result = env.InstallAs(target=target, source=mapnik) env.Alias(target='install', source=result) if result: env.AddPostAction(result, ldconfig) - # Install symlinks target1 = os.path.join(env['MAPNIK_LIB_BASE_DEST'], "%s.%d.%d" % \ (os.path.basename(env.subst(env['MAPNIK_LIB_NAME'])),int(major), int(minor))) diff --git a/src/datasource_cache.cpp b/src/datasource_cache.cpp index 70e0f4636..e303d7d6e 100644 --- a/src/datasource_cache.cpp +++ b/src/datasource_cache.cpp @@ -38,6 +38,9 @@ namespace mapnik { +extern datasource_ptr create_static_datasource(parameters const& params); +extern std::vector get_static_datasource_names(); + bool is_input_plugin(std::string const& filename) { return boost::algorithm::ends_with(filename,std::string(".input")); @@ -62,13 +65,23 @@ datasource_ptr datasource_cache::create(parameters const& params) "parameter 'type' is missing"); } + datasource_ptr ds; + +#ifdef MAPNIK_STATIC_PLUGINS + // return if it's created, raise otherwise + ds = create_static_datasource(params); + if (ds) + { + return ds; + } +#endif + #ifdef MAPNIK_THREADSAFE mutex::scoped_lock lock(mutex_); #endif - datasource_ptr ds; std::map >::iterator itr=plugins_.find(*type); - if ( itr == plugins_.end() ) + if (itr == plugins_.end()) { std::string s("Could not create datasource for type: '"); s += *type + "'"; @@ -83,7 +96,7 @@ datasource_ptr datasource_cache::create(parameters const& params) throw config_error(s); } - if (!itr->second->valid()) + if (! itr->second->valid()) { throw std::runtime_error(std::string("Cannot load library: ") + itr->second->get_error()); @@ -95,13 +108,19 @@ datasource_ptr datasource_cache::create(parameters const& params) #endif create_ds* create_datasource = reinterpret_cast(itr->second->get_symbol("create")); - if (!create_datasource) + if (! create_datasource) { throw std::runtime_error(std::string("Cannot load symbols: ") + itr->second->get_error()); } + ds = datasource_ptr(create_datasource(params), datasource_deleter()); + #ifdef MAPNIK_LOG + MAPNIK_LOG_DEBUG(datasource_cache) + << "datasource_cache: Datasource=" + << ds << " type=" << type; + MAPNIK_LOG_DEBUG(datasource_cache) << "datasource_cache: Size=" << params.size(); @@ -115,12 +134,6 @@ datasource_ptr datasource_cache::create(parameters const& params) } #endif - ds = datasource_ptr(create_datasource(params), datasource_deleter()); - - MAPNIK_LOG_DEBUG(datasource_cache) - << "datasource_cache: Datasource=" - << ds << " type=" << type; - return ds; } @@ -132,11 +145,17 @@ std::string datasource_cache::plugin_directories() std::vector datasource_cache::plugin_names() { std::vector names; + +#ifdef MAPNIK_STATIC_PLUGINS + names = get_static_datasource_names(); +#endif + std::map >::const_iterator itr; - for (itr = plugins_.begin();itr!=plugins_.end();++itr) + for (itr = plugins_.begin(); itr != plugins_.end(); ++itr) { names.push_back(itr->first); } + return names; } @@ -145,6 +164,7 @@ void datasource_cache::register_datasources(std::string const& str) #ifdef MAPNIK_THREADSAFE mutex::scoped_lock lock(mutex_); #endif + boost::filesystem::path path(str); // TODO - only push unique paths plugin_directories_.push_back(str); @@ -152,24 +172,24 @@ void datasource_cache::register_datasources(std::string const& str) if (exists(path) && is_directory(path)) { - for (boost::filesystem::directory_iterator itr(path);itr!=end_itr;++itr ) + for (boost::filesystem::directory_iterator itr(path); itr != end_itr; ++itr ) { #if (BOOST_FILESYSTEM_VERSION == 3) - if (!is_directory( *itr ) && is_input_plugin(itr->path().filename().string())) + if (! is_directory(*itr) && is_input_plugin(itr->path().filename().string())) #else // v2 - if (!is_directory( *itr ) && is_input_plugin(itr->path().leaf())) + if (! is_directory(*itr) && is_input_plugin(itr->path().leaf())) +#endif + { +#if (BOOST_FILESYSTEM_VERSION == 3) + if (register_datasource(itr->path().string())) +#else // v2 + if (register_datasource(itr->string())) #endif { -#if (BOOST_FILESYSTEM_VERSION == 3) - if (register_datasource(itr->path().string())) -#else // v2 - if (register_datasource(itr->string())) -#endif - { - registered_ = true; - } + registered_ = true; } + } } } } @@ -206,9 +226,9 @@ bool datasource_cache::register_datasource(std::string const& filename) } catch (std::exception const& ex) { - MAPNIK_LOG_ERROR(datasource_cache) - << "Exception caught while loading plugin library: " - << filename << " (" << ex.what() << ")"; + MAPNIK_LOG_ERROR(datasource_cache) + << "Exception caught while loading plugin library: " + << filename << " (" << ex.what() << ")"; } return success; } diff --git a/utils/mapnik-config/build.py b/utils/mapnik-config/build.py index deef156a7..6b94f3c37 100644 --- a/utils/mapnik-config/build.py +++ b/utils/mapnik-config/build.py @@ -52,6 +52,7 @@ if config_env['HAS_CAIRO']: dep_includes += ''.join([' -I%s' % i for i in env['CAIRO_CPPPATHS'] if not i.startswith('#')]) ldflags = config_env['CUSTOM_LDFLAGS'] + ''.join([' -L%s' % i for i in config_env['LIBPATH'] if not i.startswith('#')]) +ldflags += config_env['LIBMAPNIK_LINKFLAGS'] dep_libs = ''.join([' -l%s' % i for i in env['LIBMAPNIK_LIBS']])