# **************************************************************************** # # # # :::::::: # # Makefile :+: :+: # # +:+ # # By: qmennen +#+ # # +#+ # # Created: 2024/10/15 11:48:46 by whaffman #+# #+# # # Updated: 2025/02/23 11:20:52 by willem ######## odam.nl # # # # **************************************************************************** # NAME = minishell SRC_PATH = src INC_PATH = inc LIB_PATH = lib BUILD_PATH = build LIBFT_PATH = $(LIB_PATH)/libft LIBFT_INC_PATH = $(LIBFT_PATH)/inc LIBFT = $(LIBFT_PATH)/libft.a CC = cc RM = rm -rf INCLUDES = -I./$(INC_PATH) -I./$(LIBFT_INC_PATH) UNAME_S := $(shell uname -s) ifeq ($(UNAME_S),Linux) LDLIBS := -L$(LIBFT_PATH) -lft -lreadline endif # Include sources.mk if it exists -include sources.mk # Build configurations BUILD_CONFIGS = release debug asan tsan release_CFLAGS = -Wall -Werror -Werror -O2 debug_CFLAGS = -Wall -Werror -Werror -g3 asan_CFLAGS = -Wall -Werror -Werror -fsanitize=address,leak,undefined -g3 tsan_CFLAGS = -Wall -Werror -Werror -fsanitize=thread -g3 # Targets for each build configuration define BUILD_TARGETS $(1)_OBJ_PATH = $(BUILD_PATH)/$(1)/obj $(1)_DEPENDS = $$(addprefix $$($(1)_OBJ_PATH)/, $$(SOURCES:.c=.d)) $(1)_OBJECTS = $$(addprefix $$($(1)_OBJ_PATH)/, $$(SOURCES:.c=.o)) .PHONY: $(1) $(1): CFLAGS = $$($(1)_CFLAGS) $(1): $(BUILD_PATH)/$(1)/$(NAME) .PHONY: run_$(1) run_$(1): $(1) $$(info $(bold)$(green)Running $(1)$(reset)) ./$(BUILD_PATH)/$(1)/$(NAME) $(BUILD_PATH)/$(1)/$(NAME): $(LIBFT) $$($(1)_OBJECTS) $$(info $(bold)$(green)Linking $(1) config$(reset)) $$(CC) $$(CFLAGS) $$($(1)_OBJECTS) $$(LDLIBS) -o $$@ -include $$($(1)_DEPENDS) $$($(1)_OBJ_PATH)/%.o: %.c $(LIBFT) | $$($(1)_OBJ_PATH) $$(CC) $$(CFLAGS) $$(INCLUDES) -MMD -MP -c $$< -o $$@ $$($(1)_OBJ_PATH): $$(info $(bold)$(green)Creating $(1) object directory$(reset)) mkdir -p $$@ endef # Copy the release build configuration to the root $(NAME): $(BUILD_PATH)/release/$(NAME) $(info $(bold)$(green)Copying release build to root$(reset)) cp $< $@ $(foreach config,$(BUILD_CONFIGS),$(eval $(call BUILD_TARGETS,$(config)))) # Build all configurations all: release debug asan tsan $(info $(bold)$(green)Building all$(reset)) # Build libft $(LIBFT): $(LIBFT_PATH) check-and-reinit-submodules $(info $(bold)$(green)Building libft$(reset)) $(MAKE) -C $(LIBFT_PATH) $(LIBFT_PATH): $(info $(bold)$(green)Adding libft submodule$(reset)) git submodule add https://gitea.duinvoetje.nl/willem/libft.git $(LIBFT_PATH) # Generate sources.mk sources.mk: $(info $(bold)$(green)Generating sources.mk$(reset)) @echo "VPATH = $$(find $(SRC_PATH) -type d | tr '\n' ':')" > sources.mk @echo "SOURCES = $$(find $(SRC_PATH) -type f -name '*.c' -exec basename {} \; | tr '\n' ' ' | fold -s -w 70 | sed 's/$$/ \\/')" >> sources.mk # Remove build artifacts clean: $(info $(bold)$(red)Cleaning$(reset)) find $(BUILD_PATH) -type d -name 'obj' -exec $(RM) {} + $(MAKE) -C $(LIBFT_PATH) clean # Remove build artifacts and the executable fclean: clean $(info $(bold)$(red)Full cleaning$(reset)) $(RM) $(BUILD_PATH) $(RM) $(NAME) $(MAKE) -C $(LIBFT_PATH) fclean # Rebuild the project re: fclean $(info $(bold)$(green)Rebuilding$(reset)) $(MAKE) all $(NAME) # Run the project with the release build configuration run: run_release $(info $(bold)$(green)Running$(reset)) # Remove sources.mk to force regeneration srcs: $(info $(bold)$(green)Regenerating sources.mk$(reset)) $(RM) sources.mk # Show this help. help: @echo "Usage: make [target]" @echo "" @echo "Targets:" @awk '/^#/{c=substr($$0,3);next}c&&/^[[:alpha:]][[:alnum:]_-]+:/{print substr($$1,1,index($$1,":")),c}1{c=0}' $(MAKEFILE_LIST) | column -s: -t @echo "" .PHONY: check-and-reinit-submodules check-and-reinit-submodules: $(info $(bold)$(green)Checking and reinitializing submodules$(reset)) @if git submodule status | egrep -q '^[-+]' ; then \ echo "INFO: Need to reinitialize git submodules"; \ git submodule update --init; \ fi .PHONY: all clean fclean re srcs run help red:=$(shell tput setaf 1) green:=$(shell tput setaf 2) yellow:=$(shell tput setaf 3) blue:=$(shell tput setaf 4) magenta:=$(shell tput setaf 5) cyan:=$(shell tput setaf 6) white:=$(shell tput setaf 7) bold:=$(shell tput bold) underline:=$(shell tput smul) reset:=$(shell tput sgr0)