If you have control over the build system, clang can generate that directly nowadays, by adding -MJ path to CFLAGS (or equiv). This will save JSON fragments to path (make'em separate for each compiled file), then you can concatenate all the fragments into a compilation database.
I use this approach because on macOS, with SIP, Bear no longer works as it is forbidden from injecting its hooks into the system-protected clang shim. There may be other solutions.
(I haven't explored the space in a few years. They've historically fared poorly with embedded targets where one file may be compiled many different ways for targeting different platforms)
One of the major problems approach with this is that you need to run the compile before you can generate this database.
How do you propose to generate the compilation database without compiling? I would really like that for the Linux kernel.
You really need build system support. For example, Ninja can generate the file without actually doing the build because it knows everything it _would_ do.
the compilation database is essential for editors these days, cmake can generate it directly but not all code use cmake, in that case I just use compiledb, which is inactive (there is a newer compiledb-go though), then use bear. somehow bear did not work well for me comparing to compiledb so compiledb(now compiledb-go) is my main tool now.
Just shilling a single-file almost POSIX sh script I made to do the same: https://git.sr.ht/~q3cpma/scripts/tree/master/item/mkcdb