Generating Clang Compilation Databases on OpenBSD

Clang compilation databases are a really useful feature if you’re a Vim user and have a code linting plugin like coc. On my OpenBSD workstation, I use NeoVim and the aforementioned plugin, so I needed a way to generate the json files that clangd uses. There are some nice tools in the Linux world that do this for you, but (as usual) they don’t support BSDs and frankly I think they’re overengineered.

In the UNIX spirit, here’s a quick script that I wrote for a project to generate the files needed by clangd. This script assumes that all your .c files live in $PROJECT_ROOT/src. When using the clang compiler to generate these files, they spit out a 1:1 match of json files to source files. Thankfully, a little sed solves that problem.

#!/usr/bin/env sh

set -e

CFLAGS="-I./include -I/usr/local/include"

rm -f compile_commands.json

for f in $(find ./src -type f); do
  n=$(echo $f | grep -o '[^/]*$' | sed 's/c$/json/')
  cc -MJ $n $CFLAGS -c $f

rm *.o
sed -e '1s/^/[/' -e '$s/,$/]/' *.json > compile_commands.out
rm *.json
mv compile_commands.out compile_commands.json

There is a much easier way to solve this problem if you’re willing to go the Cmake route, which is what I’ve come around to these days. I could write a long diatribe on Cmake, but the short version is that it used to be really bad, but these days it’s pretty good. I like to provide a Makefile that sets up and runs Cmake, and let Cmake handle the actual hard part.

Here’s the template Makefile that I use for any C project. The actual project configuration is then done in CMakeLists.txt


        mkdir -p build
        cd build &&     \
                cmake ${CMAKE_OPTS} .. &&       \
                make && \
                cp compile_commands.json ..

        rm -rf build
        rm -f compile_commands.json