Files
mcaselector-lite/makefile

129 lines
3.8 KiB
Makefile

# dependencies:
# - make
# - clang
# - glfw3 (install glfw3:x64-mingw-dynamic via vcpkg for win cross compilation)
# - vcpkg (win cross-compilation)
NAME := mcaselector-lite
DEBUG ?= 0
ARCH ?= 0
# C compiler options
CC := clang
CSTD := c17
CFLAGS := -Wall -Wextra -Wpedantic -Wno-pointer-arith -Ilib
LDFLAGS :=
# profiles
ifneq ($(DEBUG),0)
CFLAGS += -g -Og -fsanitize=address,undefined
LDFLAGS += -fsanitize=address,undefined
PROF := dbg
else
CFLAGS += -DNDEBUG -O2 -Werror
PROF := rel
endif
# targets
ifneq ($(MAKECMDGOALS),clean)
ifeq ($(ARCH),linux-x86_64)
CFLAGS += -target x86_64-pc-linux-gnu $(shell pkg-config --cflags glfw3)
LDFLAGS += -target x86_64-pc-linux-gnu $(shell pkg-config --libs glfw3)
else ifeq ($(ARCH),win-x86_64)
CFLAGS += -target x86_64-pc-windows-gnu -I$(VCPKG_ROOT)/installed/x64-mingw-dynamic/include
LDFLAGS += -target x86_64-pc-windows-gnu -L$(VCPKG_ROOT)/installed/x64-mingw-dynamic/lib -lglfw3dll -fuse-ld=lld
EXT := .exe
else
$(error you must set the ARCH environment variable to one of these: 'linux-x86_64' 'win-x86_64')
endif
endif
# output files
ifneq ($(ARCH),0)
DIR_BIN := bin/$(ARCH)/$(PROF)
DIR_OBJ := obj/$(ARCH)/$(PROF)
BIN := $(DIR_BIN)/$(NAME)$(EXT)
C_SRC := $(shell find src/ -name '*.c')
C_OBJ := $(patsubst src/%,$(DIR_OBJ)/%,$(C_SRC:.c=.o))
C_DEP := $(C_OBJ:.o=.d)
C_TSRC := $(shell find test/src/ -name '*.c')
C_TOBJ := $(patsubst test/src/%,test/$(DIR_OBJ)/%,$(C_TSRC:.c=.o))
C_TDEP := $(C_TOBJ:.o=.d)
C_TOBJ += $(filter-out $(DIR_OBJ)/main.o, $(C_OBJ))
COMPILE_COMMANDS := $(DIR_OBJ)/compile_commands.json
endif
define log_col
@printf "\033[%sm%s\033[0m\n" $(2) $(1)
endef
comp = $(call log_col,$(1),92)
mesg = $(call log_col,$(1),94)
warn = $(call log_col,$(1),93)
fail = $(call log_col,$(1),91)
# creates the binary (linking step)
define link_bin
$1: $2
@$$(call mesg,"CC: '$$(CC)'")
@$$(call mesg,"CFLAGS: '$$(CFLAGS)'")
@$$(call mesg,"LDFLAGS: '$$(LDFLAGS)'")
@$$(call comp,"linking to: '$$@'")
@mkdir -p $$(@D)
@$$(CC) $$(LDFLAGS) -o $$@ $$^
@$$(call mesg,"current profile: '$$(PROF)'")
endef
# creates .o and .d files
define compile_obj
$1/%.o: $2/%.c
@$$(call comp,"compiling $$@ from $$<")
@mkdir -p $$(@D)
@$$(CC) $$(CFLAGS) -c -MD -MP -std=$$(CSTD) -x c -o $$@ $$<
endef
# compiles and executes the produced binary
run: compile; cd $(DIR_BIN) && ./$(NAME)$(EXT)
compile: compile_commands $(BIN)
run-test: compile-test; cd test/$(DIR_BIN) && ./test$(EXT)
compile-test: test/$(DIR_BIN)/test$(EXT)
.NOTPARALLEL:
clean:
@$(call warn,"cleaning!")
rm -rf bin/ obj/ test/obj test/bin compile_commands.json
# compilation macros
$(eval $(call link_bin,$(BIN),$(C_OBJ))) # link the binary
$(eval $(call compile_obj,$(DIR_OBJ),src)) # compile the objects for the binary
$(eval $(call link_bin,test/$(DIR_BIN)/test$(EXT),$(C_TOBJ))) # link the testing binary
$(eval $(call compile_obj,test/$(DIR_OBJ),test/src)) # compile the objects for the testing binary
# update compile commands if the makefile has been updated (for linting)
compile_commands: # default, empty rule
ifneq ($(shell which bear),)
ifneq ($(COMPILE_COMMANDS),)
ifeq ($(NOCMDS),)
.NOTPARALLEL .PHONY:
compile_commands: $(COMPILE_COMMANDS)
@[ "$(readlink compile_commands.json)" != "$<" ] && ln -sf $< compile_commands.json
.NOTPARALLEL:
$(COMPILE_COMMANDS): makefile
@$(call warn,"regenerating compile_commands.json thus recompiling.")
@mkdir -p ${@D} # ensure the target directory exists
@touch $@ # create the file so it isn't retriggered (will just change modification time if already exists)
@bear --output $@ -- make -B compile NOCMDS=1 # rebuild the current target using bear, to create the compile commands
endif
endif
endif
# disable implicit rules
.SUFFIXES:
# include the dependencies
-include $(C_DEP)
-include $(C_TDEP)