132 lines
3 KiB
Makefile
132 lines
3 KiB
Makefile
|
# Configuration (File extensions, tools to be used, etc)
|
||
|
|
||
|
OPTLIBEXT=-O
|
||
|
DEBUGLIBEXT=-g
|
||
|
LIBEXTS=$(OPTLIBEXT) $(DEBUGLIBEXT)
|
||
|
|
||
|
ifeq "$(MAKECMDGOALS)" "opt"
|
||
|
LIBEXT=$(OPTLIBEXT)
|
||
|
OPTFLAGS=$(OPTFLAGS_OPT)
|
||
|
else
|
||
|
LIBEXT=$(DEBUGLIBEXT)
|
||
|
OPTFLAGS=$(OPTFLAGS_DEBUG)
|
||
|
endif
|
||
|
|
||
|
CXX=clang++
|
||
|
CC=clang
|
||
|
LN=ln
|
||
|
RM=rm
|
||
|
MKDIR=mkdir
|
||
|
TOUCH=touch
|
||
|
DIRNAME=dirname
|
||
|
|
||
|
OPTFLAGS_OPT=-O3
|
||
|
OPTFLAGS_DEBUG=-O0 -g
|
||
|
# flags used for linking and compilation
|
||
|
FLAGS=#
|
||
|
# These flags are for compilation (not linking) only
|
||
|
# -MMD auto-genenerates .d files in Make format when .o files are created
|
||
|
COMPILE_FLAGS=-MMD -Werror -Wall -Wextra -pedantic -pipe $(OPTFLAGS)
|
||
|
# Flags for linking only.
|
||
|
LINK_FLAGS=-fuse-ld=gold
|
||
|
# C / C++ specific compilation flags
|
||
|
CXX_STD_FLAGS=-std=c++20
|
||
|
CXX_COMPILE_FLAGS=$(CXX_STD_FLAGS)
|
||
|
C_STD_FLAGS=-std=c99
|
||
|
C_COMPILE_FLAGS=$(C_STD_FLAGS)
|
||
|
|
||
|
CXX_SRC_EXTS=cpp C CPP
|
||
|
C_SRC_EXTS=c
|
||
|
|
||
|
SRC_EXTS=$(CXX_SRC_EXTS) $(C_SRC_EXTS)
|
||
|
|
||
|
BUILDDIR=build
|
||
|
DIRECTORIES=$(BUILDDIR)
|
||
|
EXECUTABLE_REL=main
|
||
|
LINK_NAME=$(BUILDDIR)/$(EXECUTABLE_REL)
|
||
|
EXECUTABLE=$(LINK_NAME)$(LIBEXT)
|
||
|
|
||
|
# Collect files to be compiled
|
||
|
|
||
|
CXX_SRCS=$(foreach ext, $(CXX_SRC_EXTS), $(shell find . -name "*.$(ext)"))
|
||
|
C_SRCS=$(foreach ext, $(C_SRC_EXTS), $(shell find . -name "*.$(ext)"))
|
||
|
SRCS=$(CXX_SRCS) $(C_SRCS)
|
||
|
OBJS=$(foreach ext, $(SRC_EXTS), $(patsubst %.$(ext), $(BUILDDIR)/%$(LIBEXT).o, $(filter %.$(ext), $(SRCS))))
|
||
|
|
||
|
# If there is at least one C++ source use the c++ compiler CXX to link.
|
||
|
LINKER=$(CC) $(FLAGS) $(LINK_FLAGS)
|
||
|
ifneq "$(strip $(CXX_SRCS))" ""
|
||
|
LINKER=$(CXX) $(FLAGS) $(LINK_FLAGS)
|
||
|
endif
|
||
|
|
||
|
MAKECONFIG=Make.config
|
||
|
# The set of Make-files influencing the build, hence everything depends on them
|
||
|
MAKE_DEPENDENCIES=Makefile $(MAKECONFIG)
|
||
|
|
||
|
DEFAULT_TARGET=debug
|
||
|
|
||
|
# Include Make.config to modify variables above
|
||
|
-include $(MAKECONFIG)
|
||
|
|
||
|
# The supported meta targets, dependencies
|
||
|
.PHONY: clean debug opt default check
|
||
|
default: $(DEFAULT_TARGET)
|
||
|
clean debug opt: check
|
||
|
|
||
|
opt debug: $(EXECUTABLE)
|
||
|
|
||
|
$(OBJS) : $(MAKE_DEPENDENCIES) | $(BUILDDIR)
|
||
|
|
||
|
# include autogenerated .d files
|
||
|
-include $(OBJS:.o=.d)
|
||
|
|
||
|
# Rules
|
||
|
|
||
|
define CXX_TO_OBJ
|
||
|
$(CXX) $(FLAGS) $(CXX_COMPILE_FLAGS) $(COMPILE_FLAGS) $< -c -o $@
|
||
|
endef
|
||
|
|
||
|
define C_TO_OBJ
|
||
|
$(CC) $(FLAGS) $(C_COMPILE_FLAGS) $(COMPILE_FLAGS) $< -c -o $@
|
||
|
endef
|
||
|
|
||
|
define MK_TARGETDIR
|
||
|
@$(MKDIR) -p $$($(DIRNAME) $@)
|
||
|
endef
|
||
|
|
||
|
$(BUILDDIR)/%$(LIBEXT).o: %.cpp
|
||
|
$(MK_TARGETDIR)
|
||
|
$(CXX_TO_OBJ)
|
||
|
|
||
|
$(BUILDDIR)/%$(LIBEXT).o: %.C
|
||
|
$(MK_TARGETDIR)
|
||
|
$(CXX_TO_OBJ)
|
||
|
|
||
|
$(BUILDDIR)/%$(LIBEXT).o: %.CPP
|
||
|
$(MK_TARGETDIR)
|
||
|
$(CXX_TO_OBJ)
|
||
|
|
||
|
$(BUILDDIR)/%$(LIBEXT).o: %.c
|
||
|
$(MK_TARGETDIR)
|
||
|
$(C_TO_OBJ)
|
||
|
|
||
|
$(EXECUTABLE): $(OBJS) | $(BUILDDIR)
|
||
|
$(LINKER) $(OBJS) -o $@
|
||
|
|
||
|
# Create link in opt/debug target
|
||
|
opt debug:
|
||
|
$(LN) -sf $(EXECUTABLE_REL)$(LIBEXT) $(LINK_NAME)
|
||
|
|
||
|
check: $(BUILDDIR)
|
||
|
@forbidden=$$(find $(BUILDDIR) -not -type d $(foreach filext, .o .d, -not -name "*$(filext)") $(foreach libext, $(LIBEXTS) "", -not -name "$(EXECUTABLE_REL)$(libext)")); \
|
||
|
if [ "$${forbidden}x" != "x" ]; then echo "Error: $(BUILDDIR) contains non-autogenerated files $${forbidden}"; exit 1; fi
|
||
|
|
||
|
$(DIRECTORIES):
|
||
|
@$(MKDIR) $@
|
||
|
|
||
|
$(MAKECONFIG):
|
||
|
@$(TOUCH) $@
|
||
|
|
||
|
clean:
|
||
|
@$(RM) -rf $(BUILDDIR)
|