Merge pull request #146 from kergoth/sourcery-sanity

Revamp the sanity testing
This commit is contained in:
Christopher Larson
2016-11-03 13:51:04 -07:00
committed by GitHub
2 changed files with 98 additions and 29 deletions

View File

@@ -0,0 +1,94 @@
TOOLCHAIN_SANITY_VERSION = "1"
def check_toolchain_sanity(d, generate_events=False):
import shlex
import tempfile
if not d.getVar('TCMODE', True).startswith('external'):
return
extpath = d.getVar('EXTERNAL_TOOLCHAIN', True)
# Test 1: EXTERNAL_TOOLCHAIN exists
if not os.path.exists(extpath):
raise_exttc_sanity_error('EXTERNAL_TOOLCHAIN path `%s` does not exist' % extdir, d, generate_events)
extpath = os.path.realpath(extpath)
sanity_file = d.expand('${TOPDIR}/conf/exttc_sanity_info')
version = d.getVar('TOOLCHAIN_SANITY_VERSION', True)
check, config = should_run(sanity_file, {'version': version, 'path': extpath})
if not check:
return
cfgdata = config['DEFAULT']
# Test 2: EXTERNAL_TARGET_SYS is set correctly
if d.getVar('EXTERNAL_TARGET_SYS', True) == 'UNKNOWN':
raise_exttc_sanity_error('Unable to locate prefixed gcc binary for %s in EXTERNAL_TOOLCHAIN/bin (%s/bin)' % (d.getVar('TARGET_SYS', True), d.getVar('EXTERNAL_TOOLCHAIN', True)), d, generate_events)
# Test 3: gcc binary exists
gcc = d.expand('${EXTERNAL_TOOLCHAIN}/bin/${TARGET_PREFIX}gcc')
if not os.path.exists(gcc):
raise_exttc_sanity_error('Compiler path `%s` does not exist' % gcc, d, generate_events)
# Test 4: we can run it to get the version
cmd = d.expand('${EXTERNAL_TOOLCHAIN}/bin/${TARGET_PREFIX}gcc -dumpversion')
sourcery_version = exttc_sanity_run(shlex.split(cmd), d, generate_events)
if cfgdata.get('sourcery_version') == sourcery_version:
return
# Test 5: we can compile an empty test app
with tempfile.TemporaryDirectory() as tmpdir:
with open(os.path.join(tmpdir, 'test.c'), 'w') as f:
f.write('int main() {}')
# The external toolchain recipes haven't necessarily been built, so we
# need to drop --sysroot= and --no-sysroot-suffix and use the bits in
# the external toolchain sysroots for this test
l = d.createCopy()
l.setVar('TOOLCHAIN_OPTIONS', '')
l.setVar('HOST_CC_ARCH_remove', '--no-sysroot-suffix')
cmd = l.expand('${EXTERNAL_TOOLCHAIN}/bin/${CC} ${CFLAGS} ${LDFLAGS} test.c -o test')
exttc_sanity_run(shlex.split(cmd), d, generate_events, tmpdir)
with open(sanity_file, 'w') as f:
config.write(f)
def should_run(cfgfile, expected):
import configparser
config = configparser.ConfigParser()
readfiles = config.read(cfgfile)
cfgdata = config['DEFAULT']
if cfgfile in readfiles and cfgdata == expected:
return False, None
cfgdata.update(expected)
return True, config
def raise_exttc_sanity_error(msg, d, generate_events):
msg = 'Sanity check of the external toolchain failed: ' + msg
if generate_events:
try:
bb.event.fire(bb.event.SanityCheckFailed(msg, None), d)
except TypeError:
bb.event.fire(bb.event.SanityCheckFailed(msg), d)
else:
bb.fatal(msg)
def exttc_sanity_run(cmd, d, generate_events, cwd='/'):
import subprocess
try:
return subprocess.check_output(cmd, stderr=subprocess.STDOUT, cwd=cwd)
except subprocess.CalledProcessError as exc:
if not isinstance(cmd, str):
cmd = subprocess.list2cmdline(cmd)
output = exc.output.decode()
output_indented = ''.join(' ' + l for l in output.splitlines(keepends=True))
raise_exttc_sanity_error('\n Command: %s\n Exit code: %s\n Output:\n%s' % (cmd, exc.returncode, output_indented), d, generate_events)
python toolchain_sanity_eventhandler() {
check_toolchain_sanity(d, e.generateevents)
}
toolchain_sanity_eventhandler[eventmask] = "bb.event.SanityCheck"
addhandler toolchain_sanity_eventhandler

