#*********************************************************************** # # 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))