Tasmota/lib/libesp32/RadioLib/examples/NonArduino/Tock/libtock-c/TockLibrary.mk
2024-02-23 16:20:09 +01:00

192 lines
8.1 KiB
Makefile

################################################################################
##
## libtock-c library shared makefile. Included by library makefiles to build
## libraries for use with libtock-c apps.
##
################################################################################
# The first target Make finds is its default. So this line needs to be first to
# specify `all` as our default rule.
all:
# Build settings.
include $(TOCK_USERLAND_BASE_DIR)/Configuration.mk
# Helper functions.
include $(TOCK_USERLAND_BASE_DIR)/Helpers.mk
$(call check_defined, LIBNAME)
$(call check_defined, $(LIBNAME)_DIR)
$(call check_defined, $(LIBNAME)_SRCS)
ifeq ($(strip $($(LIBNAME)_SRCS)),)
$(error Library "$(LIBNAME)" has no SRCS?)
endif
# directory for built output
$(LIBNAME)_BUILDDIR ?= $($(LIBNAME)_DIR)/build
# Handle complex paths.
#
# Okay, so this merits some explanation:
#
# Our build system aspires to put everything in build/ directories, this means
# that we have to match the path of source files (foo.c) to output directories
# (build/<arch>/foo.o). That's easy enough if all the source files are in the
# same directory, but restricts applications and libraries to a flat file
# structure.
#
# The current solution we employ is built on make's VPATH variable, which is a
# list of directories to search for dependencies, e.g.
#
# VPATH = foo/ ../bar/
# somerule: dependency.c
#
# Will find any of ./dependency.c, foo/dependency.c, or ../bar/dependency.c
# We leverage this by flattening the list of SRCS to remove all path
# information and adding all the paths from the SRCS to the VPATH, this means
# we can write rules as-if all the SRCS were in a flat directory.
#
# The obvious pitfall here is what happens when multiple directories hold a
# source file of the same name. However, both libnrf and mbed are set up to
# use VPATH without running into that problem, which gives some pretty serious
# hope that it won't be an issue in practice. The day is actually is a problem,
# we can revisit this, but the only solution I can think of presently is
# another layer of macros that generates the build rules for each path in SRCS,
# which is a pretty hairy sounding proposition
$(LIBNAME)_SRCS_FLAT := $(notdir $($(LIBNAME)_SRCS))
$(LIBNAME)_SRCS_DIRS := $(sort $(dir $($(LIBNAME)_SRCS))) # sort removes duplicates
# Only use vpath for certain types of files
# But must be a global list
VPATH_DIRS += $($(LIBNAME)_SRCS_DIRS)
vpath %.s $(VPATH_DIRS)
vpath %.c $(VPATH_DIRS)
vpath %.cc $(VPATH_DIRS)
vpath %.cpp $(VPATH_DIRS)
vpath %.cxx $(VPATH_DIRS)
# Now, VPATH allows _make_ to find all the sources, but gcc needs to be told
# how to find all of the headers. We do this by `-I`'ing any folder that had a
# LIB_SRC and has any .h files in it. We also check the common convention of
# headers in an include/ folder (both in and adjacent to src/) while we're at it
define LIB_HEADER_INCLUDES
ifneq ($$(wildcard $(1)/*.h),"")
override CPPFLAGS += -I$(1)
endif
ifneq ($$(wildcard $(1)/include/*.h),"")
override CPPFLAGS += -I$(1)/include
endif
ifneq ($$(wildcard $(1)/../include/*.h),"")
override CPPFLAGS += -I$(1)/../include
endif
endef
# uncomment to print generated rules
# $(info $(foreach hdrdir,$($(LIBNAME)_SRCS_DIRS),$(call LIB_HEADER_INCLUDES,$(hdrdir))))
# actually generate the rules
$(foreach hdrdir,$($(LIBNAME)_SRCS_DIRS),$(eval $(call LIB_HEADER_INCLUDES,$(hdrdir))))
# Rules to generate libraries for a given Architecture
# These will be used to create the different architecture versions of LibNRFSerialization
# Argument $(1) is the Architecture (e.g. cortex-m0) to build for
define LIB_RULES
$$($(LIBNAME)_BUILDDIR)/$(1):
$$(TRACE_DIR)
$$(Q)mkdir -p $$@
$$($(LIBNAME)_BUILDDIR)/$(1)/%.o: %.c | $$($(LIBNAME)_BUILDDIR)/$(1)
$$(TRACE_CC)
$$(Q)$$(TOOLCHAIN_$(1))$$(CC_$(1)) $$(CFLAGS) $$(CFLAGS_$(1)) $$(CPPFLAGS) $$(CPPFLAGS_$(1)) -MF"$$(@:.o=.d)" -MG -MM -MP -MT"$$(@:.o=.d)@" -MT"$$@" "$$<"
$$(Q)$$(TOOLCHAIN_$(1))$$(CC_$(1)) $$(CFLAGS) $$(CFLAGS_$(1)) $$(CPPFLAGS) $$(CPPFLAGS_$(1)) -c -o $$@ $$<
$$($(LIBNAME)_BUILDDIR)/$(1)/%.o: %.S | $$($(LIBNAME)_BUILDDIR)/$(1)
$$(TRACE_AS)
$$(Q)$$(TOOLCHAIN_$(1))$$(AS) $$(ASFLAGS) $$(CPPFLAGS) $$(CPPFLAGS_$(1)) -c -o $$@ $$<
$(LIBNAME)_OBJS_$(1) += $$(patsubst %.s,$$($(LIBNAME)_BUILDDIR)/$(1)/%.o,$$(filter %.s, $$($(LIBNAME)_SRCS_FLAT)))
$(LIBNAME)_OBJS_$(1) += $$(patsubst %.c,$$($(LIBNAME)_BUILDDIR)/$(1)/%.o,$$(filter %.c, $$($(LIBNAME)_SRCS_FLAT)))
$(LIBNAME)_OBJS_$(1) += $$(patsubst %.cc,$$($(LIBNAME)_BUILDDIR)/$(1)/%.o,$$(filter %.cc, $$($(LIBNAME)_SRCS_FLAT)))
$(LIBNAME)_OBJS_$(1) += $$(patsubst %.cpp,$$($(LIBNAME)_BUILDDIR)/$(1)/%.o,$$(filter %.cpp, $$($(LIBNAME)_SRCS_FLAT)))
$(LIBNAME)_OBJS_$(1) += $$(patsubst %.cxx,$$($(LIBNAME)_BUILDDIR)/$(1)/%.o,$$(filter %.cxx, $$($(LIBNAME)_SRCS_FLAT)))
# Dependency rules for picking up header changes
-include $$($(LIBNAME)_OBJS_$(1):.o=.d)
# Useful debugging
# $$(info -----------------------------------------------------)
# $$(info $(LIBNAME) $(1))
# $$(info $(LIBNAME)_SRCS: $$($(LIBNAME)_SRCS))
# $$(info $(LIBNAME)_SRCS_FLAT: $$($(LIBNAME)_SRCS_FLAT))
# $$(info VPATH: $$(VPATH))
# $$(info $(LIBNAME)_OBJS_$(1): $$($(LIBNAME)_OBJS_$(1)))
# $$(info =====================================================)
$$($(LIBNAME)_BUILDDIR)/$(1)/$(LIBNAME).a: $$($(LIBNAME)_OBJS_$(1)) | $$($(LIBNAME)_BUILDDIR)/$(1)
$$(TRACE_AR)
$$(Q)$$(TOOLCHAIN_$(1))$$(AR) rc $$@ $$^
$$(Q)$$(TOOLCHAIN_$(1))$$(RANLIB) $$@
# If we're building this library as part of a bigger build, add ourselves to
# the list of libraries
#
# Ahh.. make. By default, the RHS of variables aren't expanded at all until the
# variable is _used_ ("lazy set", "="), this means that LIBNAME will have
# changed by the time the variable is evaluated. We want immediate set (":="),
# but we'd also like to append ("+=") to grow the list. Append chooses between
# lazy or immediate set based on how the variable was previously set (yes,
# that's right, the RHS evaluation depends on the LHS type - make was ahead of
# it's time! :D), and defaults to lazy set if the variable is undefined at the
# first append. So, we force it to immediate set. Lovely.
ifndef LIBS_$(1)
LIBS_$(1) :=
endif
LIBS_$(1) += $$($(LIBNAME)_BUILDDIR)/$(1)/$(LIBNAME).a
endef
# uncomment to print generated rules
# $(info $(foreach platform,$(TOCK_ARCHS), $(call LIB_RULES,$(call ARCH_FN,$(platform)))))
# actually generate the rules for each architecture
$(foreach arch,$(TOCK_ARCHS),$(eval $(call LIB_RULES,$(arch))))
# add each architecture as a target
.PHONY: all
all: $(foreach arch, $(TOCK_ARCHS),$($(LIBNAME)_BUILDDIR)/$(arch)/$(LIBNAME).a)
# Force LIBNAME to be expanded now
define CLEAN_RULE
.PHONY: clean
clean::
rm -Rf $(1)
endef
$(eval $(call CLEAN_RULE,$($(LIBNAME)_BUILDDIR)))
# Rules for running the C linter
$(LIBNAME)_FORMATTED_FILES := $(patsubst %.c,$($(LIBNAME)_BUILDDIR)/format/%.uncrustify,$(filter %.c, $($(LIBNAME)_SRCS_FLAT)))
$(LIBNAME)_FORMATTED_FILES += $(patsubst %.cc,$($(LIBNAME)_BUILDDIR)/format/%.uncrustify,$(filter %.cc, $($(LIBNAME)_SRCS_FLAT)))
$(LIBNAME)_FORMATTED_FILES += $(patsubst %.cpp,$($(LIBNAME)_BUILDDIR)/format/%.uncrustify,$(filter %.cpp, $($(LIBNAME)_SRCS_FLAT)))
$(LIBNAME)_FORMATTED_FILES += $(patsubst %.cxx,$($(LIBNAME)_BUILDDIR)/format/%.uncrustify,$(filter %.cxx, $($(LIBNAME)_SRCS_FLAT)))
$($(LIBNAME)_BUILDDIR)/format:
@mkdir -p $@
.PHONY: fmt format
fmt format:: $($(LIBNAME)_FORMATTED_FILES)
$($(LIBNAME)_BUILDDIR)/format/%.uncrustify: %.c | _format_check_unstaged
$(Q)$(UNCRUSTIFY) -f $< -o $@
$(Q)cmp -s $< $@ || (if [ "$$CI" = "true" ]; then diff -y $< $@; rm $@; exit 1; else cp $@ $<; fi)
$($(LIBNAME)_BUILDDIR)/format/%.uncrustify: %.cc | _format_check_unstaged
$(Q)$(UNCRUSTIFY) -f $< -o $@
$(Q)cmp -s $< $@ || (if [ "$$CI" = "true" ]; then diff -y $< $@; rm $@; exit 1; else cp $@ $<; fi)
$($(LIBNAME)_BUILDDIR)/format/%.uncrustify: %.cpp | _format_check_unstaged
$(Q)$(UNCRUSTIFY) -f $< -o $@
$(Q)cmp -s $< $@ || (if [ "$$CI" = "true" ]; then diff -y $< $@; rm $@; exit 1; else cp $@ $<; fi)
$($(LIBNAME)_BUILDDIR)/format/%.uncrustify: %.cxx | _format_check_unstaged
$(Q)$(UNCRUSTIFY) -f $< -o $@
$(Q)cmp -s $< $@ || (if [ "$$CI" = "true" ]; then diff -y $< $@; rm $@; exit 1; else cp $@ $<; fi)