#!/usr/bin/env sh # Generate compile_commands.json for clangd. # # Uses bear when available so every real compile command is captured # (future-proof as the project grows). Otherwise hand-rolls the single # entry from the flags in the generated Makefile — one source file, one # entry, no mysteries. set -eu ROOT=$(cd "$(dirname "$0")/.." && pwd) cd "$ROOT" if [ ! -f Makefile ]; then echo "gen-compile-commands: no Makefile found - run ./autogen.sh first" >&2 exit 1 fi if command -v bear >/dev/null 2>&1; then bear -- make -B >/dev/null # Drop the configure probes (conftest.c); clangd only wants real files. jq 'map(select(.file | endswith("conftest.c") | not))' compile_commands.json \ > compile_commands.json.tmp && mv compile_commands.json.tmp compile_commands.json echo "compile_commands.json generated via bear" exit 0 fi CC=$(sed -n 's/^CC = //p' Makefile | head -n1) [ -z "$CC" ] && CC=cc DEFS=$(sed -n 's/^DEFS = //p' Makefile | head -n1) AM_CFLAGS=$(sed -n 's/^AM_CFLAGS = //p' Makefile | head -n1) CFLAGS=$(sed -n 's/^CFLAGS = //p' Makefile | head -n1) # Drop defines carrying embedded quotes (PACKAGE_* metadata): they would # break JSON and clangd does not need them. SAFE_DEFS='' for d in $DEFS; do case "$d" in *\"*) ;; *) SAFE_DEFS="$SAFE_DEFS $d" ;; esac done CMD="$CC$SAFE_DEFS -I. $AM_CFLAGS $CFLAGS -c src/main.c -o src/main.o" if command -v jq >/dev/null 2>&1; then jq -n --arg d "$ROOT" --arg c "$CMD" --arg f "$ROOT/src/main.c" \ '[{directory: $d, command: $c, file: $f}]' > compile_commands.json else printf '[{"directory":"%s","command":"%s","file":"%s"}]\n' \ "$ROOT" "$CMD" "$ROOT/src/main.c" > compile_commands.json fi echo "compile_commands.json generated (fallback)"