sanity-external-toolchain.bbclass 3.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. TOOLCHAIN_SANITY_VERSION = "1"
  2. def check_toolchain_sanity(d, generate_events=False):
  3. import shlex
  4. import tempfile
  5. if not d.getVar('TCMODE', True).startswith('external'):
  6. return
  7. extpath = d.getVar('EXTERNAL_TOOLCHAIN', True)
  8. # Test 1: EXTERNAL_TOOLCHAIN exists
  9. if not os.path.exists(extpath):
  10. raise_exttc_sanity_error('EXTERNAL_TOOLCHAIN path `%s` does not exist' % extpath, d, generate_events)
  11. extpath = os.path.realpath(extpath)
  12. sanity_file = d.expand('${TOPDIR}/conf/exttc_sanity_info')
  13. version = d.getVar('TOOLCHAIN_SANITY_VERSION', True)
  14. check, config = should_run(sanity_file, {'version': version, 'path': extpath})
  15. if not check:
  16. return
  17. cfgdata = config['DEFAULT']
  18. # Test 2: EXTERNAL_TARGET_SYS is set correctly
  19. if d.getVar('EXTERNAL_TARGET_SYS', True) == 'UNKNOWN':
  20. raise_exttc_sanity_error('Unable to locate prefixed gcc binary for %s in EXTERNAL_TOOLCHAIN_BIN (%s)' % (d.getVar('TARGET_SYS', True), d.getVar('EXTERNAL_TOOLCHAIN_BIN', True)), d, generate_events)
  21. # Test 3: gcc binary exists
  22. gcc = d.expand('${EXTERNAL_TOOLCHAIN_BIN}/${EXTERNAL_TARGET_SYS}-gcc')
  23. if not os.path.exists(gcc):
  24. raise_exttc_sanity_error('Compiler path `%s` does not exist' % gcc, d, generate_events)
  25. # Test 4: we can run it to get the version
  26. cmd = d.expand('${EXTERNAL_TOOLCHAIN_BIN}/${EXTERNAL_CC} -dumpversion')
  27. sourcery_version = exttc_sanity_run(shlex.split(cmd), d, generate_events)
  28. if cfgdata.get('sourcery_version') == sourcery_version:
  29. return
  30. # Test 5: we can compile an empty test app
  31. with tempfile.TemporaryDirectory() as tmpdir:
  32. with open(os.path.join(tmpdir, 'test.c'), 'w') as f:
  33. f.write('int main() {}')
  34. # The external toolchain recipes haven't necessarily been built, so we
  35. # need to drop --sysroot= and --no-sysroot-suffix and use the bits in
  36. # the external toolchain sysroots for this test
  37. l = d.createCopy()
  38. l.setVar('TOOLCHAIN_OPTIONS', '')
  39. l.setVar('TARGET_PREFIX', '${EXTERNAL_TARGET_SYS}-')
  40. l.setVar('HOST_CC_ARCH:remove', '--no-sysroot-suffix')
  41. cmd = l.expand('${EXTERNAL_TOOLCHAIN_BIN}/${EXTERNAL_CC} ${HOST_CC_ARCH} ${CFLAGS} ${LDFLAGS} test.c -o test')
  42. exttc_sanity_run(shlex.split(cmd), d, generate_events, tmpdir)
  43. with open(sanity_file, 'w') as f:
  44. config.write(f)
  45. def should_run(cfgfile, expected):
  46. import configparser
  47. config = configparser.ConfigParser()
  48. readfiles = config.read(cfgfile)
  49. cfgdata = config['DEFAULT']
  50. if cfgfile in readfiles and cfgdata == expected:
  51. return False, None
  52. cfgdata.update(expected)
  53. return True, config
  54. def raise_exttc_sanity_error(msg, d, generate_events):
  55. msg = 'Sanity check of the external toolchain failed: ' + msg
  56. if generate_events:
  57. try:
  58. bb.event.fire(bb.event.SanityCheckFailed(msg, None), d)
  59. except TypeError:
  60. bb.event.fire(bb.event.SanityCheckFailed(msg), d)
  61. else:
  62. bb.fatal(msg)
  63. def exttc_sanity_run(cmd, d, generate_events, cwd='/'):
  64. import subprocess
  65. try:
  66. return subprocess.check_output(cmd, stderr=subprocess.STDOUT, cwd=cwd)
  67. except FileNotFoundError:
  68. raise_exttc_sanity_error('\n Command: %s\n Exit Code: 127\n Output: no such file or directory' % cmd, d, generate_events)
  69. except subprocess.CalledProcessError as exc:
  70. if not isinstance(cmd, str):
  71. cmd = subprocess.list2cmdline(cmd)
  72. output = exc.output.decode()
  73. output_indented = ''.join(' ' + l for l in output.splitlines(keepends=True))
  74. raise_exttc_sanity_error('\n Command: %s\n Exit code: %s\n Output:\n%s' % (cmd, exc.returncode, output_indented), d, generate_events)
  75. python toolchain_sanity_eventhandler() {
  76. check_toolchain_sanity(d, e.generateevents)
  77. }
  78. toolchain_sanity_eventhandler[eventmask] = "bb.event.SanityCheck"
  79. addhandler toolchain_sanity_eventhandler