Skip to content

Instantly share code, notes, and snippets.

@gtors
Created December 10, 2018 12:57
Show Gist options
  • Star 26 You must be signed in to star a gist
  • Fork 4 You must be signed in to fork a gist
  • Save gtors/effe8eef7dbe7052b22a009f3c7fc434 to your computer and use it in GitHub Desktop.
Save gtors/effe8eef7dbe7052b22a009f3c7fc434 to your computer and use it in GitHub Desktop.
Makefile -> compilation_commands.json

Guillaume Papin(@Sarcasm) has a thorough article about compilation databases.

% mkdir build
% (cd build; cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=YES ..)
% ln -s build/compile_commands.json

Caveat on Windows: CMake dumps Windows shell command line directly into command, depends on how ccls was built, it may confuse this field as command line from a POSIX shell, in which Windows path separator '\' is a escape character. You can use jq to convert such entries to use arguments which does not have this issue:

jq '[.[] | {directory: .directory, file: .file, arguments: .command | split(" ") | map(select(length > 0)) | map(sub("\\\\\""; "\""; "g"))}]' < compile_commands.json

Bear is a tool that generates a compilation database for clang tooling. It can be used for any project based on Makefile.

bear make
# generates compile_commands.json

scan-build is a python package that can generate a compilation database for clang tooling (uses Bear as a backend). This too can be used for any project based on a Makefile.

intercept-build make all # generates compile_commands.json from the `make all` ruleset
# Format: ninja -t compdb rule_names... > compile_commands.json
ninja -C out/Release -t compdb cxx cc > compile_commands.json

Load the clang_compilation_database tool in your wscript:

def configure(conf):
    conf.load('clang_compilation_database')
./waf configure build
ln -s build/compile_commands.json
buck build :helloworld#compilation-database
ln -s $(buck targets --show-output :helloworld#compilation-database | cut -d ' ' -f 2)

stdout of an external command

You may use the initialization option "compilationDatabaseCommand" to provide the JSON compilation database. ccls will read its stdout rather than read compile_commands.json. This may be useful when ccls cannot parse the compile_commands.json correctly (e.g. MSVC cl.exe, Intel C++ Compiler options)

# extra command line option
'--init={"compilationDatabaseCommand":"mycompdb"}'
(setq ccls-extra-init-params '(:compilationDatabaseCommand "mycompdb"))

Suppose the project is at /tmp/c, mycompdb /tmp/c will be executed with stdin=initializationOptions and the stdout should be a JSON compilation database.

You may use this shell script as a starting point:

#!/bin/zsh
# mycompdb /tmp/c
cat >> /tmp/initialization-options
cat <<e
[ { "arguments": [ "c++", "a.o", "a.cc" ],
    "directory": "/tmp/c", "file": "a.cc" } ]
e

An example to scrub Intel C++ Compiler options (or, even easier, check out clang.excludeArgs in the Initialization options):

#!/usr/bin/env python3
import json
import os
import sys
with open(os.path.join(sys.argv[1], 'compile_commands.json')) as f:
    db = json.load(f)
    for entry in db:
        args = entry['arguments']
        try:
            # Intel C++ Compiler option that is unknown to clang
            args.remove('-xHost')
        except ValueError:
            pass
    json.dump(db, sys.stdout)

Examples

Linux kernel

wget 'https://git.archlinux.org/svntogit/packages.git/plain/trunk/config?h=packages/linux' -O .config
yes '' | make config
bear make -j bzImage modules
ccls -index ~/Dev/Linux -init='{"clang":{"excludeArgs":[
"-falign-jumps=1","-falign-loops=1","-fconserve-stack","-fmerge-constants","-fno-code-hoisting","-fno-schedule-insns","-fno-sched-pressure","-fno-var-tracking-assignments","-fsched-pressure",
"-mhard-float","-mindirect-branch-register","-mindirect-branch=thunk-inline","-mpreferred-stack-boundary=2","-mpreferred-stack-boundary=3","-mpreferred-stack-boundary=4","-mrecord-mcount","-mindirect-branch=thunk-extern","-mno-fp-ret-in-387","-mskip-rax-setup",
"--param=allow-store-data-races=0","-Wa,arch/x86/kernel/macros.s","-Wa,-"
], "extraArgs":["--gcc-toolchain=/usr"]}}'

musl

mkdir Debug; cd Debug
../configure --enable-optimize=no --enable-debug --prefix=~/.local/stow/musl
bear make -j
cd ..; ln -s Debug/compile_commands.json

Misc

compile_commands.json should reside in the project root. Set the initialization option compilationDatabaseDirectory for an alternative directory containing compile_commands.json.

@ioperations
Copy link

linux kernel do have compile_commands.json support in master branch

@jhgorse
Copy link

jhgorse commented Jan 4, 2024

What about Makefiles for GCC toolset? compiledb option works fine.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment