1968b4db3SPaolo Bonzini#! /usr/bin/env python3 2968b4db3SPaolo Bonzini 3*deb62371SPaolo Bonzini# Invoke sparse based on the contents of compile_commands.json, 4*deb62371SPaolo Bonzini# also working around several deficiencies in cgcc's command line 5*deb62371SPaolo Bonzini# parsing 6968b4db3SPaolo Bonzini 7968b4db3SPaolo Bonziniimport json 8968b4db3SPaolo Bonziniimport subprocess 9*deb62371SPaolo Bonziniimport os 10968b4db3SPaolo Bonziniimport sys 11968b4db3SPaolo Bonziniimport shlex 12968b4db3SPaolo Bonzini 13*deb62371SPaolo Bonzinidef cmdline_for_sparse(sparse, cmdline): 14*deb62371SPaolo Bonzini # Do not include the C compiler executable 15*deb62371SPaolo Bonzini skip = True 16*deb62371SPaolo Bonzini arg = False 17*deb62371SPaolo Bonzini out = sparse + ['-no-compile'] 18*deb62371SPaolo Bonzini for x in cmdline: 19*deb62371SPaolo Bonzini if arg: 20*deb62371SPaolo Bonzini out.append(x) 21*deb62371SPaolo Bonzini arg = False 22*deb62371SPaolo Bonzini continue 23*deb62371SPaolo Bonzini if skip: 24*deb62371SPaolo Bonzini skip = False 25*deb62371SPaolo Bonzini continue 26*deb62371SPaolo Bonzini # prevent sparse from treating output files as inputs 27*deb62371SPaolo Bonzini if x == '-MF' or x == '-MQ' or x == '-o': 28*deb62371SPaolo Bonzini skip = True 29*deb62371SPaolo Bonzini continue 30*deb62371SPaolo Bonzini # cgcc ignores -no-compile if it sees -M or -MM? 31*deb62371SPaolo Bonzini if x.startswith('-M'): 32*deb62371SPaolo Bonzini continue 33*deb62371SPaolo Bonzini # sparse does not understand these! 34*deb62371SPaolo Bonzini if x == '-iquote' or x == '-isystem': 35*deb62371SPaolo Bonzini x = '-I' 36*deb62371SPaolo Bonzini if x == '-I': 37*deb62371SPaolo Bonzini arg = True 38*deb62371SPaolo Bonzini out.append(x) 39*deb62371SPaolo Bonzini return out 40968b4db3SPaolo Bonzini 41*deb62371SPaolo Bonziniroot_path = os.getenv('MESON_BUILD_ROOT') 42*deb62371SPaolo Bonzinidef build_path(s): 43*deb62371SPaolo Bonzini return s if not root_path else os.path.join(root_path, s) 44*deb62371SPaolo Bonzini 45*deb62371SPaolo Bonziniccjson_path = build_path(sys.argv[1]) 46*deb62371SPaolo Bonziniwith open(ccjson_path, 'r') as fd: 47968b4db3SPaolo Bonzini compile_commands = json.load(fd) 48968b4db3SPaolo Bonzini 49*deb62371SPaolo Bonzinisparse = sys.argv[2:] 50*deb62371SPaolo Bonzinisparse_env = os.environ.copy() 51968b4db3SPaolo Bonzinifor cmd in compile_commands: 52*deb62371SPaolo Bonzini cmdline = shlex.split(cmd['command']) 53*deb62371SPaolo Bonzini cmd = cmdline_for_sparse(sparse, cmdline) 54*deb62371SPaolo Bonzini print('REAL_CC=%s' % shlex.quote(cmdline[0]), 55*deb62371SPaolo Bonzini ' '.join((shlex.quote(x) for x in cmd))) 56*deb62371SPaolo Bonzini sparse_env['REAL_CC'] = cmdline[0] 57*deb62371SPaolo Bonzini r = subprocess.run(cmd, env=sparse_env, cwd=root_path) 58968b4db3SPaolo Bonzini if r.returncode != 0: 59968b4db3SPaolo Bonzini sys.exit(r.returncode) 60