From 2b60d6d425869d7f542c111ff185a651f39be8db Mon Sep 17 00:00:00 2001 From: Artem Pavlenko Date: Mon, 21 Jan 2008 20:15:07 +0000 Subject: [PATCH] applied patch to build on OSX Leopard and Sun's C++ compiler on Solaris from Justin Bronn --- SConstruct | 109 ++++++++++++------ agg/SConscript | 5 +- .../detail/ptree_implementation.hpp | 5 + include/mapnik/enumeration.hpp | 4 +- include/mapnik/gamma.hpp | 5 + include/mapnik/geom_util.hpp | 6 + include/mapnik/global.hpp | 4 + include/mapnik/image_data.hpp | 6 + include/mapnik/utils.hpp | 16 ++- scons/scons-local-0.97/SCons/Tool/sunc++.py | 11 +- src/SConscript | 2 + src/distance.cpp | 9 ++ src/envelope.cpp | 105 +++++++++++++---- src/unicode.cpp | 2 +- 14 files changed, 220 insertions(+), 69 deletions(-) diff --git a/SConstruct b/SConstruct index 842c15317..6f441e134 100644 --- a/SConstruct +++ b/SConstruct @@ -27,7 +27,12 @@ if platform.uname()[4] == 'x86_64': else: LIBDIR_SCHEMA='lib' +#### SCons build options and initial setup #### + +# All of the following options may be modified at the command-line, for example: +# `python scons/scons PREFIX=/opt` opts = Options('config.py') +opts.Add('CXX', 'The C++ compiler to use (defaults to g++).', 'g++') opts.Add('PREFIX', 'The install path "prefix"', '/usr/local') opts.Add(PathOption('BOOST_INCLUDES', 'Search path for boost include files', '/usr/include')) opts.Add(PathOption('BOOST_LIBS', 'Search path for boost library files', '/usr/' + LIBDIR_SCHEMA)) @@ -73,29 +78,44 @@ Help(opts.GenerateHelpText(env)) conf = Configure(env) +#### Libraries and headers dependency checks #### + +# Helper function for uniquely appending paths to a SCons path listing. +def uniq_add(env, key, val): + if not val in env[key]: env[key].append(val) + # Libraries and headers dependency checks - env['CPPPATH'] = ['#agg/include', '#tinyxml', '#include', '#'] - -for path in [env['BOOST_INCLUDES'], - env['PNG_INCLUDES'], - env['JPEG_INCLUDES'], - env['TIFF_INCLUDES'], - env['PGSQL_INCLUDES'], - env['PROJ_INCLUDES'], - env['GDAL_INCLUDES']] : - if path not in env['CPPPATH']: env['CPPPATH'].append(path) - env['LIBPATH'] = ['#agg', '#src'] -for path in [env['BOOST_LIBS'], - env['PNG_LIBS'], - env['JPEG_LIBS'], - env['TIFF_LIBS'], - env['PGSQL_LIBS'], - env['PROJ_LIBS'], - env['GDAL_LIBS']]: - if path not in env['LIBPATH']: env['LIBPATH'].append(path) +# Solaris & Sun Studio settings (the `SUNCC` flag will only be +# set if the `CXX` option begins with `CC`) +SOLARIS = env['PLATFORM'] == 'SunOS' +SUNCC = SOLARIS and env['CXX'].startswith('CC') + +# For Solaris include paths (e.g., for freetype2, ltdl, etc.). +if SOLARIS: + blastwave_dir = '/opt/csw/%s' + uniq_add(env, 'CPPPATH', blastwave_dir % 'include') + uniq_add(env, 'LIBPATH', blastwave_dir % LIBDIR_SCHEMA) + +# If the Sun Studio C++ compiler (`CC`) is used instead of GCC. +if SUNCC: + env['CC'] = 'cc' + # To be compatible w/Boost everything needs to be compiled + # with the `-library=stlport4` flag (which needs to come + # before the `-o` flag). + env['CXX'] = 'CC -library=stlport4' + if env['THREADING'] == 'multi': + env['CXXFLAGS'] = ['-mt'] + +# Adding the prerequisite library directories to the include path for +# compiling and the library path for linking, respectively. +for prereq in ('BOOST', 'PNG', 'JPEG', 'TIFF', 'PROJ', 'GDAL',): + inc_path = env['%s_INCLUDES' % prereq] + lib_path = env['%s_LIBS' % prereq] + uniq_add(env, 'CPPPATH', inc_path) + uniq_add(env, 'LIBPATH', lib_path) env.ParseConfig(env['FREETYPE_CONFIG'] + ' --libs --cflags') @@ -121,6 +141,7 @@ C_LIBSHEADERS = [ ['z', 'zlib.h', True], ['jpeg', ['stdio.h', 'jpeglib.h'], True], ['proj', 'proj_api.h', True], + ['iconv', 'iconv.h', True], ['pq', 'libpq-fe.h', False] ] @@ -168,23 +189,20 @@ inputplugins = [ driver.strip() for driver in Split(env['INPUT_PLUGINS'])] bindings = [ binding.strip() for binding in Split(env['BINDINGS'])] +#### Build instructions & settings #### # Build agg first, doesn't need anything special - SConscript('agg/SConscript') # Build the core library - SConscript('src/SConscript') # Build shapeindex and remove its dependency from the LIBS - if 'boost_program_options%s-mt' % env['BOOST_APPEND'] in env['LIBS']: SConscript('utils/shapeindex/SConscript') env['LIBS'].remove('boost_program_options%s-mt' % env['BOOST_APPEND']) # Build the input plug-ins - if 'postgis' in inputplugins and 'pq' in env['LIBS']: SConscript('plugins/input/postgis/SConscript') env['LIBS'].remove('pq') @@ -201,8 +219,7 @@ if 'gdal' in inputplugins and 'gdal' in env['LIBS']: if 'gigabase' in inputplugins and 'gigabase_r' in env['LIBS']: SConscript('plugins/input/gigabase/SConscript') -# Check out the Python situation - +# Build the Python bindings. if 'python' in env['BINDINGS']: if not os.access(env['PYTHON'], os.X_OK): color_print(1,"Cannot run python interpreter at '%s', make sure that you have the permissions to execute it." % env['PYTHON']) @@ -222,22 +239,44 @@ if 'python' in env['BINDINGS']: color_print(4,'Python %s prefix... %s' % (env['PYTHON_VERSION'], env['PYTHON_PREFIX'])) SConscript('bindings/python/SConscript') - env = conf.Finish() -# Setup the c++ args for our own codebase -if env['PLATFORM'] == 'Darwin': pthread = '' -else: pthread = '-pthread' +# Common C++ flags. +common_cxx_flags = '-D%s -DBOOST_SPIRIT_THREADSAFE ' % env['PLATFORM'].upper() -common_cxx_flags = '-ansi -Wall %s -ftemplate-depth-100 -D%s -DBOOST_SPIRIT_THREADSAFE ' % (pthread, env['PLATFORM'].upper()); - -if env['DEBUG']: - env.Append(CXXFLAGS = common_cxx_flags + '-O0 -fno-inline -g -DDEBUG -DMAPNIK_DEBUG') +# Mac OSX (Darwin) special settings +if env['PLATFORM'] == 'Darwin': + pthread = '' + # Getting the macintosh version number, sticking as a compiler macro + # for Leopard -- needed because different workarounds are needed than + # for Tiger. + if platform.mac_ver()[0].startswith('10.5'): + common_cxx_flags += '-DOSX_LEOPARD ' else: - env.Append(CXXFLAGS = common_cxx_flags + '-O2 -finline-functions -Wno-inline -DNDEBUG') + pthread = '-pthread' + +# Common debugging flags. +debug_flags = '-g -DDEBUG -DMAPNIK_DEBUG' +ndebug_flags = '-DNDEBUG' + +# Customizing the C++ compiler flags depending on: +# (1) the C++ compiler used; and +# (2) whether debug binaries are requested. +if SUNCC: + if env['DEBUG']: + env.Append(CXXFLAGS = common_cxx_flags + debug_flags) + else: + env.Append(CXXFLAGS = common_cxx_flags + '-O %s' % ndebug_flags) +else: + # Common flags for GCC. + gcc_cxx_flags = '-ansi -Wall %s -ftemplate-depth-100 %s' % (pthread, common_cxx_flags) + + if env['DEBUG']: + env.Append(CXXFLAGS = gcc_cxx_flags + '-O0 -fno-inline %s' % debug_flags) + else: + env.Append(CXXFLAGS = gcc_cxx_flags + '-O2 -finline-functions -Wno-inline %s' % ndebug_flags) -# Install some free default fonts SConscript('fonts/SConscript') diff --git a/agg/SConscript b/agg/SConscript index 2dd1d3197..5c3a1a848 100644 --- a/agg/SConscript +++ b/agg/SConscript @@ -21,4 +21,7 @@ import glob Import('env') -env.StaticLibrary('agg', glob.glob('./src/' + '*.cpp'), LIBS=[], CPPPATH='./include', CXXFLAGS='-O3 -fPIC -DNDEBUG') +if env['PLATFORM'] == 'SunOS': + env.StaticLibrary('agg', glob.glob('./src/' + '*.cpp'), LIBS=[], CPPPATH='./include', CXXFLAGS='-O -KPIC -DNDEBUG') +else: + env.StaticLibrary('agg', glob.glob('./src/' + '*.cpp'), LIBS=[], CPPPATH='./include', CXXFLAGS='-O3 -fPIC -DNDEBUG') diff --git a/boost/property_tree/detail/ptree_implementation.hpp b/boost/property_tree/detail/ptree_implementation.hpp index 0b348df26..e938b75af 100644 --- a/boost/property_tree/detail/ptree_implementation.hpp +++ b/boost/property_tree/detail/ptree_implementation.hpp @@ -906,7 +906,12 @@ namespace boost { namespace property_tree // Make sure that no pointer other than char_type * is allowed BOOST_STATIC_ASSERT((is_pointer::value == false || is_same::type>::type>::value == true)); +#ifdef __SUNPRO_CC + // For the Sun Studio compiler the declaration needs to be within a statement. + if (typename traits_type::template inserter()(m_impl->m_data, value, loc)){} +#else typename traits_type::template inserter()(m_impl->m_data, value, loc); +#endif } // Put value in data of child ptree (custom path separator) diff --git a/include/mapnik/enumeration.hpp b/include/mapnik/enumeration.hpp index ce945843a..9cd956435 100644 --- a/include/mapnik/enumeration.hpp +++ b/include/mapnik/enumeration.hpp @@ -251,7 +251,7 @@ class MAPNIK_DECL enumeration { std::cerr << "### FATAL: Not enough strings for enum " << our_name_ << " defined in file '" << filename << "' at line " << line_no << std::endl; - exit(1); + std::exit(1); } } if ( std::string("") != our_strings_[THE_MAX]) @@ -260,7 +260,7 @@ class MAPNIK_DECL enumeration { << " defined in file '" << filename << "' at line " << line_no << " has too many items or is not terminated with an " << "empty string." << std::endl; - exit(1); + std::exit(1); } return true; } diff --git a/include/mapnik/gamma.hpp b/include/mapnik/gamma.hpp index bd4df437e..ba072642a 100644 --- a/include/mapnik/gamma.hpp +++ b/include/mapnik/gamma.hpp @@ -27,6 +27,11 @@ #include +// When using Sun's C++ compiler, use the `std` namespace to get the math routines. +#ifdef __SUNPRO_CC +using std::pow; +#endif + namespace mapnik { struct MAPNIK_DECL gamma diff --git a/include/mapnik/geom_util.hpp b/include/mapnik/geom_util.hpp index 57cedf8dc..0e4dd9c0d 100644 --- a/include/mapnik/geom_util.hpp +++ b/include/mapnik/geom_util.hpp @@ -32,6 +32,12 @@ // stl #include +// When using Sun's C++ compiler, use the `std` namespace to get the math routines. +#ifdef __SUNPRO_CC +using std::fabs; +using std::sqrt; +#endif + namespace mapnik { template diff --git a/include/mapnik/global.hpp b/include/mapnik/global.hpp index da12558e0..d27be2747 100644 --- a/include/mapnik/global.hpp +++ b/include/mapnik/global.hpp @@ -27,11 +27,15 @@ #include +#ifdef __SUNPRO_CC +// Foo +#else using boost::int32_t; using boost::uint32_t; using boost::int16_t; using boost::uint16_t; using boost::uint8_t; +#endif namespace mapnik { diff --git a/include/mapnik/image_data.hpp b/include/mapnik/image_data.hpp index 749805e2b..fa53f5f0b 100644 --- a/include/mapnik/image_data.hpp +++ b/include/mapnik/image_data.hpp @@ -28,6 +28,12 @@ #include #include +// When using Sun's C++ compiler, use the `std` namespace to get memcpy, memset routines. +#ifdef __SUNPRO_CC +using std::memcpy; +using std::memset; +#endif + namespace mapnik { template class ImageData diff --git a/include/mapnik/utils.hpp b/include/mapnik/utils.hpp index ed03d429f..badfdee10 100644 --- a/include/mapnik/utils.hpp +++ b/include/mapnik/utils.hpp @@ -79,8 +79,12 @@ namespace mapnik static MaxAlign staticMemory; return new(&staticMemory) T; } - +#ifdef __SUNPRO_CC + // Sun C++ Compiler doesn't handle `volatile` keyword same as GCC. + static void destroy(T* obj) +#else static void destroy(volatile T* obj) +#endif { obj->~T(); } @@ -89,7 +93,15 @@ namespace mapnik template class CreatePolicy=CreateStatic> class singleton { - friend class CreatePolicy; +#ifdef __SUNPRO_CC + /* Sun's C++ compiler will issue the following errors if CreatePolicy is used: + Error: A class template name was expected instead of mapnik::CreatePolicy + Error: A "friend" declaration must specify a class or function. + */ + friend class CreatePolicy; +#else + friend class CreatePolicy; +#endif static T* pInstance_; static bool destroyed_; singleton(const singleton &rhs); diff --git a/scons/scons-local-0.97/SCons/Tool/sunc++.py b/scons/scons-local-0.97/SCons/Tool/sunc++.py index c7d91ddd0..36ac37d3b 100644 --- a/scons/scons-local-0.97/SCons/Tool/sunc++.py +++ b/scons/scons-local-0.97/SCons/Tool/sunc++.py @@ -39,6 +39,8 @@ import os.path cplusplus = __import__('c++', globals(), locals(), []) +compilers = ['CC', 'sunCC'] + # use the package installer tool lslpp to figure out where cppc and what # version of it is installed def get_cppc(env): @@ -69,16 +71,11 @@ def generate(env): cplusplus.generate(env) env['CXX'] = cxx - env['SHCXX'] = shcxx + #env['SHCXX'] = shcxx env['CXXVERSION'] = version env['SHCXXFLAGS'] = SCons.Util.CLVar('$CXXFLAGS -KPIC') env['SHOBJPREFIX'] = 'so_' env['SHOBJSUFFIX'] = '.o' def exists(env): - path, cxx, shcxx, version = get_cppc(env) - if path and cxx: - cppc = os.path.join(path, cxx) - if os.path.exists(cppc): - return cppc - return None + return env.Detect(compilers) diff --git a/src/SConscript b/src/SConscript index 1820fceea..b1b0133b6 100644 --- a/src/SConscript +++ b/src/SConscript @@ -35,6 +35,8 @@ libraries = ['agg'] + env['LIBS'] if env['PLATFORM'] == 'Darwin': libraries.append('iconv') linkflags = '-Wl,-install_name,libmapnik.dylib' +elif env['PLATFORM'] == 'SunOS' and env['CXX'].startswith('CC'): + linkflags = '-R. -h libmapnik.so' else: # Linux and others linkflags = '-Wl,-rpath-link,. -Wl,-soname,libmapnik.so.' + ("%d.%d" % (ABI_VERSION[0],ABI_VERSION[1])) diff --git a/src/distance.cpp b/src/distance.cpp index efe89570c..22621d2c0 100644 --- a/src/distance.cpp +++ b/src/distance.cpp @@ -26,6 +26,15 @@ #include #include +// When using Sun's C++ compiler, use the `std` namespace to get the math routines. +#ifdef __SUNPRO_CC +using std::atan2; +using std::cos; +using std::pow; +using std::sin; +using std::sqrt; +#endif + namespace mapnik { static const double deg2rad = 0.0174532925199432958; diff --git a/src/envelope.cpp b/src/envelope.cpp index ef40ff00a..c679077a4 100644 --- a/src/envelope.cpp +++ b/src/envelope.cpp @@ -48,7 +48,10 @@ namespace mapnik } template - inline bool Envelope::operator==(const Envelope& other) const +#if !defined(__SUNPRO_CC) + inline +#endif + bool Envelope::operator==(const Envelope& other) const { return minx_==other.minx_ && miny_==other.miny_ && @@ -57,43 +60,64 @@ namespace mapnik } template - inline T Envelope::minx() const +#if !defined(__SUNPRO_CC) + inline +#endif + T Envelope::minx() const { return minx_; } template - inline T Envelope::maxx() const +#if !defined(__SUNPRO_CC) + inline +#endif + T Envelope::maxx() const { return maxx_; } template - inline T Envelope::miny() const +#if !defined(__SUNPRO_CC) + inline +#endif + T Envelope::miny() const { return miny_; } template - inline T Envelope::maxy() const +#if !defined(__SUNPRO_CC) + inline +#endif + T Envelope::maxy() const { return maxy_; } template - inline T Envelope::width() const +#if !defined(__SUNPRO_CC) + inline +#endif + T Envelope::width() const { return maxx_-minx_; } template - inline T Envelope::height() const +#if !defined(__SUNPRO_CC) + inline +#endif + T Envelope::height() const { return maxy_-miny_; } template - inline void Envelope::width(T w) +#if !defined(__SUNPRO_CC) + inline +#endif + void Envelope::width(T w) { T cx=center().x; minx_=static_cast(cx-w*0.5); @@ -101,7 +125,10 @@ namespace mapnik } template - inline void Envelope::height(T h) +#if !defined(__SUNPRO_CC) + inline +#endif + void Envelope::height(T h) { T cy=center().y; miny_=static_cast(cy-h*0.5); @@ -109,20 +136,29 @@ namespace mapnik } template - inline coord Envelope::center() const +#if !defined(__SUNPRO_CC) + inline +#endif + coord Envelope::center() const { return coord(static_cast(0.5*(minx_+maxx_)), static_cast(0.5*(miny_+maxy_))); } template - inline void Envelope::expand_to_include(const coord& c) +#if !defined(__SUNPRO_CC) + inline +#endif + void Envelope::expand_to_include(const coord& c) { expand_to_include(c.x,c.y); } template - inline void Envelope::expand_to_include(T x,T y) +#if !defined(__SUNPRO_CC) + inline +#endif + void Envelope::expand_to_include(T x,T y) { if (xmaxx_) maxx_=x; @@ -140,19 +176,28 @@ namespace mapnik } template - inline bool Envelope::contains(const coord &c) const +#if !defined(__SUNPRO_CC) + inline +#endif + bool Envelope::contains(const coord &c) const { return contains(c.x,c.y); } template - inline bool Envelope::contains(T x,T y) const +#if !defined(__SUNPRO_CC) + inline +#endif + bool Envelope::contains(T x,T y) const { return x>=minx_ && x<=maxx_ && y>=miny_ && y<=maxy_; } template - inline bool Envelope::contains(const Envelope &other) const +#if !defined(__SUNPRO_CC) + inline +#endif + bool Envelope::contains(const Envelope &other) const { return other.minx_>=minx_ && other.maxx_<=maxx_ && @@ -161,26 +206,38 @@ namespace mapnik } template - inline bool Envelope::intersects(const coord &c) const +#if !defined(__SUNPRO_CC) + inline +#endif + bool Envelope::intersects(const coord &c) const { return intersects(c.x,c.y); } template - inline bool Envelope::intersects(T x,T y) const +#if !defined(__SUNPRO_CC) + inline +#endif + bool Envelope::intersects(T x,T y) const { return !(x>maxx_ || xmaxy_ || y - inline bool Envelope::intersects(const Envelope &other) const +#if !defined(__SUNPRO_CC) + inline +#endif + bool Envelope::intersects(const Envelope &other) const { return !(other.minx_>maxx_ || other.maxx_maxy_ || other.maxy_ - inline Envelope Envelope::intersect(const EnvelopeType& other) const +#if !defined(__SUNPRO_CC) + inline +#endif + Envelope Envelope::intersect(const EnvelopeType& other) const { T x0=std::max(minx_,other.minx_); @@ -193,7 +250,10 @@ namespace mapnik } template - inline void Envelope::re_center(T cx,T cy) +#if !defined(__SUNPRO_CC) + inline +#endif + void Envelope::re_center(T cx,T cy) { T dx=cx-center().x; T dy=cy-center().y; @@ -204,7 +264,10 @@ namespace mapnik } template - inline void Envelope::init(T x0,T y0,T x1,T y1) +#if !defined(__SUNPRO_CC) + inline +#endif + void Envelope::init(T x0,T y0,T x1,T y1) { if (x0(input.data());