View File

@@ -56,6 +56,9 @@ PREFERRED_PROVIDER_linux-libc-headers = "linux-libc-headers-external"
# Support use of an external toolchain with the SDK/ADE/etc
TOOLCHAIN_TARGET_TASK_append = " sdk-env-external-toolchain"
# Sanity check the toolchain configuration and toolchain
INHERIT += "sanity-external-toolchain"
# Pull in our utility functions for use elsewhere
INHERIT += "external-common"
@@ -180,7 +183,7 @@ python toolchain_metadata_setup () {
with tempfile.NamedTemporaryFile(suffix='.c') as f:
try:
subprocess.check_output([d.expand('${EXTERNAL_TOOLCHAIN}/bin/${EXTERNAL_TARGET_SYS}-gcc'), '-msgxx-glibc', '-E', f.name], stderr=subprocess.STDOUT, env=testenv, cwd=d.getVar('TOPDIR', True))
subprocess.check_output([d.expand('${EXTERNAL_TOOLCHAIN}/bin/${TARGET_PREFIX}gcc'), '-msgxx-glibc', '-E', f.name], stderr=subprocess.STDOUT, env=testenv, cwd=d.getVar('TOPDIR', True))
except (OSError, subprocess.CalledProcessError):
pass
else:
@@ -256,34 +259,6 @@ def set_vars_from_toolchains(codebench_path, d):
d.setVar('EXTERNAL_TARGET_SYS', triplets[0])
d.setVar('EXTERNAL_TOOLCHAIN', os.path.join(toolchains_path, toolchain_subdir))
python toolchain_sanity_check () {
d = e.data
external_toolchain = d.getVar('EXTERNAL_TOOLCHAIN', True)
if not external_toolchain or external_toolchain == 'UNDEFINED':
bb.fatal("EXTERNAL_TOOLCHAIN must be set to the path to your sourcery toolchain")
if not os.path.exists(external_toolchain):
bb.fatal("EXTERNAL_TOOLCHAIN is invalid: path '%s' does not exist" % external_toolchain)
bindir = os.path.join(external_toolchain, 'bin')
if not os.path.exists(bindir):
bb.fatal("EXTERNAL_TOOLCHAIN is invalid: path '%s' does not exist" % bindir)
if d.getVar('EXTERNAL_TARGET_SYS', True) == 'UNKNOWN':
bb.fatal('Unable to locate prefixed gcc binary for %s in EXTERNAL_TOOLCHAIN/bin (%s/bin)' % (d.getVar('TARGET_SYS', True), d.getVar('EXTERNAL_TOOLCHAIN', True)))
if d.getVar('GCC_VERSION', True) == 'UNKNOWN':
bb.warn("EXTERNAL_TOOLCHAIN gcc version extraction failed, see debug messages for details")
}
# This runs at TreeDataPreparationStarted time, as we want bitbake -e to work,
# so it has to run after ConfigParsed, and we want to see these errors rather
# than the highly verbose unbuildable -external recipe errors which occur when
# generating the runqueue, so we need to run before BuildStarted.
toolchain_sanity_check[eventmask] = "bb.event.TreeDataPreparationStarted"
addhandler toolchain_sanity_check
GCCVERSION ?= "${@'.'.join('${GCC_VERSION}'.split('.')[:2])}%"
GCC_VERSION = "${@external_run(d, 'gcc', '-dumpversion').rstrip()}"
GCC_VERSION_allarch = ""