compile_commands.json fileThe Better One of the Bunch - Meson!
How build systems talk to each other
.pc file is generated, we can consume that project.config/external/foo/flags.{common,linux,apple,windows}scripts/make/exports.mk script which looks like this...# scripts/make/exports.mk
EXTERNALS = $(shell realpath ./external)
EXTERNALS_CONFIG = $(shell realpath ./config/external)
INSTALL_DIRECTORY = $(shell realpath ./install)
BUILD_DIRECTORY = $(shell realpath ./build)
CLANGD_CONFIG = $(shell realpath ./.clangd)
PLATFORM = $(shell uname -s)
MESON_BUILD_TYPE = debug
CMAKE_BUILD_TYPE = Debug
SHELL := /bin/bash
ifeq ($(PLATFORM),Linux)
PLATFORM_CONFIG_EXTENSION = linux
else ifeq ($(PLATFORM),Darwin)
PLATFORM_CONFIG_EXTENSION = apple
else ifeq ($(PLATFORM),MINGW64*)
PLATFORM_CONFIG_EXTENSION = windows
else
PLATFORM_CONFIG_EXTENSION = unknown
endif
About exports.mk
flags.commonMake metaprogramming
scripts/make/build_wrappers.mk and eval call them from Makefilefoo, we generate foo, foo.configure, foo.build, foo.clangd, foo.install and foo.cleanconfig/external/foofoo depends on all those foo prefixed targets# scripts/make/build_wrappers.mk
define build_wrapper_cmake
$(1)_CONFIGURE_FLAGS=$$(shell cat $$(EXTERNALS_CONFIG)/$(1)/{flags.common,flags.$$(PLATFORM_CONFIG_EXTENSION)} | xargs)
$(1): $(1).configure $(1).build $(1).install $(1).clangd
$(1).configure:
cmake \
-DCMAKE_BUILD_TYPE=$$(CMAKE_BUILD_TYPE) \
-DCMAKE_INSTALL_PREFIX=$$(INSTALL_DIRECTORY) \
-DCMAKE_EXPORT_COMPILE_COMMANDS=ON \
$$($(1)_CONFIGURE_FLAGS) \
-B "$$(BUILD_DIRECTORY)/$(1)" \
-S "$$(EXTERNALS)/$(1)"
$(1).build:
cmake --build "$$(BUILD_DIRECTORY)/$(1)"
$(1).clangd:
$$(call clangd_config_string,$(1),$$(BUILD_DIRECTORY)/$(1))
$(1).install:
cmake --install "$$(BUILD_DIRECTORY)/$(1)" --prefix "$$(INSTALL_DIRECTORY)"
$(1).clean:
rm -rf "$$(BUILD_DIRECTORY)/$(1)"
endef
...# Makefile
$(eval $(call build_wrapper_meson,fontconfig))
$(eval $(call build_wrapper_cmake,cglm))
$(eval $(call build_wrapper_cmake,freetype))
$(eval $(call build_wrapper_meson,harfbuzz))
$(eval $(call build_wrapper_cmake,glfw))
$(eval $(call build_wrapper_cmake,glad))
$(eval $(call build_wrapper_autotools,ffmpeg))Clangd & CompDB
compile_commands.json file in the project root and the build/ directoryOne way is to use an external tool like bear to wrap all the build commands & append their compdb files
Clangd configuration
CompileFlags.CompilationDatabase in .clangd to tell clang where to look for the compdb fileCompilationDatabase path
# scripts/make/build_wrappers.mk
define clangd_config_string
@touch $(CLANGD_CONFIG)
@if ! grep -q $(1) $(CLANGD_CONFIG); then \
{ echo "---"; \
echo "If:"; \
echo " PathMatch: .*$(1).*"; \
echo "CompileFlags:"; \
echo " CompilationDatabase: $(2)"; \
} | tee -a $(CLANGD_CONFIG); \
endef
# Makefile
clangd:
$(call clangd_config_string,engine,$(BUILD_DIRECTORY))
$(call clangd_config_string,projects,$(BUILD_DIRECTORY))
.clangd to avoid duplicationfoo.clangd where we call this metaprogram