2
0

check_sparse.py 1.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859
  1. #! /usr/bin/env python3
  2. # Invoke sparse based on the contents of compile_commands.json,
  3. # also working around several deficiencies in cgcc's command line
  4. # parsing
  5. import json
  6. import subprocess
  7. import os
  8. import sys
  9. import shlex
  10. def cmdline_for_sparse(sparse, cmdline):
  11. # Do not include the C compiler executable
  12. skip = True
  13. arg = False
  14. out = sparse + ['-no-compile']
  15. for x in cmdline:
  16. if arg:
  17. out.append(x)
  18. arg = False
  19. continue
  20. if skip:
  21. skip = False
  22. continue
  23. # prevent sparse from treating output files as inputs
  24. if x == '-MF' or x == '-MQ' or x == '-o':
  25. skip = True
  26. continue
  27. # cgcc ignores -no-compile if it sees -M or -MM?
  28. if x.startswith('-M'):
  29. continue
  30. # sparse does not understand these!
  31. if x == '-iquote' or x == '-isystem':
  32. x = '-I'
  33. if x == '-I':
  34. arg = True
  35. out.append(x)
  36. return out
  37. root_path = os.getenv('MESON_BUILD_ROOT')
  38. def build_path(s):
  39. return s if not root_path else os.path.join(root_path, s)
  40. ccjson_path = build_path(sys.argv[1])
  41. with open(ccjson_path, 'r') as fd:
  42. compile_commands = json.load(fd)
  43. sparse = sys.argv[2:]
  44. sparse_env = os.environ.copy()
  45. for cmd in compile_commands:
  46. cmdline = shlex.split(cmd['command'])
  47. cmd = cmdline_for_sparse(sparse, cmdline)
  48. print('REAL_CC=%s' % shlex.quote(cmdline[0]),
  49. ' '.join((shlex.quote(x) for x in cmd)))
  50. sparse_env['REAL_CC'] = cmdline[0]
  51. r = subprocess.run(cmd, env=sparse_env, cwd=root_path)
  52. if r.returncode != 0:
  53. sys.exit(r.returncode)