summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLibravatar Philippe Blain <levraiphilippeblain@gmail.com>2020-09-03 22:13:38 +0000
committerLibravatar Junio C Hamano <gitster@pobox.com>2020-09-06 12:22:26 -0700
commit3821c3806879ac9b42fa98051ab96f1231c89e73 (patch)
treea05335ca3fcd102e649d7e7c4d0bdc8aaaa05e05
parentTwelfth batch (diff)
downloadtgif-3821c3806879ac9b42fa98051ab96f1231c89e73.tar.xz
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>
-rw-r--r--.gitignore2
-rw-r--r--Makefile59
2 files changed, 56 insertions, 5 deletions
diff --git a/.gitignore b/.gitignore
index ee509a2ad2..f4c51300e0 100644
--- a/.gitignore
+++ b/.gitignore
@@ -197,6 +197,7 @@
/git.spec
*.exe
*.[aos]
+*.o.json
*.py[co]
.depend/
*.gcda
@@ -218,6 +219,7 @@
/tags
/TAGS
/cscope*
+/compile_commands.json
*.hcc
*.obj
*.lib
diff --git a/Makefile b/Makefile
index 65f8cfb236..39ca667689 100644
--- a/Makefile
+++ b/Makefile
@@ -462,6 +462,12 @@ all::
# the global variable _wpgmptr containing the absolute path of the current
# 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
# and family are auto detected, but could be overridden by defining
# 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
+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
SANE_TOOL_PATH_SQ = $(subst ','\'',$(SANE_TOOL_PATH))
BROKEN_PATH_FIX = 's|^\# @@BROKEN_PATH_FIX@@$$|git_broken_path_fix "$(SANE_TOOL_PATH_SQ)"|'
@@ -2381,16 +2408,30 @@ missing_dep_dirs =
dep_args =
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_OBJ := $(ASM_SRC:S=o)
C_OBJ := $(filter-out $(ASM_OBJ),$(OBJECTS))
.SUFFIXES:
-$(C_OBJ): %.o: %.c GIT-CFLAGS $(missing_dep_dirs)
- $(QUIET_CC)$(CC) -o $*.o -c $(dep_args) $(ALL_CFLAGS) $(EXTRA_CPPFLAGS) $<
-$(ASM_OBJ): %.o: %.S GIT-CFLAGS $(missing_dep_dirs)
- $(QUIET_CC)$(CC) -o $*.o -c $(dep_args) $(ALL_CFLAGS) $(EXTRA_CPPFLAGS) $<
+$(C_OBJ): %.o: %.c GIT-CFLAGS $(missing_dep_dirs) $(missing_compdb_dir)
+ $(QUIET_CC)$(CC) -o $*.o -c $(dep_args) $(compdb_args) $(ALL_CFLAGS) $(EXTRA_CPPFLAGS) $<
+$(ASM_OBJ): %.o: %.S GIT-CFLAGS $(missing_dep_dirs) $(missing_compdb_dir)
+ $(QUIET_CC)$(CC) -o $*.o -c $(dep_args) $(compdb_args) $(ALL_CFLAGS) $(EXTRA_CPPFLAGS) $<
%.s: %.c GIT-CFLAGS FORCE
$(QUIET_CC)$(CC) -o $@ -S $(ALL_CFLAGS) $(EXTRA_CPPFLAGS) $<
@@ -2413,6 +2454,14 @@ else
$(OBJECTS): $(LIB_H) $(GENERATED_H)
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: EXTRA_CPPFLAGS = \
'-DGIT_EXEC_PATH="$(gitexecdir_SQ)"' \
@@ -3117,7 +3166,7 @@ clean: profile-clean coverage-clean cocciclean
$(RM) $(TEST_PROGRAMS)
$(RM) $(FUZZ_PROGRAMS)
$(RM) $(HCC)
- $(RM) -r bin-wrappers $(dep_dirs)
+ $(RM) -r bin-wrappers $(dep_dirs) $(compdb_dir) compile_commands.json
$(RM) -r po/build/
$(RM) *.pyc *.pyo */*.pyc */*.pyo $(GENERATED_H) $(ETAGS_TARGET) tags cscope*
$(RM) -r $(GIT_TARNAME) .doc-tmp-dir