Skip to content

Instantly share code, notes, and snippets.

@fwyzard
Last active November 1, 2016 05:29
Show Gist options
  • Save fwyzard/727563d5fe7ebfb084f40392bdad019d to your computer and use it in GitHub Desktop.
Save fwyzard/727563d5fe7ebfb084f40392bdad019d to your computer and use it in GitHub Desktop.
Python tool to add entries to an LLVM compilation database
#! /usr/bin/env python
import sys
import os
import fcntl
import argparse
import json
# the default location for the compilation database is the file 'compile_commands.json' in the current directory
def_dbname = 'compile_commands.json'
# arguments and options
parser = argparse.ArgumentParser(
description = '''Add an entry to an LLVM Compilation Database.
See http://clang.llvm.org/docs/JSONCompilationDatabase.html for details.''')
parser.add_argument('--path', '-p',
metavar = 'PATH',
dest = 'dbname',
default = def_dbname,
help = '''path to the compilation database (directory or json file).
PATH can be a file or directory; if it is a directory, PATH/compile_commands.json will be used.
The default is to use the file "compile_commands.json" in the current directory.''')
parser.add_argument('--replace', '-r',
action = 'store_true',
default = False,
help = 'replace any existing record with the same FILE entry. The default is to allow duplicates with a different COMMAND or DIRECTORY.')
parser.add_argument('--directory', '-d',
metavar = 'DIRECTORY',
default = os.getcwd(),
help = 'set the "directory" entry for the new record. The default is the current directory.')
parser.add_argument('file',
metavar = 'FILE',
help = 'set the "file" entry for the new record')
parser.add_argument('command',
metavar = 'COMMAND',
help = 'set the "command" entry for the new record')
args = parser.parse_args()
# open the file for read/append, so it is not truncated
dbname = args.dbname
if os.path.isdir(dbname):
dbname = os.path.join(dbname, def_dbname)
dbfile = open(dbname, 'a+')
# acquire an advisory exclusive lock on the file
fcntl.flock(dbfile, fcntl.LOCK_EX)
# read the content of the file
dbfile.seek(0)
dbjson = dbfile.read()
try:
dbdata = json.loads(dbjson)
except ValueError as e:
# if the file is empty or the content s not valid json, start from an empty database
dbdata = []
# add the new record, if not present already
record = { 'directory': args.directory, 'file': args.file, 'command': args.command }
if args.replace:
for r in list(dbdata):
if r['file'] == record['file']:
dbdata.remove(r)
dbdata.append(record)
else:
if not record in dbdata:
dbdata.append(record)
# truncate the file and replace its content
dbfile.seek(0)
dbfile.truncate()
dbfile.write(json.dumps(dbdata, indent=2, separators=(',', ': ')))
dbfile.write('\n')
# the lock is automatically release when the file is closed
dbfile.close()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment