# Compiler and flags CC = gcc CFLAGS = -Wall -O2 # Directories SRC_DIR = src BIN_DIR = bin # Source and target names TARGET = iptool SRC = $(SRC_DIR)/$(TARGET).c PRE = $(BIN_DIR)/$(TARGET).i ASM = $(BIN_DIR)/$(TARGET).s OBJ = $(BIN_DIR)/$(TARGET).o BIN = $(BIN_DIR)/$(TARGET) # Example argument for test ARG = # Default: build executable all: $(BIN) # Ensure bin directory exists $(BIN_DIR): mkdir -p $(BIN_DIR) # Stage 1: Preprocess $(PRE): $(SRC) | $(BIN_DIR) $(CC) -E $(CFLAGS) $< -o $@ # Stage 2: Compile to assembly $(ASM): $(PRE) $(CC) -S $(CFLAGS) $< -o $@ # Stage 3: Assemble to object file $(OBJ): $(ASM) $(CC) -c $(CFLAGS) $< -o $@ # Stage 4: Link object to executable $(BIN): $(OBJ) $(CC) $(CFLAGS) $< -o $@ # Run tests define run_test @name="$(1) $(2)"; \ width=40; \ printf "%s" "$$name"; \ dots=$$((width - $${#name})); \ for i in $$(seq 1 $$dots); do printf "."; done; \ ./$(BIN) $(2) >/dev/null 2>&1; \ ec=$$?; \ if [ $$ec -eq 0 ] || [ $$ec -eq 2 ]; then \ echo " OK"; \ else \ echo " FAILED (exit $$ec)"; \ exit 1; \ fi endef test: $(BIN) $(call run_test,$(TARGET),no args) $(call run_test,$(TARGET),$(ARG)) # Clean all generated files clean: rm -v -f $(BIN_DIR)/$(TARGET).* $(BIN)