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:
Dane Springmeyer 2010-01-05 23:27:13 +00:00
parent a3b3d7dde6
commit b64fb713f3

View file

@ -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
@ -94,9 +127,10 @@ PLUGINS = { # plugins with external dependencies
'occi': {'default':False,'path':'OCCI','inc':'occi.h','lib':'ociei','lang':'C++'}, 'occi': {'default':False,'path':'OCCI','inc':'occi.h','lib':'ociei','lang':'C++'},
'sqlite': {'default':False,'path':'SQLITE','inc':'sqlite3.h','lib':'sqlite3','lang':'C'}, 'sqlite': {'default':False,'path':'SQLITE','inc':'sqlite3.h','lib':'sqlite3','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++'},
@ -230,9 +264,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
@ -271,7 +311,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".')
@ -295,14 +335,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')
@ -318,10 +365,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
@ -741,7 +794,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)
@ -778,18 +832,19 @@ 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-1_37 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)
color_print(4," $ sudo python scons/scons.py install") color_print(4," $ sudo python scons/scons.py install")
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
@ -807,7 +862,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
@ -940,76 +995,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')