scons: make sure help is displayed if -h or --help is supplied even if we are not able to configure successfully and add more user friendly output for dependencies that are not found
This commit is contained in:
parent
5094080f77
commit
de4032a602
1 changed files with 137 additions and 81 deletions
218
SConstruct
218
SConstruct
|
@ -54,11 +54,11 @@ def regular_print(color,text,newline=True):
|
||||||
else:
|
else:
|
||||||
print text
|
print text
|
||||||
|
|
||||||
def call(cmd):
|
def call(cmd, silent=False):
|
||||||
stdin, stderr = Popen(cmd,shell=True,stdout=PIPE,stderr=PIPE).communicate()
|
stdin, stderr = Popen(cmd,shell=True,stdout=PIPE,stderr=PIPE).communicate()
|
||||||
if not stderr:
|
if not stderr:
|
||||||
return stdin.strip()
|
return stdin.strip()
|
||||||
else:
|
elif not silent:
|
||||||
color_print(1,'Problem encounted with SCons scripts, please post bug report to: http://trac.mapnik.org\nError was: %s' % stderr)
|
color_print(1,'Problem encounted with SCons scripts, please post bug report to: http://trac.mapnik.org\nError was: %s' % stderr)
|
||||||
|
|
||||||
def shortest_name(libs):
|
def shortest_name(libs):
|
||||||
|
@ -75,6 +75,39 @@ elif platform.uname()[4] == 'ppc64':
|
||||||
else:
|
else:
|
||||||
LIBDIR_SCHEMA='lib'
|
LIBDIR_SCHEMA='lib'
|
||||||
|
|
||||||
|
pretty_dep_names = {
|
||||||
|
'ociei':'Oracle database library | configure with OCCI_LIBS & OCCI_INCLUDES | more info: http://trac.mapnik.org/wiki/OCCI',
|
||||||
|
'gdal':'GDAL C++ library | configured using gdal-config program | try setting GDAL_CONFIG SCons option | more info: http://trac.mapnik.org/wiki/GDAL',
|
||||||
|
'ogr':'OGR-enabled GDAL C++ Library | configured using gdal-config program | try setting GDAL_CONFIG SCons option | more info: http://trac.mapnik.org/wiki/OGR',
|
||||||
|
'cairo':'Cairo C library | configured using pkg-config | try setting PKG_CONFIG_PATH SCons option',
|
||||||
|
'cairomm':'Cairomm C++ bindings to Cairo library | configured using pkg-config | try setting PKG_CONFIG_PATH SCons option',
|
||||||
|
'pycairo':'Python bindings to Cairo library | configured using pkg-config | try setting PKG_CONFIG_PATH SCons option',
|
||||||
|
'proj':'Proj.4 C Projections library | configure with PROJ_LIBS & PROJ_INCLUDES | more info: http://trac.osgeo.org/proj/',
|
||||||
|
'pg':'Postgres C Library requiered for PostGIS plugin | configure with pg_config program | more info: http://trac.mapnik.org/wiki/PostGIS',
|
||||||
|
'sqlite3':'SQLite3 C Library | configure with SQLITE_LIBS & SQLITE_INCLUDES | more info: http://trac.mapnik.org/wiki/SQLite',
|
||||||
|
'osm':'more info: http://trac.mapnik.org/wiki/OsmPlugin',
|
||||||
|
'jpeg':'JPEG C library | configure with JPEG_LIBS & JPEG_INCLUDES',
|
||||||
|
'tiff':'TIFF C library | configure with TIFF_LIBS & TIFF_INCLUDES',
|
||||||
|
'png':'PNG C library | configure with PNG_LIBS & PNG_INCLUDES',
|
||||||
|
'icuuc':'ICU C++ library | configure with ICU_LIBS & ICU_INCLUDES or use ICU_LIB_NAME to specify custom lib name | more info: http://site.icu-project.org/',
|
||||||
|
'ltdl':'GNU Libtool | more info: http://www.gnu.org/software/libtool',
|
||||||
|
'z':'Z compression library | more info: http://www.zlib.net/',
|
||||||
|
'm':'Basic math library, part of C++ stlib',
|
||||||
|
'pkg-config':'pkg-config tool | more info: http://pkg-config.freedesktop.org',
|
||||||
|
'pg_config':'pg_config program | try setting PG_CONFIG SCons option',
|
||||||
|
'xml2-config':'xml2-config program | try setting XML2_CONFIG SCons option',
|
||||||
|
'gdal-config':'gdal-config program | try setting GDAL_CONFIG SCons option',
|
||||||
|
'freetype-config':'freetype-config program | try setting FREETYPE_CONFIG SCons option',
|
||||||
|
}
|
||||||
|
|
||||||
|
def pretty_dep(dep):
|
||||||
|
pretty = pretty_dep_names.get(dep)
|
||||||
|
if pretty:
|
||||||
|
return '%s (%s)' % (dep,pretty)
|
||||||
|
elif 'boost' in dep:
|
||||||
|
return '%s (%s)' % (dep,'more info see: http://trac.mapnik.org/wiki/MapnikInstallation & http://www.boost.org')
|
||||||
|
return dep
|
||||||
|
|
||||||
# local file to hold custom user configuration variables
|
# local file to hold custom user configuration variables
|
||||||
SCONS_LOCAL_CONFIG = 'config.py'
|
SCONS_LOCAL_CONFIG = 'config.py'
|
||||||
# local pickled file to cache configured environment
|
# local pickled file to cache configured environment
|
||||||
|
@ -95,9 +128,10 @@ PLUGINS = { # plugins with external dependencies
|
||||||
'sqlite': {'default':False,'path':'SQLITE','inc':'sqlite3.h','lib':'sqlite3','lang':'C'},
|
'sqlite': {'default':False,'path':'SQLITE','inc':'sqlite3.h','lib':'sqlite3','lang':'C'},
|
||||||
'rasterlite': {'default':False,'path':'RASTERLITE','inc':['sqlite3.h','rasterlite.h'],'lib':'rasterlite','lang':'C'},
|
'rasterlite': {'default':False,'path':'RASTERLITE','inc':['sqlite3.h','rasterlite.h'],'lib':'rasterlite','lang':'C'},
|
||||||
|
|
||||||
# plugins without external dependencies requiring CheckLibWithHeader...
|
# todo: osm plugin does depend on libxml2 and libcurl
|
||||||
# note: osm plugin does depend on libxml2
|
|
||||||
'osm': {'default':False,'path':None,'inc':None,'lib':None,'lang':'C++'},
|
'osm': {'default':False,'path':None,'inc':None,'lib':None,'lang':'C++'},
|
||||||
|
|
||||||
|
# plugins without external dependencies requiring CheckLibWithHeader...
|
||||||
'shape': {'default':True,'path':None,'inc':None,'lib':None,'lang':'C++'},
|
'shape': {'default':True,'path':None,'inc':None,'lib':None,'lang':'C++'},
|
||||||
'raster': {'default':True,'path':None,'inc':None,'lib':None,'lang':'C++'},
|
'raster': {'default':True,'path':None,'inc':None,'lib':None,'lang':'C++'},
|
||||||
'kismet': {'default':False,'path':None,'inc':None,'lib':None,'lang':'C++'},
|
'kismet': {'default':False,'path':None,'inc':None,'lib':None,'lang':'C++'},
|
||||||
|
@ -233,9 +267,15 @@ preconfigured = False
|
||||||
force_configure = False
|
force_configure = False
|
||||||
command_line_args = sys.argv[1:]
|
command_line_args = sys.argv[1:]
|
||||||
|
|
||||||
|
HELP_REQUESTED = False
|
||||||
|
|
||||||
|
if ('-h' in command_line_args) or ('--help' in command_line_args):
|
||||||
|
HELP_REQUESTED = True
|
||||||
|
|
||||||
|
|
||||||
if 'configure' in command_line_args:
|
if 'configure' in command_line_args:
|
||||||
force_configure = True
|
force_configure = True
|
||||||
elif ('-h' in command_line_args) or ('--help' in command_line_args):
|
elif HELP_REQUESTED:
|
||||||
preconfigured = True # this is just to ensure config gets skipped when help is requested
|
preconfigured = True # this is just to ensure config gets skipped when help is requested
|
||||||
|
|
||||||
# initially populate environment with defaults and any possible custom arguments
|
# initially populate environment with defaults and any possible custom arguments
|
||||||
|
@ -274,7 +314,7 @@ if opts.args:
|
||||||
preconfigured = False
|
preconfigured = False
|
||||||
|
|
||||||
elif preconfigured:
|
elif preconfigured:
|
||||||
if ('-h' not in command_line_args) and ('--help' not in command_line_args):
|
if not HELP_REQUESTED:
|
||||||
color_print(4,'Using previous successful configuration...')
|
color_print(4,'Using previous successful configuration...')
|
||||||
color_print(4,'Re-configure by running "python scons/scons.py configure".')
|
color_print(4,'Re-configure by running "python scons/scons.py configure".')
|
||||||
|
|
||||||
|
@ -298,14 +338,21 @@ def CheckPKG(context, name):
|
||||||
def parse_config(context, config, checks='--libs --cflags'):
|
def parse_config(context, config, checks='--libs --cflags'):
|
||||||
env = context.env
|
env = context.env
|
||||||
tool = config.lower().replace('_','-')
|
tool = config.lower().replace('_','-')
|
||||||
|
toolname = tool
|
||||||
if config == 'GDAL_CONFIG':
|
if config == 'GDAL_CONFIG':
|
||||||
tool += ' %s' % checks
|
toolname += ' %s' % checks
|
||||||
context.Message( 'Checking for %s... ' % tool)
|
context.Message( 'Checking for %s... ' % toolname)
|
||||||
cmd = '%s %s' % (env[config],checks)
|
cmd = '%s %s' % (env[config],checks)
|
||||||
ret = context.TryAction(cmd)[0]
|
ret = context.TryAction(cmd)[0]
|
||||||
|
parsed = False
|
||||||
if ret:
|
if ret:
|
||||||
env.ParseConfig(cmd)
|
try:
|
||||||
else:
|
env.ParseConfig(cmd)
|
||||||
|
parsed = True
|
||||||
|
except OSError, e:
|
||||||
|
ret = False
|
||||||
|
print ' (xml2-config not found!)'
|
||||||
|
if not parsed:
|
||||||
if config == 'GDAL_CONFIG':
|
if config == 'GDAL_CONFIG':
|
||||||
env['SKIPPED_DEPS'].append(tool)
|
env['SKIPPED_DEPS'].append(tool)
|
||||||
conf.rollback_option('GDAL_CONFIG')
|
conf.rollback_option('GDAL_CONFIG')
|
||||||
|
@ -321,10 +368,16 @@ def get_pkg_lib(context, config, lib):
|
||||||
context.Message( 'Checking for name of %s library... ' % lib)
|
context.Message( 'Checking for name of %s library... ' % lib)
|
||||||
cmd = '%s --libs' % env[config]
|
cmd = '%s --libs' % env[config]
|
||||||
ret = context.TryAction(cmd)[0]
|
ret = context.TryAction(cmd)[0]
|
||||||
|
parsed = False
|
||||||
if ret:
|
if ret:
|
||||||
libnames = re.findall(libpattern,call(cmd))
|
try:
|
||||||
if libnames:
|
libnames = re.findall(libpattern,call(cmd,silent=True))
|
||||||
libname = libnames[0]
|
if libnames:
|
||||||
|
libname = libnames[0]
|
||||||
|
except Exception, e:
|
||||||
|
ret = False
|
||||||
|
print ' unable to determine library name:'# %s' % str(e)
|
||||||
|
return None
|
||||||
context.Result( libname )
|
context.Result( libname )
|
||||||
return libname
|
return libname
|
||||||
|
|
||||||
|
@ -744,7 +797,8 @@ if not preconfigured:
|
||||||
backup = env.Clone().Dictionary()
|
backup = env.Clone().Dictionary()
|
||||||
# Note, the 'delete_existing' keyword makes sure that these paths are prepended
|
# Note, the 'delete_existing' keyword makes sure that these paths are prepended
|
||||||
# to the beginning of the path list even if they already exist
|
# to the beginning of the path list even if they already exist
|
||||||
env.PrependUnique(CPPPATH = env['%s_INCLUDES' % details['path']],delete_existing=True)
|
incpath = env['%s_INCLUDES' % details['path']]
|
||||||
|
env.PrependUnique(CPPPATH = incpath,delete_existing=True)
|
||||||
env.PrependUnique(LIBPATH = env['%s_LIBS' % details['path']],delete_existing=True)
|
env.PrependUnique(LIBPATH = env['%s_LIBS' % details['path']],delete_existing=True)
|
||||||
if not conf.CheckLibWithHeader(details['lib'], details['inc'], details['lang']):
|
if not conf.CheckLibWithHeader(details['lib'], details['inc'], details['lang']):
|
||||||
env.Replace(**backup)
|
env.Replace(**backup)
|
||||||
|
@ -781,10 +835,10 @@ if not preconfigured:
|
||||||
|
|
||||||
if env['MISSING_DEPS']:
|
if env['MISSING_DEPS']:
|
||||||
# if required dependencies are missing, print warnings and then let SCons finish without building or saving local config
|
# if required dependencies are missing, print warnings and then let SCons finish without building or saving local config
|
||||||
color_print(1,'\nExiting... the following required dependencies were not found:\n - %s' % '\n - '.join(env['MISSING_DEPS']))
|
color_print(1,'\nExiting... the following required dependencies were not found:\n - %s' % '\n - '.join([pretty_dep(dep) for dep in env['MISSING_DEPS']]))
|
||||||
color_print(1,"\nSee the 'config.log' for details on possible problems.")
|
color_print(1,"\nSee the 'config.log' for details on possible problems.")
|
||||||
if env['SKIPPED_DEPS']:
|
if env['SKIPPED_DEPS']:
|
||||||
color_print(4,'\nAlso, these optional dependencies were not found:\n - %s' % '\n - '.join(env['SKIPPED_DEPS']))
|
color_print(4,'\nAlso, these OPTIONAL dependencies were not found:\n - %s' % '\n - '.join([pretty_dep(dep) for dep in env['SKIPPED_DEPS']]))
|
||||||
color_print(4,"\nSet custom paths to these libraries and header files on the command-line or in a file called '%s'" % SCONS_LOCAL_CONFIG)
|
color_print(4,"\nSet custom paths to these libraries and header files on the command-line or in a file called '%s'" % SCONS_LOCAL_CONFIG)
|
||||||
color_print(4," ie. $ python scons/scons.py BOOST_INCLUDES=/usr/local/include BOOST_LIBS=/usr/local/lib")
|
color_print(4," ie. $ python scons/scons.py BOOST_INCLUDES=/usr/local/include BOOST_LIBS=/usr/local/lib")
|
||||||
color_print(4, "\nOnce all required dependencies are found a local '%s' will be saved and then install:" % SCONS_LOCAL_CONFIG)
|
color_print(4, "\nOnce all required dependencies are found a local '%s' will be saved and then install:" % SCONS_LOCAL_CONFIG)
|
||||||
|
@ -792,7 +846,8 @@ if not preconfigured:
|
||||||
color_print(4,"\nTo view available path variables:\n $ python scons/scons.py --help or -h")
|
color_print(4,"\nTo view available path variables:\n $ python scons/scons.py --help or -h")
|
||||||
color_print(4,'\nTo view overall SCons help options:\n $ python scons/scons.py --help-options or -H\n')
|
color_print(4,'\nTo view overall SCons help options:\n $ python scons/scons.py --help-options or -H\n')
|
||||||
color_print(4,'More info: http://trac.mapnik.org/wiki/MapnikInstallation')
|
color_print(4,'More info: http://trac.mapnik.org/wiki/MapnikInstallation')
|
||||||
Exit(1)
|
if not HELP_REQUESTED:
|
||||||
|
Exit(1)
|
||||||
else:
|
else:
|
||||||
# Save the custom variables in a SCONS_LOCAL_CONFIG
|
# Save the custom variables in a SCONS_LOCAL_CONFIG
|
||||||
# that will be reloaded to allow for `install` without re-specifying custom variables
|
# that will be reloaded to allow for `install` without re-specifying custom variables
|
||||||
|
@ -810,7 +865,7 @@ if not preconfigured:
|
||||||
color_print(4,"Did not use user config file, no custom path variables will be saved...")
|
color_print(4,"Did not use user config file, no custom path variables will be saved...")
|
||||||
|
|
||||||
if env['SKIPPED_DEPS']:
|
if env['SKIPPED_DEPS']:
|
||||||
color_print(3,'\nNote: will build without these optional dependencies:\n - %s' % '\n - '.join(env['SKIPPED_DEPS']))
|
color_print(3,'\nNote: will build without these OPTIONAL dependencies:\n - %s' % '\n - '.join([pretty_dep(dep) for dep in env['SKIPPED_DEPS']]))
|
||||||
print
|
print
|
||||||
|
|
||||||
# fetch the mapnik version header in order to set the
|
# fetch the mapnik version header in order to set the
|
||||||
|
@ -943,76 +998,77 @@ if not preconfigured:
|
||||||
|
|
||||||
if 'configure' in command_line_args:
|
if 'configure' in command_line_args:
|
||||||
color_print(4,'\n*Configure complete*\nNow run "python scons/scons.py" to build or "python scons/scons.py install" to install')
|
color_print(4,'\n*Configure complete*\nNow run "python scons/scons.py" to build or "python scons/scons.py install" to install')
|
||||||
Exit(0)
|
if not HELP_REQUESTED:
|
||||||
|
Exit(0)
|
||||||
|
|
||||||
# autogenerate help on default/current SCons options
|
# autogenerate help on default/current SCons options
|
||||||
Help(opts.GenerateHelpText(env))
|
Help(opts.GenerateHelpText(env))
|
||||||
|
|
||||||
#### Builds ####
|
#### Builds ####
|
||||||
|
if not HELP_REQUESTED:
|
||||||
# export env so it is available in Sconscript files
|
# export env so it is available in Sconscript files
|
||||||
Export('env')
|
Export('env')
|
||||||
|
|
||||||
|
|
||||||
if env['FAST']:
|
|
||||||
# caching is 'auto' by default in SCons
|
|
||||||
# But let's also cache implicit deps...
|
|
||||||
EnsureSConsVersion(0,98)
|
|
||||||
SetOption('implicit_cache', 1)
|
|
||||||
env.Decider('MD5-timestamp')
|
|
||||||
SetOption('max_drift', 1)
|
|
||||||
|
|
||||||
else:
|
|
||||||
# Set the cache mode to 'force' unless requested, avoiding hidden caching of Scons 'opts' in '.sconsign.dblite'
|
|
||||||
# This allows for a SCONS_LOCAL_CONFIG, if present, to be used as the primary means of storing paths to successful build dependencies
|
|
||||||
SetCacheMode('force')
|
|
||||||
|
|
||||||
if env['JOBS'] > 1:
|
|
||||||
SetOption("num_jobs", env['JOBS'])
|
|
||||||
|
|
||||||
# Build agg first, doesn't need anything special
|
if env['FAST']:
|
||||||
if env['INTERNAL_LIBAGG']:
|
# caching is 'auto' by default in SCons
|
||||||
SConscript('agg/SConscript')
|
# But let's also cache implicit deps...
|
||||||
|
EnsureSConsVersion(0,98)
|
||||||
# Build the core library
|
SetOption('implicit_cache', 1)
|
||||||
SConscript('src/SConscript')
|
env.Decider('MD5-timestamp')
|
||||||
|
SetOption('max_drift', 1)
|
||||||
# Build the requested and able-to-be-compiled input plug-ins
|
|
||||||
GDAL_BUILT = False
|
else:
|
||||||
OGR_BUILT = False
|
# Set the cache mode to 'force' unless requested, avoiding hidden caching of Scons 'opts' in '.sconsign.dblite'
|
||||||
for plugin in env['REQUESTED_PLUGINS']:
|
# This allows for a SCONS_LOCAL_CONFIG, if present, to be used as the primary means of storing paths to successful build dependencies
|
||||||
details = env['PLUGINS'][plugin]
|
SetCacheMode('force')
|
||||||
if details['lib'] in env['LIBS']:
|
|
||||||
SConscript('plugins/input/%s/SConscript' % plugin)
|
if env['JOBS'] > 1:
|
||||||
if plugin == 'ogr': OGR_BUILT = True
|
SetOption("num_jobs", env['JOBS'])
|
||||||
if plugin == 'gdal': GDAL_BUILT = True
|
|
||||||
if plugin == 'ogr' or plugin == 'gdal':
|
# Build agg first, doesn't need anything special
|
||||||
if GDAL_BUILT and OGR_BUILT:
|
if env['INTERNAL_LIBAGG']:
|
||||||
|
SConscript('agg/SConscript')
|
||||||
|
|
||||||
|
# Build the core library
|
||||||
|
SConscript('src/SConscript')
|
||||||
|
|
||||||
|
# Build the requested and able-to-be-compiled input plug-ins
|
||||||
|
GDAL_BUILT = False
|
||||||
|
OGR_BUILT = False
|
||||||
|
for plugin in env['REQUESTED_PLUGINS']:
|
||||||
|
details = env['PLUGINS'][plugin]
|
||||||
|
if details['lib'] in env['LIBS']:
|
||||||
|
SConscript('plugins/input/%s/SConscript' % plugin)
|
||||||
|
if plugin == 'ogr': OGR_BUILT = True
|
||||||
|
if plugin == 'gdal': GDAL_BUILT = True
|
||||||
|
if plugin == 'ogr' or plugin == 'gdal':
|
||||||
|
if GDAL_BUILT and OGR_BUILT:
|
||||||
|
env['LIBS'].remove(details['lib'])
|
||||||
|
else:
|
||||||
env['LIBS'].remove(details['lib'])
|
env['LIBS'].remove(details['lib'])
|
||||||
else:
|
elif not details['lib']:
|
||||||
env['LIBS'].remove(details['lib'])
|
# build internal shape and raster plugins
|
||||||
elif not details['lib']:
|
SConscript('plugins/input/%s/SConscript' % plugin)
|
||||||
# build internal shape and raster plugins
|
|
||||||
SConscript('plugins/input/%s/SConscript' % plugin)
|
|
||||||
|
|
||||||
# Build the c++ rundemo app if requested
|
|
||||||
if env['DEMO']:
|
|
||||||
SConscript('demo/c++/SConscript')
|
|
||||||
|
|
||||||
# Build the pgsql2psqlite app if requested
|
|
||||||
if env['PGSQL2SQLITE']:
|
|
||||||
SConscript('utils/pgsql2sqlite/SConscript')
|
|
||||||
|
|
||||||
# Build shapeindex and remove its dependency from the LIBS
|
# Build the c++ rundemo app if requested
|
||||||
if 'boost_program_options%s' % env['BOOST_APPEND'] in env['LIBS']:
|
if env['DEMO']:
|
||||||
SConscript('utils/shapeindex/SConscript')
|
SConscript('demo/c++/SConscript')
|
||||||
env['LIBS'].remove('boost_program_options%s' % env['BOOST_APPEND'])
|
|
||||||
else :
|
|
||||||
color_print(1,"WARNING: Cannot find boost_program_options. 'shapeindex' won't be available")
|
|
||||||
|
|
||||||
# Build the Python bindings
|
# Build the pgsql2psqlite app if requested
|
||||||
if 'python' in env['BINDINGS']:
|
if env['PGSQL2SQLITE']:
|
||||||
SConscript('bindings/python/SConscript')
|
SConscript('utils/pgsql2sqlite/SConscript')
|
||||||
|
|
||||||
# Configure fonts and if requested install the bundled DejaVu fonts
|
# Build shapeindex and remove its dependency from the LIBS
|
||||||
SConscript('fonts/SConscript')
|
if 'boost_program_options%s' % env['BOOST_APPEND'] in env['LIBS']:
|
||||||
|
SConscript('utils/shapeindex/SConscript')
|
||||||
|
env['LIBS'].remove('boost_program_options%s' % env['BOOST_APPEND'])
|
||||||
|
else :
|
||||||
|
color_print(1,"WARNING: Cannot find boost_program_options. 'shapeindex' won't be available")
|
||||||
|
|
||||||
|
# Build the Python bindings
|
||||||
|
if 'python' in env['BINDINGS']:
|
||||||
|
SConscript('bindings/python/SConscript')
|
||||||
|
|
||||||
|
# Configure fonts and if requested install the bundled DejaVu fonts
|
||||||
|
SConscript('fonts/SConscript')
|
||||||
|
|
Loading…
Reference in a new issue