Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Generating compile_commands.json for clang-tidy #1755

Open
honggyukim opened this issue Jul 9, 2023 · 1 comment
Open

Generating compile_commands.json for clang-tidy #1755

honggyukim opened this issue Jul 9, 2023 · 1 comment
Labels

Comments

@honggyukim
Copy link
Collaborator

honggyukim commented Jul 9, 2023

Recent analysis tools benefits from compile_commands.json.

Having the compile_commands.json gives some chances of sophisticated static analysis such as using clang-tidy.

The compile_commands.json can easily be generated by modern build systems such as cmake and meson, but we use simple make build system so we do not have a way to generate the compile_commands.json.

I have prepared a simple script that generating compile_commands.json based on our build output.

It needs to be refactored more, but the simple script looks as follows.

$ cat gen-compile-commands.py
#!/usr/bin/env python

import os
import subprocess as sp
import sys

def do_dry_make():
    make_cmds = 'make V=1 --dry-run'
    with sp.Popen(make_cmds.split(), stdout=sp.PIPE) as p:
        lines = p.communicate()[0].decode(errors='ignore').split('\n')
        return lines

def main():
    if not os.path.exists('Makefile'):
        print('error: Makefile not found.')
        return -1

    with open('compile_commands.json', 'w') as f:
        f.write('[')
        needs_comma = False
        directory = os.getcwd()
        lines = do_dry_make()
        for line in lines:
            command = line
            if command[:3] != 'gcc' and command[:5] != 'clang':
                # We're only interested in compilation commands
                # so skip otherwise.
                continue
            file = ''
            words = command.split()
            for word in words:
                if word[-2:] == '.c':
                    file = word
            if file == '':
                continue
            if 'libtraceevent' in file:
                continue
            command = command.replace('"', '\\"')

            if needs_comma:
                f.write(',')
            f.write('\n{\n')
            f.write('  "directory": "%s",\n' % directory)
            f.write('  "command": "%s",\n' % command)
            f.write('  "file": "%s"\n' % file)
            f.write('}')
            needs_comma = True

        f.write('\n]\n')

if __name__ == '__main__':
    sys.exit(main())

The usage is as follows.

$ make clean

$ make V=1 | tee build.log

$ ./gen-compile-commands.py 

$ wc -l compile_commands.json 
587 compile_commands.json

We can run clang-tidy as follows.

$ run-clang-tidy
(... it shows many warnings ...)
@honggyukim honggyukim added the RFC label Jul 9, 2023
@honggyukim
Copy link
Collaborator Author

It's related to #1756.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant