# **************************************************************************** # # # # ::: :::::::: # # Makefile :+: :+: :+: # # +:+ +:+ +:+ # # By: qmennen +#+ +:+ +#+ # # +#+#+#+#+#+ +#+ # # Created: 2024/10/15 11:48:46 by whaffman #+# #+# # # Updated: 2025/06/11 17:41:17 by qmennen ### ########.fr # # # # **************************************************************************** # NAME = cub3D FLAGS="-DFULLSCREEN=1" DIST_PATH = dist 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 MLX42_PATH = $(LIB_PATH)/MLX42 MLX42_TOP_INCLUDE = $(MLX42_PATH)/include MLX42_INC_PATH = $(MLX42_PATH)/include/MLX42 GLAD_INC_PATH = $(MLX42_PATH)/include/glad MLX42 = $(MLX42_PATH)/build/libmlx42.a CC = cc RM = rm -rf INCLUDES = -I./$(INC_PATH) -I./$(LIBFT_INC_PATH) -I./$(MLX42_INC_PATH) -I./$(GLAD_INC_PATH) -I./$(MLX42_TOP_INCLUDE) UNAME_S := $(shell uname -s) ifeq ($(UNAME_S),Linux) LDLIBS := -L$(LIBFT_PATH) -lft -L$(MLX42_PATH)/build -lmlx42 -ldl -lglfw -pthread -lm endif VPATH = $(shell find $(SRC_PATH) -type d | tr '\n' ':') SOURCES = $(shell basename -a $(shell find $(SRC_PATH) -type f -name "*.c")) # Include sources.mk if it exists # -include sources.mk # Build configurations BUILD_CONFIGS = release debug asan tsan release_CFLAGS = -Wall -Wextra -Werror -flto -Ofast -march=native -mtune=native -ffast-math unity_CFLAGS = -Wall -Wextra -Werror -Ofast -march=native -mtune=native -ffast-math debug_CFLAGS = -Wall -Wextra -Werror -g3 -DDEBUG -DDBG='fprintf(stderr, RED "DEBUG: " RESET "%s:%d (%s)\n", __FILE__, __LINE__, __PRETTY_FUNCTION__);' asan_CFLAGS = -Wall -Wextra -Werror -flto -fsanitize=address,leak,undefined -g3 tsan_CFLAGS = -Wall -Wextra -Werror -fsanitize=thread -g3 RUN_ARGS=test.cub # 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) $$(FLAGS) $(1): $(BUILD_PATH)/$(1)/$(NAME) .PHONY: run_$(1) run_$(1): $(1) $$(info $$(bold)$$(green)Running $(1)$$(reset)) ./$(BUILD_PATH)/$(1)/$(NAME) $(RUN_ARGS) $(BUILD_PATH)/$(1)/$(NAME): $(LIBFT) $(MLX42) $$($(1)_OBJECTS) Makefile $$(info $$(bold)$$(green)Linking $(1) config$$(reset)) $$(CC) $$(CFLAGS) $$($(1)_OBJECTS) $$(LDLIBS) -o $$@ -include $$($(1)_DEPENDS) $$($(1)_OBJ_PATH)/%.o: %.c $(LIBFT) $(MLX42) Makefile | $$($(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): release $(info $(bold)$(green)Copying release build to root$(reset)) cp $(BUILD_PATH)/release/$(NAME) $@ $(foreach config,$(BUILD_CONFIGS),$(eval $(call BUILD_TARGETS,$(config)))) # Build all configurations all: release debug asan tsan $(info $(bold)$(green)All builc config have been build$(reset)) # Unity/Jumbo/Blob build ALL_SOURCES = $(shell find $(SRC_PATH) -type f -name "*.c") run_unity: $(BUILD_PATH)/unity/$(NAME) $(info $(bold)$(green)Running unity build$(reset)) ./$(BUILD_PATH)/unity/$(NAME) $(RUN_ARGS) unity: $(BUILD_PATH)/unity/$(NAME) $(BUILD_PATH)/unity/$(NAME): $(BUILD_PATH)/unity/blob.c $(LIBFT) $(MLX42) $(ALL_SOURCES) $(info $(bold)$(green)Building unity blob$(reset)) $(CC) $(unity_CFLAGS) $(INCLUDES) -Isrc -MMD -MP -c $(BUILD_PATH)/unity/blob.c -o $(BUILD_PATH)/unity/blob.o $(CC) $(unity_CFLAGS) $(INCLUDES) -o $@ $(BUILD_PATH)/unity/blob.o $(LDLIBS) $(BUILD_PATH)/unity/blob.c: $(ALL_SOURCES) $(BUILD_PATH)/unity $(info $(bold)$(green)Generating unity blob.c$(reset)) @echo "/* This file is generated by the Makefile */" > $@ @echo "#include \"cub3d.h\"" >> $@ @echo $(ALL_SOURCES) | tr ' ' '\n' | sed 's%^%#include "../../%; s/$$/"/' >> $@ $(BUILD_PATH)/unity: $(info $(bold)$(green)Creating unity build directory$(reset)) mkdir -p $(BUILD_PATH)/unity # Build libft $(LIBFT): $(LIBFT_PATH) 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) # Build MLX42 $(MLX42): $(MLX42_PATH) $(info $(bold)$(green)Building MLX42$(reset)) cmake $(MLX42_PATH) -B $(MLX42_PATH)/build $(MAKE) -C $(MLX42_PATH)/build -j4 $(MLX42_PATH): git submodule add https://github.com/codam-coding-college/MLX42.git $(MLX42_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) fclean $(MAKE) -C $(MLX42_PATH)/build clean # Remove build artifacts and the executable fclean: clean $(info $(bold)$(red)Full cleaning$(reset)) $(RM) $(BUILD_PATH) $(RM) $(NAME) # Rebuild the project re: fclean $(info $(bold)$(green)Rebuilding$(reset)) $(MAKE) all $(NAME) # Run the project with the release build configuration run: run_release run_valgrind: debug valgrind --leak-check=full --show-leak-kinds=all --track-origins=yes --suppressions=MLX42.supp ./$(BUILD_PATH)/debug/$(NAME) # # Remove sources.mk to force regeneration srcs: $(info $(bold)$(green)Regenerating sources.mk on next make$(reset)) $(RM) sources.mk # dist: $(SRC_PATH) $(INC_PATH) $(LIB_PATH) release_makefile.mk # @if [ ! -d $(DIST_PATH) ]; then \ # mkdir -p $(DIST_PATH); \ # else \ # rm -rf $(DIST_PATH)/*; \ # fi # @rsync -av --include='*/' --include='*.c' --include='*.h' --include='Makefile' --exclude='*' src/ $(DIST_PATH)/src/ # @rsync -av --include='*/' --include='*.c' --include='*.h' --include='Makefile' --exclude='*' inc/ $(DIST_PATH)/inc/ # @rsync -av --include='*/' --include='*.c' --include='*.h' --include='Makefile' --exclude='*' lib/ $(DIST_PATH)/lib/ # @cp release_makefile.mk $(DIST_PATH)/Makefile # @make -s sources.mk # @cp sources.mk $(DIST_PATH)/sources.mk # @norminette $(DIST_PATH) > /dev/null; \ # if [ $$? -ne 0 ]; then \ # echo "\e[31mNorminette failed, deleting dist folder\e[0m"; \ # norminette $(DIST_PATH) | grep "Error"; \ # rm -rf $(DIST_PATH); \ # exit 1; \ # fi # @echo -e "\e[32mDistribute successful\e[0m" # Show this help. help: @echo "Usage: make [target]" @echo "" @echo "Targets:" @echo " $(green)$(bold)all $(reset)- Build all configurations (release, debug, asan, tsan)" @echo " $(green)$(bold)dist $(reset)- rebuild the folderstructure for distribution" @echo " $(green)$(bold)clean $(reset)- Remove build artifacts" @echo " $(green)$(bold)fclean $(reset)- Remove build artifacts and the executable" @echo " $(green)$(bold)re $(reset)- Rebuild the project" @echo " $(green)$(bold)run $(reset)- Run the release build" @echo " $(green)$(bold)srcs $(reset)- Remove sources.mk" @echo " $(green)$(bold)help $(reset)- Show this help message" @echo "" @echo "Build configurations:" @echo " $(green)$(bold)release $(reset)- Build with release configuration" @echo " $(green)$(bold)debug $(reset)- Build with debug configuration" @echo " $(green)$(bold)asan $(reset)- Build with AddressSanitizer configuration" @echo " $(green)$(bold)tsan $(reset)- Build with ThreadSanitizer configuration" @echo "" @echo "Run configurations:" @echo " $(green)$(bold)run_release $(reset)- Run the release build" @echo " $(green)$(bold)run_debug $(reset)- Run the debug build" @echo " $(green)$(bold)run_asan $(reset)- Run the AddressSanitizer build" @echo " $(green)$(bold)run_tsan $(reset)- Run the ThreadSanitizer build" @echo " $(green)$(bold)run_valgrind $(reset)- Run the release build with valgrind" @echo "" @echo "Other targets:" @echo " $(green)$(bold)submodules $(reset)- Check and reinitialize git submodules" @echo " $(green)$(bold)libft $(reset)- Build libft" @echo " $(green)$(bold)sources.mk $(reset)- Generate sources.mk" @echo "" .PHONY: submodules 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 dist 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)