#! /usr/bin/env python3 # Invoke sparse based on the contents of compile_commands.json, # also working around several deficiencies in cgcc's command line # parsing import json import subprocess import os import sys import shlex def cmdline_for_sparse(sparse, cmdline): # Do not include the C compiler executable skip = True arg = False out = sparse + ['-no-compile'] for x in cmdline: if arg: out.append(x) arg = False continue if skip: skip = False continue # prevent sparse from treating output files as inputs if x == '-MF' or x == '-MQ' or x == '-o': skip = True continue # cgcc ignores -no-compile if it sees -M or -MM? if x.startswith('-M'): continue # sparse does not understand these! if x == '-iquote' or x == '-isystem': x = '-I' if x == '-I': arg = True out.append(x) return out root_path = os.getenv('MESON_BUILD_ROOT') def build_path(s): return s if not root_path else os.path.join(root_path, s) ccjson_path = build_path(sys.argv[1]) with open(ccjson_path, 'r') as fd: compile_commands = json.load(fd) sparse = sys.argv[2:] sparse_env = os.environ.copy() for cmd in compile_commands: cmdline = shlex.split(cmd['command']) cmd = cmdline_for_sparse(sparse, cmdline) print('REAL_CC=%s' % shlex.quote(cmdline[0]), ' '.join((shlex.quote(x) for x in cmd))) sparse_env['REAL_CC'] = cmdline[0] r = subprocess.run(cmd, env=sparse_env, cwd=root_path) if r.returncode != 0: sys.exit(r.returncode)