Browse Source

Makefile: add support for generating JSON compilation database

Tools based on LibClang [1] can make use of a 'JSON Compilation
Database' [2] that keeps track of the exact options used to compile a set
of source files.

For example, clangd [3], which is a C language server protocol
implementation, can use a JSON compilation database to determine the
flags needed to compile a file so it can provide proper editor
integration.  As a result, editors supporting the language server
protocol (such as VS Code, Emacs, or Vim, with suitable plugins) can
provide better searching, integration, and refactoring tools.

The Clang compiler can generate JSON fragments when compiling [4],
using the `-MJ` flag. These JSON fragments (one per compiled source
file) can then be concatenated to create the compilation database,
commonly called 'compile_commands.json'.

Add support to the Makefile for generating these JSON fragments as well
as the compilation database itself, if the environment variable
'GENERATE_COMPILATION_DATABASE' is set.

If this variable is set, check that $(CC) indeed supports the `-MJ`
flag, following what is done for automatic dependencies.

All JSON fragments are placed in the 'compile_commands/' directory, and
the compilation database 'compile_commands.json' is generated as a
dependency of the 'all' target using a `sed` invocation.

[1] https://clang.llvm.org/docs/Tooling.html
[2] https://clang.llvm.org/docs/JSONCompilationDatabase.html
[3] https://clangd.llvm.org/
[4] https://clang.llvm.org/docs/ClangCommandLineReference.html#cmdoption-clang-mj-arg

Helped-by: brian m. carlson <sandals@crustytoothpaste.net>
Signed-off-by: Philippe Blain <levraiphilippeblain@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
maint
Philippe Blain 4 years ago committed by Junio C Hamano
parent
commit
3821c38068
  1. 2
      .gitignore
  2. 59
      Makefile

2
.gitignore vendored

@ -197,6 +197,7 @@
/git.spec /git.spec
*.exe *.exe
*.[aos] *.[aos]
*.o.json
*.py[co] *.py[co]
.depend/ .depend/
*.gcda *.gcda
@ -218,6 +219,7 @@
/tags /tags
/TAGS /TAGS
/cscope* /cscope*
/compile_commands.json
*.hcc *.hcc
*.obj *.obj
*.lib *.lib

59
Makefile

