Hi Doron,

I am not a GNU make developer but I am pretty sure that it is not
possible to do this generically within make itself. Make does not work
at that level. It just runs shell code, it doesn't understand that a
particular command is, for example, invoking clang and should be added
to a compilation database.

If you want to generate a compilation database you can write makefile
rules to do that, however it will necessarily be at least somewhat
project-specific. For example, see the attached makefile module that
does this for us. Note that it references a bunch of variables defined
elsewhere, contains code that is specific to our needs, and will
certainly not work out-of-the-box for anyone else. It also assumes you
have other rules which are generating "ccmd" files containing the
exact compiler command invocations (you will need this anyway in order
to detect and handle compiler flags changing -- another thing that
ninja handles automatically that make cannot). Also it has a lot of
hackiness to deal with target-specific variables. So much regret:
learn from my mistakes! Do not use target-specific variables!

Cheers,
Duane.

On Sun, Jul 29, 2018 at 3:13 AM, Doron Behar <doron.be...@gmail.com> wrote:
> Many build systems, IDEs and text editors plugins, integrate with source
> code files using a compilation database. It is `compile_commands.json`
> and it is placed in a project's root directory.
>
> It is best explained here:
> https://clang.llvm.org/docs/JSONCompilationDatabase.html
>
> As listed here:
> (https://github.com/cquery-project/cquery/wiki/compile_commands.json),
> some build systems support it out of the box (ninja, cmake and waf) -
> (https://ninja-build.org/ https://cmake.org https://waf.io/)
>
> With probably the most common one, the GNU build system, this is not
> supported out of the box. Although there is currently 1 workaround
> (https://github.com/rizsotto/scan-build), It would be great it would be
> supported right out of the box, perhaps by introducing a new flag like
> `--compdb` which will create this file.
>
> I think it would be worth the effort of the developers, what do you guys
> think?
>
> _______________________________________________
> Bug-make mailing list
> Bug-make@gnu.org
> https://lists.gnu.org/mailman/listinfo/bug-make



-- 
"I never could learn to drink that blood and call it wine" - Bob Dylan
#***********************************************************************
#
# Rules for generating the compilation DB.
#
# This is used by the clang tooling. It contains a list of translation units
# and the commands used to generate them (also the working directory, but that
# is uninteresting for our build system).
#
# See the clang docs for more information:
# http://clang.llvm.org/docs/JSONCompilationDatabase.html
#
# To generate the compilation DB we must be building with clang and have
# CMD_CHECK set. We must also undo the effects of SKIPDEP *not* being set.
#
# The clang compiler is required so the flags used are consistent with what the
# clang tooling expects. If we are using some other compiler then we just error
# out.
#
# CMD_CHECK is required as without it there is no dependency from the object
# file to the command file. That dependency is required so the target-specific
# variables used to build the object file are present when writing the command
# file. To address this if it is missing we just reinvoke make with it.
#
# Copyright (c) 2016 Process Systems Enterprise Ltd
# ALL RIGHTS RESERVED
#
#***********************************************************************

.PHONY: compilation_db

# The JSON compilation database file.
COMPILATION_DB := $(GEN_DIR)/compile_commands.json

# Note we also need an (order-only) dependency on messaging headers otherwise
# we will get a failure when building from clean. Note also that ordering
# matters: this must be declared before the other dependencies below.
$(COMPILATION_DB): | GenerateMessagingHeaders

# Adds a dependency on the object file and command file to the compilation
# database and adds the command file to the list to be processed.
#
# NOTE: Adding the object file as a dependency is bad and wrong but necessary
#       to make this all work. Unfortunately it seems that make (at least as of
#       4.2.1) determines target-specific variables based on whether
#       dependencies that set them are rebuilt or not. I.e. the fact that the
#       object file has a dependency on the command file does not necessarily
#       mean the command file rules will run with the target-specific variables
#       defined for the object files. That will happen if and only if the
#       object files are also being rebuilt.
#
#       This means that in order to generate a correct command file we need to
#       also be building the object file at the same time. If we've previously
#       built the object file and command file together then everything should
#       be fine. However if not (e.g. because we are building from clean or
#       CMD_CHECK is not set) then to get it right we must rebuild the object
#       file.
#
# TODO: It would be really nice if we could avoid this!
CMD_FILE_SRCS :=
define DefineCommandFile
$(COMPILATION_DB): $(addprefix $(call GenObjBaseName,$(1)),.o .ccmd)
CMD_FILE_SRCS += $(1)
endef

# Text to generate for each entry in the compilation database.
define CompilationDBEntry
{ "file": "$(1)",
  "directory": "$(abspath $(TOP))",
  "command": "$(shell cat $(call GenObjBaseName,$(1)).ccmd)" },
endef

CommandFileSuffixes := %.c %.cpp %.cxx
CommandFileSources := $(filter $(CommandFileSuffixes),$(SOURCES))
$(foreach src,$(CommandFileSources),$(eval $(call DefineCommandFile,$(src))))

# Building with clang and CMD_CHECK: all good.
define CompilationDBReady

# Pseudo-target to generate the compilation database.
compilation_db: $(COMPILATION_DB)

# The compilation database's build rule.
#
# We add a bogus empty entry last so we don't need to worry about not adding a
# trailing comma to the last entry (stupid JSON!)
#
# NOTE: Dependencies on all command files have been added above (see
#       DefineCommandFile)
$(COMPILATION_DB):
	$$(file >$$@,[)
	$$(foreach cmdfile,$(CMD_FILE_SRCS),$$(file >>$$@,$$(call CompilationDBEntry,$$(cmdfile))))
	$$(file >>$$@,{"file": "", "command": "", "directory": ""}])
	@echo "Generated compilation database: $$@"

# Keep the compilation database up-to-date when doing a regular build with
# appropriate settings
TARGETS += $(COMPILATION_DB)
endef

# Building with clang but not CMD_CHECK: reinvoke with it.
define CompilationDBReinvoke
compilation_db::
	@$$(MAKE) --no-print-directory CC=clang CMD_CHECK=1 compilation_db
endef

# Not building with clang: fail.
define CompilationDBNeedsClang
compilation_db::
	@echo "You must build with clang (CC=clang) in order to generate the compilation database."
	@/bin/false
endef

# Select the appropriate rule for the pseudo-target depending on whether we
# have already been invoked with the correct flags.
CompilationDBSelectedRule = $(if $(findstring clang,$(CC)),$(if $(CMD_CHECK),$(CompilationDBReady),$(CompilationDBReinvoke)),$(CompilationDBNeedsClang))
$(eval $(CompilationDBSelectedRule))
_______________________________________________
Bug-make mailing list
Bug-make@gnu.org
https://lists.gnu.org/mailman/listinfo/bug-make

Reply via email to