# **************************************************************************** # # # # ::: :::::::: # # Makefile :+: :+: :+: # # +:+ +:+ +:+ # # By: acossari +#+ +:+ +#+ # # +#+#+#+#+#+ +#+ # # Created: 2026/08/19 10:05:52 by acossari #+# #+# # # Updated: 2026/08/20 22:18:47 by acossari ### ########.fr # # # # **************************************************************************** # NAME := webserv SRC_DIR := src OBJ_DIR := obj INC_DIR := include CXX := g++ # EXTRA_CXXFLAGS is the slot for flags added from the command line, for example # make EXTRA_CXXFLAGS="-g3 -fsanitize=address". CXXFLAGS itself must never be # overridden that way, it carries the warning flags that have to stay on. CXXFLAGS := -Wall -Wextra -Werror -std=c++23 -I$(INC_DIR) $(EXTRA_CXXFLAGS) # The C++ standard library goes inside the binary instead of being loaded from # the system at startup. A recent compiler emits references to symbol versions # that an older system libstdc++.so.6 does not carry, and that failure shows up # when the program is started, not when it is linked. LDFLAGS := -static-libstdc++ -static-libgcc CLANG ?= clang++ CLANG_TIDY ?= clang-tidy CLANG_FORMAT ?= clang-format # Separate object directory and binary for the clang build. Sharing obj/ would # link a fresh g++ object with a leftover clang one, and the error looks like a # bug in the source instead of an old file. CLANG_NAME := $(NAME)-clang CLANG_OBJ_DIR := $(OBJ_DIR)/clang # libstdc++ is the GNU library and ships with g++, libc++ is the LLVM one and # ships with clang. On Linux clang usually sits on libstdc++ anyway, and that # pairing cannot build this project: # # clang 18 with libstdc++ : std::expected not available # clang 18 with libc++ : std::expected available # # So every clang pass gets libc++. g++ never sees this flag. CLANG_STDLIB ?= -stdlib=libc++ # find returns files in filesystem order, which is not the same on every # machine. sort keeps the compile and link lines stable, so build logs and # clang-tidy output stay comparable. #SRCS := $(sort $(shell find $(SRC_DIR) -type f -name '*.cpp')) SRCS := src/Log.cpp src/main.cpp src/Server.cpp \ src/config/Config.cpp src/config/ConfigurationParser.cpp src/config/LocationConfig.cpp src/config/ServerConfig.cpp \ src/event/Epoll.cpp src/event/EventToken.cpp \ src/net/ByteBuffer.cpp src/net/Connection.cpp src/net/FileDescriptor.cpp src/net/Listener.cpp src/net/ListenerPlan.cpp src/net/PauseMask.cpp src/net/SlotPool.cpp \ src/http/Request.cpp src/http/RequestParser.cpp OBJS := $(SRCS:$(SRC_DIR)/%.cpp=$(OBJ_DIR)/%.o) # Make only knows that obj/main.o comes from src/main.cpp, so editing Log.hpp # would leave the old main.o in place. Each .d adds the missing line, obj/main.o # also depends on include/Log.hpp, and -include at the bottom pulls them in. DEPS := $(OBJS:.o=.d) HDRS := include/config/Config.hpp include/config/ConfigurationParser.hpp include/config/LocationConfig.hpp include/config/ServerConfig.hpp \ include/event/Epoll.hpp include/event/EventToken.hpp \ include/http/HttpStatus.hpp include/http/Request.hpp include/http/RequestParser.hpp \ include/net/ByteBuffer.hpp include/net/Connection.hpp include/net/FileDescriptor.hpp include/net/Listener.hpp include/net/ListenerPlan.hpp include/net/PauseMask.hpp include/net/SlotPool.hpp \ include/Log.hpp include/Result.hpp include/Server.hpp \ #HDRS := $(sort $(shell find $(INC_DIR) $(SRC_DIR) -type f \ # \( -name '*.hpp' -o -name '*.tpp' \))) all: $(NAME) $(NAME): $(OBJS) $(CXX) $(CXXFLAGS) $(LDFLAGS) $(OBJS) -o $(NAME) # -MMD writes the .d file described above. -MP adds an empty rule for every # header in it, which matters after a rename: the old .d still asks for the old # path and make stops, having no way to build that file. The empty rule says the # header needs no recipe, so make moves on and recompiles. $(OBJ_DIR)/%.o: $(SRC_DIR)/%.cpp @mkdir -p $(dir $@) $(CXX) $(CXXFLAGS) -MMD -MP -c $< -o $@ # Reports only, never fails the build: WarningsAsErrors is empty in .clang-tidy # and all does not depend on this. clang-tidy parses the code itself, so it # needs the same flags the compiler gets (everything after the --). tidy: $(SRCS) $(CLANG_TIDY) $(SRCS) -- $(CXXFLAGS) $(CLANG_STDLIB) # Same sources through the other compiler and standard library, into files of # its own, so the normal build is untouched. Worth running because the two # compilers do not warn about the same things. Needs libc++ 18 or newer, the # first release that ships . check-clang: $(MAKE) --no-print-directory NAME=$(CLANG_NAME) OBJ_DIR=$(CLANG_OBJ_DIR) \ CXX=$(CLANG) EXTRA_CXXFLAGS="$(CLANG_STDLIB)" format: $(CLANG_FORMAT) -i $(SRCS) $(HDRS) format-check: $(CLANG_FORMAT) --dry-run --Werror $(SRCS) $(HDRS) clean: rm -rf $(OBJ_DIR) fclean: clean rm -f $(NAME) $(CLANG_NAME) re: fclean all -include $(DEPS) .PHONY: all clean fclean re tidy check-clang format format-check