aos/tools/harness/builds.py
Daniel Schwyn 6d444bf552 Main handout
Signed-off-by: Daniel Schwyn <daniel.schwyn@inf.ethz.ch>
2022-03-03 14:57:51 +01:00

241 lines
8.4 KiB
Python

##########################################################################
# Copyright (c) 2009, 2010, 2011, ETH Zurich.
# All rights reserved.
#
# This file is distributed under the terms in the attached LICENSE file.
# If you do not find this file, copies can be found by writing to:
# ETH Zurich D-INFK, Universitaetstrasse 6, CH-8092 Zurich. Attn: Systems Group.
##########################################################################
import os, errno, re
import siteconfig
import debug
MPSS_LINUX_PATH=':/opt/mpss/3.7.1/sysroots/x86_64-mpsssdk-linux/usr/bin:/opt/mpss/3.7.1/sysroots/x86_64-mpsssdk-linux/usr/bin/k1om-mpss-linux'
class Build(object):
name = None # should be overriden by a subclass
def __init__(self, options):
self.build_dir = None
self.options = options
def _make_build_dir(self, build_dir=None):
if build_dir is None:
build_dir = os.path.join(self.options.buildbase, self.name.lower())
self.build_dir = build_dir
debug.verbose('creating build directory %s' % build_dir)
try:
os.makedirs(build_dir)
except OSError, e:
if e.errno == errno.EEXIST:
debug.log("reusing existing build in directory %s" % build_dir)
else:
raise
def configure(self, checkout):
raise NotImplementedError
def build(self, targets):
raise NotImplementedError
def install(self, targets, path):
"""install to the given path"""
raise NotImplementedError
class HakeBuildBase(Build):
def _run_hake(self, srcdir, archs):
# if srcdir is relative, adjust to be wrt build_dir
print archs
if not os.path.isabs(srcdir):
srcdir = os.path.relpath(srcdir, self.build_dir)
debug.checkcmd([os.path.join(srcdir, "hake", "hake.sh"), "--source-dir", srcdir],
cwd=self.build_dir)
def _get_hake_conf(self, srcdir, archs):
default_config = {
"source_dir": "\"%s\"" % srcdir,
"architectures": "[" + ", ".join("\"%s\"" % a for a in archs) + "]",
"install_dir": "\".\"",
"toolroot": "Nothing",
"arm_toolspec": "Nothing",
"aarch64_toolspec": "Nothing",
"thumb_toolspec": "Nothing",
"armeb_toolspec": "Nothing",
"x86_toolspec": "Nothing",
"k1om_toolspec": "Nothing",
"cache_dir": "\"%s\"" % os.path.expanduser("~/.cache/barrelfish/"),
"hagfish_location" : "\"%s\"" % siteconfig.get('HAGFISH_LOCATION')
}
return default_config
def _write_hake_conf(self, srcdir, archs):
# create hake dir
hakedir = os.path.join(self.build_dir, 'hake')
if not os.path.isdir(hakedir):
os.mkdir(hakedir)
# read default config template
with open(os.path.join(srcdir, 'hake', 'Config.hs.template')) as fh:
conf_template = fh.readlines()
# if srcdir is relative, adjust to be wrt build_dir
if os.path.isabs(srcdir):
rel_srcdir = srcdir
else:
rel_srcdir = os.path.relpath(srcdir, self.build_dir)
# get custom configuration options as a dictionary
conf = self._get_hake_conf(rel_srcdir, archs)
# create a new config file: template and then local options
newconf = []
for line in conf_template:
# XXX: exclude options from the defaults that are set locally
# where is the haskell parsing library for python? :)
if any([line.startswith(k) and re.match(' +=', line[len(k):])
for k in conf.keys()]):
line = '-- ' + line
newconf.append(line)
newconf.extend(['\n', '\n', '-- Added by test harness:\n'])
for item in conf.items():
newconf.append("%s = %s\n" % item)
# write it, only if it's different or the old one doesn't exist
try:
with open(os.path.join(hakedir, 'Config.hs'), 'r') as fh:
if fh.readlines() == newconf:
return # identical files
except IOError:
pass
with open(os.path.join(hakedir, 'Config.hs'), 'w') as fh:
fh.writelines(newconf)
def configure(self, checkout, archs):
srcdir = checkout.get_base_dir()
environ = dict(os.environ)
if "k1om" in archs :
environ['PATH'] = environ['PATH'] + MPSS_LINUX_PATH
self._make_build_dir()
self._write_hake_conf(srcdir, archs)
self._run_hake(srcdir, archs)
# this should be a nop -- building it here causes us to stop early
# with any tool or dependency-generation errors before doing test setup
self.build(["Makefile"], env=environ)
@staticmethod
def split_env(e):
def split_reduce_env(state, c):
if not state[0] and c == '\\':
return True, state[1]
elif not state[0] and c.isspace():
state[1].append('')
elif state[0]:
ec = '\\'+c
s = ec.decode('string_escape')
if s == ec:
# decode had no effect, just drop backslash
s = c
state[1][-1] += s
else:
state[1][-1] += c
return False, state[1]
e = e.lstrip()
e = reduce(split_reduce_env, e, (False, ['']))[1]
e = filter(bool, e)
return e
def build(self, targets, **kwargs):
makeopts = self.split_env(os.environ.get('MAKEOPTS', ''))
debug.checkcmd(["make"] + makeopts + targets, cwd=self.build_dir, **kwargs)
def install(self, targets, path):
debug.checkcmd(["make", "install",
"INSTALL_PREFIX=%s" % path,
"MODULES=%s" % (" ".join(targets))],
cwd=self.build_dir)
class HakeReleaseBuild(HakeBuildBase):
"""Release build (optimisations, no debug information)"""
name = 'release'
def _get_hake_conf(self, *args):
conf = super(HakeReleaseBuild, self)._get_hake_conf(*args)
conf["cOptFlags"] = "[\"-O2\", \"-DNDEBUG\", \"-Wno-unused-variable\"]"
return conf
class HakeTestBuild(HakeBuildBase):
"""Test build (optimisations, no debug symbols, but assertions enabled)"""
name = 'test'
def _get_hake_conf(self, *args):
conf = super(HakeTestBuild, self)._get_hake_conf(*args)
conf["cOptFlags"] = "[\"-O2\"]"
return conf
class HakeReleaseTraceBuild(HakeBuildBase):
"""optimisations, no debug information, and tracing """
name = 'release_trace'
def _get_hake_conf(self, *args):
conf = super(HakeReleaseBuild, self)._get_hake_conf(*args)
conf["cOptFlags"] = "[\"-O2\", \"-DNDEBUG\"]"
conf["trace"] = "True"
return conf
class HakeTestMdbInvariantsBuild(HakeTestBuild):
"""optimisations, no debug symbols, assertions and MDB invariant checking enabled"""
name = 'test_mdbinvariants'
def _get_hake_conf(self, *args):
conf = super(HakeTestMdbInvariantsBuild, self)._get_hake_conf(*args)
conf["mdb_check_invariants"] = "True"
return conf
class HakeDebugBuild(HakeBuildBase):
"""Default Hake build: debug symbols, optimisations, assertions"""
name = 'debug'
def _get_hake_conf(self, *args):
conf = super(HakeDebugBuild, self)._get_hake_conf(*args)
conf["cOptFlags"] = "[\"-O2\", \"-g\"]"
return conf
class HakeDebugTraceBuild(HakeBuildBase):
"""debug symbols, optimisations, assertions, and tracing"""
name = 'debug_trace'
def _get_hake_conf(self, *args):
conf = super(HakeDebugTraceBuild, self)._get_hake_conf(*args)
conf["cOptFlags"] = "[\"-O2\"]"
conf["trace"] = "True"
return conf
all_builds = [HakeReleaseBuild, HakeTestBuild, HakeDebugBuild, HakeReleaseTraceBuild,
HakeTestMdbInvariantsBuild, HakeDebugTraceBuild]
class ExistingBuild(HakeBuildBase):
'''Dummy build class for an existing Hake build dir.'''
name = 'existing'
def __init__(self, options, build_dir):
super(ExistingBuild, self).__init__(options)
debug.verbose('using existing build directory %s' % build_dir)
self.build_dir = build_dir
def configure(self, *args):
pass
def existingbuild(*args):
"""construct the build class for an existing build"""
return ExistingBuild(*args)