scons: clean up the main SConstruct file more.

Add some features to read_command so it works a little bit better
Clean up the mercurial checks.
Filter the user environment and only pick out the useful stuff.
This commit is contained in:
Nathan Binkert 2009-02-11 16:58:51 -08:00
parent f255957b90
commit 312fbb1b48

View file

@ -1,5 +1,6 @@
# -*- mode:python -*- # -*- mode:python -*-
# Copyright (c) 2009 The Hewlett-Packard Development Company
# Copyright (c) 2004-2005 The Regents of The University of Michigan # Copyright (c) 2004-2005 The Regents of The University of Michigan
# All rights reserved. # All rights reserved.
# #
@ -106,12 +107,27 @@ from os.path import exists, isdir, isfile
from os.path import join as joinpath, split as splitpath from os.path import join as joinpath, split as splitpath
import SCons import SCons
import SCons.Node
def read_command(cmd): def read_command(cmd, **kwargs):
"""run the command cmd, read the results and return them """run the command cmd, read the results and return them
this is sorta like `cmd` in shell""" this is sorta like `cmd` in shell"""
from subprocess import Popen, PIPE, STDOUT from subprocess import Popen, PIPE, STDOUT
subp = Popen(cmd, shell=True, stdout=PIPE, stderr=STDOUT, close_fds=True)
no_exception = 'exception' in kwargs
exception = kwargs.pop('exception', None)
kwargs.setdefault('shell', False)
kwargs.setdefault('stdout', PIPE)
kwargs.setdefault('stderr', STDOUT)
kwargs.setdefault('close_fds', True)
try:
subp = Popen(cmd, **kwargs)
except Exception, e:
if no_exception:
return exception
raise
return subp.communicate()[0] return subp.communicate()[0]
# helper function: compare arrays or strings of version numbers. # helper function: compare arrays or strings of version numbers.
@ -137,40 +153,34 @@ def compare_versions(v1, v2):
if len(v1) > len(v2): return 1 if len(v1) > len(v2): return 1
return 0 return 0
# The absolute path to the current directory (where this file lives). ########################################################################
ROOT = Dir('.').abspath #
# Set up the base build environment.
#
########################################################################
use_vars = set([ 'AS', 'AR', 'CC', 'CXX', 'HOME', 'PATH', 'RANLIB' ])
# Path to the M5 source tree. use_env = {}
SRCDIR = joinpath(ROOT, 'src') for key,val in os.environ.iteritems():
if key in use_vars or key.startswith("M5"):
use_env[key] = val
# tell python where to find m5 python code env = Environment(ENV=use_env)
sys.path.append(joinpath(ROOT, 'src/python')) env.root = Dir(".") # The current directory (where this file lives).
env.srcdir = Dir("src") # The source directory
################################################### ########################################################################
#
# Mercurial Stuff. # Mercurial Stuff.
# 1) Grab repository revision if we know it. #
# 2) Ensure that the style hook is in place. # If the M5 directory is a mercurial repository, we should do some
################################################### # extra things.
#
########################################################################
hg_info = "Unknown" hgdir = env.root.Dir(".hg")
try:
if not exists(ROOT) or not isdir(ROOT) or \
not exists(joinpath(ROOT, ".hg")):
raise ValueError(".hg directory not found")
hg_info = read_command("cd %s; hg id -n -i -t -b" % ROOT).strip()
except ImportError, e:
print "Mercurial not found"
except ValueError, e:
print e
except Exception, e:
print "Other mercurial exception: %s" % e
def check_style_hook(ui): mercurial_style_message = """
ui.readconfig(joinpath(ROOT, '.hg', 'hgrc'))
style_hook = ui.config('hooks', 'pretxncommit.style', None)
if not style_hook:
print """\
You're missing the M5 style hook. You're missing the M5 style hook.
Please install the hook so we can ensure that all code fits a common style. Please install the hook so we can ensure that all code fits a common style.
@ -183,16 +193,50 @@ style = %s/util/style.py
[hooks] [hooks]
pretxncommit.style = python:style.check_whitespace pretxncommit.style = python:style.check_whitespace
""" % (ROOT) """ % (env.root)
sys.exit(1)
if ARGUMENTS.get('IGNORE_STYLE') != 'True' and isdir(joinpath(ROOT, '.hg')): mercurial_bin_not_found = """
Mercurial binary cannot be found, unfortunately this means that we
cannot easily determine the version of M5 that you are running and
this makes error messages more difficult to collect. Please consider
installing mercurial if you choose to post an error message
"""
mercurial_lib_not_found = """
Mercurial libraries cannot be found, ignoring style hook
If you are actually a M5 developer, please fix this and
run the style hook. It is important.
"""
if hgdir.exists():
# 1) Grab repository revision if we know it.
cmd = "hg id -n -i -t -b"
try: try:
from mercurial import ui hg_info = read_command(cmd, cwd=env.root.abspath).strip()
check_style_hook(ui.ui()) except OSError:
except ImportError: hg_info = "Unknown"
pass print mercurial_bin_not_found
env['HG_INFO'] = hg_info
# 2) Ensure that the style hook is in place.
try:
ui = None
if ARGUMENTS.get('IGNORE_STYLE') != 'True':
from mercurial import ui
ui = ui.ui()
except ImportError:
print mercurial_lib_not_found
if ui is not None:
ui.readconfig(hgdir.File('hgrc').abspath)
style_hook = ui.config('hooks', 'pretxncommit.style', None)
if not style_hook:
print mercurial_style_message
sys.exit(1)
else:
print ".hg directory not found"
################################################### ###################################################
# #
@ -257,18 +301,6 @@ for t in abs_targets:
if not isdir(build_root): if not isdir(build_root):
mkdir(build_root) mkdir(build_root)
###################################################
#
# Set up the default build environment. This environment is copied
# and modified according to each selected configuration.
#
###################################################
env = Environment(ENV = environ, # inherit user's environment vars
ROOT = ROOT,
SRCDIR = SRCDIR,
HG_INFO = hg_info)
Export('env') Export('env')
env.SConsignFile(joinpath(build_root, "sconsign")) env.SConsignFile(joinpath(build_root, "sconsign"))
@ -329,7 +361,7 @@ global_sticky_vars.Save(global_sticky_vars_file, env)
# Parse EXTRAS variable to build list of all directories where we're # Parse EXTRAS variable to build list of all directories where we're
# look for sources etc. This list is exported as base_dir_list. # look for sources etc. This list is exported as base_dir_list.
base_dir = joinpath(ROOT, 'src') base_dir = env.srcdir.abspath
if env['EXTRAS']: if env['EXTRAS']:
extras_dir_list = env['EXTRAS'].split(':') extras_dir_list = env['EXTRAS'].split(':')
else: else:
@ -340,9 +372,13 @@ Export('extras_dir_list')
# M5_PLY is used by isa_parser.py to find the PLY package. # M5_PLY is used by isa_parser.py to find the PLY package.
env.Append(ENV = { 'M5_PLY' : str(Dir('ext/ply')) }) env.Append(ENV = { 'M5_PLY' : str(Dir('ext/ply')) })
env['GCC'] = read_command(env['CXX'] + ' --version').find('g++') >= 0
env['SUNCC'] = read_command(env['CXX'] + ' -V').find('Sun C++') >= 0 CXX_version = read_command([env['CXX'],'--version'], exception=False)
env['ICC'] = read_command(env['CXX'] + ' -V').find('Intel') >= 0 CXX_V = read_command([env['CXX'],'-V'], exception=False)
env['GCC'] = CXX_version and CXX_version.find('g++') >= 0
env['SUNCC'] = CXX_V and CXX_V.find('Sun C++') >= 0
env['ICC'] = CXX_V and CXX_V.find('Intel') >= 0
if env['GCC'] + env['SUNCC'] + env['ICC'] > 1: if env['GCC'] + env['SUNCC'] + env['ICC'] > 1:
print 'Error: How can we have two at the same time?' print 'Error: How can we have two at the same time?'
Exit(1) Exit(1)
@ -388,7 +424,7 @@ if not env.has_key('SWIG'):
Exit(1) Exit(1)
# Check for appropriate SWIG version # Check for appropriate SWIG version
swig_version = read_command('swig -version').split() swig_version = read_command(('swig', '-version'), exception='').split()
# First 3 words should be "SWIG Version x.y.z" # First 3 words should be "SWIG Version x.y.z"
if len(swig_version) < 3 or \ if len(swig_version) < 3 or \
swig_version[0] != 'SWIG' or swig_version[1] != 'Version': swig_version[0] != 'SWIG' or swig_version[1] != 'Version':
@ -597,6 +633,8 @@ env = conf.Finish()
# Collect all non-global variables # Collect all non-global variables
# #
Export('env')
# Define the universe of supported ISAs # Define the universe of supported ISAs
all_isa_list = [ ] all_isa_list = [ ]
Export('all_isa_list') Export('all_isa_list')
@ -708,13 +746,11 @@ env.Append(BUILDERS = { 'ConfigFile' : config_builder })
# libelf build is shared across all configs in the build root. # libelf build is shared across all configs in the build root.
env.SConscript('ext/libelf/SConscript', env.SConscript('ext/libelf/SConscript',
variant_dir = joinpath(build_root, 'libelf'), variant_dir = joinpath(build_root, 'libelf'))
exports = 'env')
# gzstream build is shared across all configs in the build root. # gzstream build is shared across all configs in the build root.
env.SConscript('ext/gzstream/SConscript', env.SConscript('ext/gzstream/SConscript',
variant_dir = joinpath(build_root, 'gzstream'), variant_dir = joinpath(build_root, 'gzstream'))
exports = 'env')
################################################### ###################################################
# #
@ -859,12 +895,3 @@ for variant_path in variant_paths:
exports = { 'env' : e }, duplicate = False) exports = { 'env' : e }, duplicate = False)
Help(help_text) Help(help_text)
###################################################
#
# Let SCons do its thing. At this point SCons will use the defined
# build environments to build the requested targets.
#
###################################################