Integrate libimagequant directly into the scons build. Enable SSE when available and not cross compiling, or explicitly enabled.

This commit is contained in:
Daniel Patterson 2015-05-16 01:18:53 -07:00
parent c30bb11c8b
commit dd4b84bd08
4 changed files with 42 additions and 19 deletions

View file

@ -84,7 +84,6 @@ pretty_dep_names = {
'jpeg':'JPEG C library | configure with JPEG_LIBS & JPEG_INCLUDES', 'jpeg':'JPEG C library | configure with JPEG_LIBS & JPEG_INCLUDES',
'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',
'imgquant':'ImageQuant C library | configure with IQ_LIBS & IQ_INCLUDES',
'webp':'WEBP C library | configure with WEBP_LIBS & WEBP_INCLUDES', 'webp':'WEBP C library | configure with WEBP_LIBS & WEBP_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/',
'harfbuzz':'HarfBuzz text shaping library | configure with HB_LIBS & HB_INCLUDES', 'harfbuzz':'HarfBuzz text shaping library | configure with HB_LIBS & HB_INCLUDES',
@ -298,6 +297,7 @@ opts.AddVariables(
('CUSTOM_DEFINES', 'Custom Compiler DEFINES, e.g. -DENABLE_THIS', ''), ('CUSTOM_DEFINES', 'Custom Compiler DEFINES, e.g. -DENABLE_THIS', ''),
('CUSTOM_CFLAGS', 'Custom C flags, e.g. -I<include dir> if you have headers in a nonstandard directory <include dir> (only used for configure checks)', ''), ('CUSTOM_CFLAGS', 'Custom C flags, e.g. -I<include dir> if you have headers in a nonstandard directory <include dir> (only used for configure checks)', ''),
('CUSTOM_LDFLAGS', 'Custom linker flags, e.g. -L<lib dir> if you have libraries in a nonstandard directory <lib dir>', ''), ('CUSTOM_LDFLAGS', 'Custom linker flags, e.g. -L<lib dir> if you have libraries in a nonstandard directory <lib dir>', ''),
EnumVariable('USE_SSE', "Build with SSE instruction set (will default to 'no' if cross-compiling)",'detect', ['detect','yes','no']),
EnumVariable('LINKING', "Set library format for libmapnik",'shared', ['shared','static']), EnumVariable('LINKING', "Set library format for libmapnik",'shared', ['shared','static']),
EnumVariable('RUNTIME_LINK', "Set preference for linking dependencies",'shared', ['shared','static']), EnumVariable('RUNTIME_LINK', "Set preference for linking dependencies",'shared', ['shared','static']),
EnumVariable('OPTIMIZATION','Set compiler optimization level','3', ['0','1','2','3','4','s']), EnumVariable('OPTIMIZATION','Set compiler optimization level','3', ['0','1','2','3','4','s']),
@ -347,9 +347,6 @@ opts.AddVariables(
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),
BoolVariable('IQ', 'Build Mapnik with ImageQuant support', 'True'),
PathVariable('IQ_INCLUDES', 'Search path for libimagequant include files', '/usr/include', PathVariable.PathAccept),
PathVariable('IQ_LIBS','Search path for libimagequant library files','/usr/' + LIBDIR_SCHEMA_DEFAULT, PathVariable.PathAccept),
BoolVariable('JPEG', 'Build Mapnik with JPEG read and write support', 'True'), BoolVariable('JPEG', 'Build Mapnik with JPEG read and write support', 'True'),
PathVariable('JPEG_INCLUDES', 'Search path for libjpeg include files', '/usr/include', PathVariable.PathAccept), PathVariable('JPEG_INCLUDES', 'Search path for libjpeg include files', '/usr/include', PathVariable.PathAccept),
PathVariable('JPEG_LIBS', 'Search path for libjpeg library files', '/usr/' + LIBDIR_SCHEMA_DEFAULT, PathVariable.PathAccept), PathVariable('JPEG_LIBS', 'Search path for libjpeg library files', '/usr/' + LIBDIR_SCHEMA_DEFAULT, PathVariable.PathAccept),
@ -1201,6 +1198,36 @@ if not preconfigured:
env.Append(LINKFLAGS = env['CUSTOM_LDFLAGS']) env.Append(LINKFLAGS = env['CUSTOM_LDFLAGS'])
### platform specific bits ### platform specific bits
#
# libimagequant includes SSE optimizations, so detect if flag is set (USE_SSE)
# or if 'detect', check current machine for support
SSE_DETECTED = False
if "darwin" in sys.platform:
import subprocess
process = subprocess.Popen(["sysctl","-a"], stdout=subprocess.PIPE)
result = process.communicate()[0]
for line in result.split("\n"):
if "cpu.feature" in line and "SSE" in line:
if "USE_SSE" in env and env["USE_SSE"] == "detect":
color_print(4,'SSE detected on Darwin host')
SSE_DETECTED = True
break
elif "linux" in sys.platform:
for line in open("/proc/cpuinfo"):
if "flags" in line and "SSE" in line:
if "USE_SSE" in env and env["USE_SSE"] == "detect":
color_print(4,'SSE detected on Linux host')
SSE_DETECTED = True
break
else:
if "USE_SSE" in env and env["USE_SSE"] == "detect":
color_print(4,'SSE detection not implemented on this platform, building without SSE')
# Only enable SSE when explitily set, or when not cross compiling and current host supports it
if (not env["HOST"] and (env["USE_SSE"] == "detect" and SSE_DETECTED)) or env["USE_SSE"] == "yes":
env.Append(CFLAGS = '-DUSE_SSE -msse')
if 'gcc' in env['CC']:
lib_env.Append(CFLAGS='-mfpmath=sse')
thread_suffix = 'mt' thread_suffix = 'mt'
if env['PLATFORM'] == 'FreeBSD': if env['PLATFORM'] == 'FreeBSD':
@ -1308,15 +1335,6 @@ if not preconfigured:
else: else:
env['SKIPPED_DEPS'].extend(['png']) env['SKIPPED_DEPS'].extend(['png'])
if env['IQ']:
OPTIONAL_LIBSHEADERS.append(['imagequant', 'libimagequant.h', False,'C','-DHAVE_IQ'])
inc_path = env['%s_INCLUDES' % 'IQ']
lib_path = env['%s_LIBS' % 'IQ']
env.AppendUnique(CPPPATH = fix_path(inc_path))
env.AppendUnique(LIBPATH = fix_path(lib_path))
else:
env['SKIPPED_DEPS'].extend(['iq'])
if env['WEBP']: if env['WEBP']:
OPTIONAL_LIBSHEADERS.append(['webp', 'webp/decode.h', False,'C','-DHAVE_WEBP']) OPTIONAL_LIBSHEADERS.append(['webp', 'webp/decode.h', False,'C','-DHAVE_WEBP'])
inc_path = env['%s_INCLUDES' % 'WEBP'] inc_path = env['%s_INCLUDES' % 'WEBP']
@ -1576,6 +1594,7 @@ if not preconfigured:
# prepend to make sure we link locally # prepend to make sure we link locally
env.Prepend(CPPPATH = '#deps/agg/include') env.Prepend(CPPPATH = '#deps/agg/include')
env.Prepend(LIBPATH = '#deps/agg') env.Prepend(LIBPATH = '#deps/agg')
env.Prepend(CPPPATH = '#deps/pngquant/lib')
env.Prepend(CPPPATH = '#deps/clipper/include') env.Prepend(CPPPATH = '#deps/clipper/include')
# prepend deps dir for auxillary headers # prepend deps dir for auxillary headers
env.Prepend(CPPPATH = '#deps') env.Prepend(CPPPATH = '#deps')

View file

@ -107,8 +107,6 @@ CAIRO_INCLUDES = '${MASON_LINKED_REL}/include'
CAIRO_LIBS = '${MASON_LINKED_REL}/lib' CAIRO_LIBS = '${MASON_LINKED_REL}/lib'
SQLITE_INCLUDES = '${MASON_LINKED_REL}/include' SQLITE_INCLUDES = '${MASON_LINKED_REL}/include'
SQLITE_LIBS = '${MASON_LINKED_REL}/lib' SQLITE_LIBS = '${MASON_LINKED_REL}/lib'
IQ_INCLUDES = /usr/local/include
IQ_LIBS = /usr/local/lib
BENCHMARK = True BENCHMARK = True
CPP_TESTS = True CPP_TESTS = True
PGSQL2SQLITE = True PGSQL2SQLITE = True

View file

@ -42,7 +42,7 @@ extern "C"
{ {
#include <png.h> #include <png.h>
// TODO: make this optional // TODO: make this optional
#include "libimagequant.h" #include <libimagequant.h>
} }
#define MAX_OCTREE_LEVELS 4 #define MAX_OCTREE_LEVELS 4

View file

@ -23,6 +23,7 @@
import os import os
import sys import sys
import glob import glob
import platform
from copy import copy from copy import copy
from subprocess import Popen, PIPE from subprocess import Popen, PIPE
@ -73,9 +74,6 @@ if '-DHAVE_PNG' in env['CPPDEFINES']:
lib_env['LIBS'].append('png') lib_env['LIBS'].append('png')
enabled_imaging_libraries.append('png_reader.cpp') enabled_imaging_libraries.append('png_reader.cpp')
if '-DHAVE_IQ' in env['CPPDEFINES']:
lib_env['LIBS'].append('imagequant')
if '-DMAPNIK_USE_PROJ4' in env['CPPDEFINES']: if '-DMAPNIK_USE_PROJ4' in env['CPPDEFINES']:
lib_env['LIBS'].append('proj') lib_env['LIBS'].append('proj')
@ -346,6 +344,14 @@ source += Split(
../deps/clipper/src/clipper.cpp ../deps/clipper/src/clipper.cpp
""") """)
# libimagequant
lib_env.Append(CFLAGS = "-O3 -fno-math-errno -funroll-loops -fomit-frame-pointer -std=c99")
# As of GCC 4.5, 387 fp math is significantly slower in C99 mode without this.
# Note: CPUs without SSE2 use 387 for doubles, even when SSE fp math is set.
if 'gcc' in env['CC']:
lib_env.Append(CFLAGS='-fexcess-prevision=fast')
source += glob.glob("../deps/pngquant/lib/" + "*.c")
if env['RUNTIME_LINK'] == "static": if env['RUNTIME_LINK'] == "static":
source += glob.glob('../deps/agg/src/' + '*.cpp') source += glob.glob('../deps/agg/src/' + '*.cpp')