@ -462,6 +462,12 @@ all::
# the global variable _wpgmptr containing the absolute path of the current # the global variable _wpgmptr containing the absolute path of the current
# executable (this is the case on Windows). # executable (this is the case on Windows).
# #
# Define GENERATE_COMPILATION_DATABASE to "yes" to generate JSON compilation
# database entries during compilation if your compiler supports it, using the
# `-MJ` flag. The JSON entries will be placed in the `compile_commands/`
# directory, and the JSON compilation database 'compile_commands.json' will be
# created at the root of the repository.
#
# Define DEVELOPER to enable more compiler warnings. Compiler version # Define DEVELOPER to enable more compiler warnings. Compiler version
# and family are auto detected, but could be overridden by defining # and family are auto detected, but could be overridden by defining
# COMPILER_FEATURES (see config.mak.dev). You can still set # COMPILER_FEATURES (see config.mak.dev). You can still set
@ -1258,6 +1264,27 @@ $(error please set COMPUTE_HEADER_DEPENDENCIES to yes, no, or auto \
endif endif
endif endif


ifndef GENERATE_COMPILATION_DATABASE
GENERATE_COMPILATION_DATABASE = no
endif

ifeq ($(GENERATE_COMPILATION_DATABASE),yes)
compdb_check = $(shell $(CC) $(ALL_CFLAGS) \
-c -MJ /dev/null \
-x c /dev/null -o /dev/null 2>&1; \
echo $$?)
ifneq ($(compdb_check),0)
override GENERATE_COMPILATION_DATABASE = no
$(warning GENERATE_COMPILATION_DATABASE is set to "yes", but your compiler does not \
support generating compilation database entries)
endif
else
ifneq ($(GENERATE_COMPILATION_DATABASE),no)
$(error please set GENERATE_COMPILATION_DATABASE to "yes" or "no" \
(not "$(GENERATE_COMPILATION_DATABASE)"))
endif
endif

ifdef SANE_TOOL_PATH ifdef SANE_TOOL_PATH
SANE_TOOL_PATH_SQ = $(subst ','\'',$(SANE_TOOL_PATH)) SANE_TOOL_PATH_SQ = $(subst ','\'',$(SANE_TOOL_PATH))
BROKEN_PATH_FIX = 's|^\# @@BROKEN_PATH_FIX@@$$|git_broken_path_fix "$(SANE_TOOL_PATH_SQ)"|' BROKEN_PATH_FIX = 's|^\# @@BROKEN_PATH_FIX@@$$|git_broken_path_fix "$(SANE_TOOL_PATH_SQ)"|'
@ -2381,16 +2408,30 @@ missing_dep_dirs =
dep_args = dep_args =
endif endif


compdb_dir = compile_commands

ifeq ($(GENERATE_COMPILATION_DATABASE),yes)
missing_compdb_dir = $(compdb_dir)
$(missing_compdb_dir):
@mkdir -p $@

compdb_file = $(compdb_dir)/$(subst /,-,$@.json)
compdb_args = -MJ $(compdb_file)
else
missing_compdb_dir =
compdb_args =
endif

ASM_SRC := $(wildcard $(OBJECTS:o=S)) ASM_SRC := $(wildcard $(OBJECTS:o=S))
ASM_OBJ := $(ASM_SRC:S=o) ASM_OBJ := $(ASM_SRC:S=o)
C_OBJ := $(filter-out $(ASM_OBJ),$(OBJECTS)) C_OBJ := $(filter-out $(ASM_OBJ),$(OBJECTS))


.SUFFIXES: .SUFFIXES:


$(C_OBJ): %.o: %.c GIT-CFLAGS $(missing_dep_dirs) $(C_OBJ): %.o: %.c GIT-CFLAGS $(missing_dep_dirs) $(missing_compdb_dir)
$(QUIET_CC)$(CC) -o $*.o -c $(dep_args) $(ALL_CFLAGS) $(EXTRA_CPPFLAGS) $< $(QUIET_CC)$(CC) -o $*.o -c $(dep_args) $(compdb_args) $(ALL_CFLAGS) $(EXTRA_CPPFLAGS) $<
$(ASM_OBJ): %.o: %.S GIT-CFLAGS $(missing_dep_dirs) $(ASM_OBJ): %.o: %.S GIT-CFLAGS $(missing_dep_dirs) $(missing_compdb_dir)
$(QUIET_CC)$(CC) -o $*.o -c $(dep_args) $(ALL_CFLAGS) $(EXTRA_CPPFLAGS) $< $(QUIET_CC)$(CC) -o $*.o -c $(dep_args) $(compdb_args) $(ALL_CFLAGS) $(EXTRA_CPPFLAGS) $<


%.s: %.c GIT-CFLAGS FORCE %.s: %.c GIT-CFLAGS FORCE
$(QUIET_CC)$(CC) -o $@ -S $(ALL_CFLAGS) $(EXTRA_CPPFLAGS) $< $(QUIET_CC)$(CC) -o $@ -S $(ALL_CFLAGS) $(EXTRA_CPPFLAGS) $<
@ -2413,6 +2454,14 @@ else
$(OBJECTS): $(LIB_H) $(GENERATED_H) $(OBJECTS): $(LIB_H) $(GENERATED_H)
endif endif


ifeq ($(GENERATE_COMPILATION_DATABASE),yes)
all:: compile_commands.json
compile_commands.json:
@$(RM) $@
$(QUIET_GEN)sed -e '1s/^/[/' -e '$$s/,$$/]/' $(compdb_dir)/*.o.json > $@+
@if test -s $@+; then mv $@+ $@; else $(RM) $@+; fi
endif

exec-cmd.sp exec-cmd.s exec-cmd.o: GIT-PREFIX exec-cmd.sp exec-cmd.s exec-cmd.o: GIT-PREFIX
exec-cmd.sp exec-cmd.s exec-cmd.o: EXTRA_CPPFLAGS = \ exec-cmd.sp exec-cmd.s exec-cmd.o: EXTRA_CPPFLAGS = \
'-DGIT_EXEC_PATH="$(gitexecdir_SQ)"' \ '-DGIT_EXEC_PATH="$(gitexecdir_SQ)"' \
@ -3117,7 +3166,7 @@ clean: profile-clean coverage-clean cocciclean
$(RM) $(TEST_PROGRAMS) $(RM) $(TEST_PROGRAMS)
$(RM) $(FUZZ_PROGRAMS) $(RM) $(FUZZ_PROGRAMS)
$(RM) $(HCC) $(RM) $(HCC)
$(RM) -r bin-wrappers $(dep_dirs) $(RM) -r bin-wrappers $(dep_dirs) $(compdb_dir) compile_commands.json
$(RM) -r po/build/ $(RM) -r po/build/
$(RM) *.pyc *.pyo */*.pyc */*.pyo $(GENERATED_H) $(ETAGS_TARGET) tags cscope* $(RM) *.pyc *.pyo */*.pyc */*.pyo $(GENERATED_H) $(ETAGS_TARGET) tags cscope*
$(RM) -r $(GIT_TARNAME) .doc-tmp-dir $(RM) -r $(GIT_TARNAME) .doc-tmp-dir

Loading…
Cancel
Save