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.

Here’s a script that I wrote for a recent project that generates the compilation database files. This script assumes that all your .c files live in $PROJECT_ROOT/src, tweak the find(1) usage as necessary. 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
done

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

CMAKE_OPTS=-DCMAKE_EXPORT_COMPILE_COMMANDS=1

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

clean:
        rm -rf build
        rm -f compile_commands.json

burkey.co


2023-10-31