| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349 |
- # Standard of Iron - Makefile
- # Provides standard targets for building, running, and managing the project
- # Default target
- .DEFAULT_GOAL := help
- # Configuration
- BUILD_DIR := build
- BUILD_TIDY_DIR := build-tidy
- BINARY_NAME := standard_of_iron
- MAP_EDITOR_BINARY := map_editor
- DEFAULT_LANG ?= en
- # Clang-tidy auto-fixer (git-only by default; --all scans whole project)
- CLANG_TIDY_FIXER := scripts/run-clang-tidy-fixes.sh
- # Optional knobs (override on the command line)
- # e.g. make tidy CLANG_TIDY_JOBS=2 CLANG_TIDY_AUTO_FIX_CHECKS="-*,bugprone-*"
- CLANG_TIDY_JOBS ?=
- CLANG_TIDY_AUTO_FIX_CHECKS ?=
- CLANG_TIDY_FIX_PATHS ?=
- # Base for git diff (fallback is origin/main inside the script if unset)
- CLANG_TIDY_GIT_BASE ?=
- # Formatting config
- CLANG_FORMAT ?= clang-format
- # Try to find qmlformat in common Qt installation paths if not in PATH
- QMLFORMAT ?= $(shell command -v qmlformat 2>/dev/null || echo /usr/lib/qt5/bin/qmlformat)
- FMT_GLOBS := -name "*.cpp" -o -name "*.c" -o -name "*.h" -o -name "*.hpp"
- SHADER_GLOBS := -name "*.frag" -o -name "*.vert"
- QML_GLOBS := -name "*.qml"
- # Colors for output
- BOLD := \033[1m
- GREEN := \033[32m
- BLUE := \033[34m
- YELLOW := \033[33m
- RED := \033[31m
- RESET := \033[0m
- # Help target - shows available commands
- .PHONY: help
- help:
- @echo "$(BOLD)Standard of Iron - Build System$(RESET)"
- @echo ""
- @echo "$(BOLD)Available targets:$(RESET)"
- @echo " $(GREEN)install$(RESET) - Install all dependencies"
- @echo " $(GREEN)configure$(RESET) - Configure build with CMake"
- @echo " $(GREEN)build$(RESET) - Build the project"
- @echo " $(GREEN)build-tidy$(RESET) - Build with clang-tidy static analysis enabled"
- @echo " $(GREEN)debug$(RESET) - Build with debug symbols and GDB support (no optimizations)"
- @echo " $(GREEN)release$(RESET) - Build optimized release version"
- @echo " $(GREEN)run$(RESET) - Run the main application"
- @echo " $(GREEN)editor$(RESET) - Run the map editor"
- @echo " $(GREEN)clean$(RESET) - Clean build directory"
- @echo " $(GREEN)rebuild$(RESET) - Clean and build"
- @echo " $(GREEN)test$(RESET) - Run tests (if any)"
- @echo " $(GREEN)format$(RESET) - Format all code (C++, QML, shaders)"
- @echo " $(GREEN)format-check$(RESET) - Verify formatting (CI-friendly, no changes)"
- @echo " $(GREEN)tidy$(RESET) - Run clang-tidy fixes on changed files (git diff vs origin/main)"
- @echo " $(GREEN)tidy-all$(RESET) - Run clang-tidy fixes on the whole project"
- @echo " $(GREEN)check-deps$(RESET) - Check if dependencies are installed"
- @echo " $(GREEN)dev$(RESET) - Set up development environment (install + configure + build)"
- @echo " $(GREEN)all$(RESET) - Full build (configure + build)"
- @echo ""
- @echo "$(BOLD)Examples:$(RESET)"
- @echo " make install # Install dependencies"
- @echo " make dev # Complete development setup"
- @echo " make debug # Build for debugging with GDB"
- @echo " make run # Build and run the game"
- @echo " DEFAULT_LANG=de make build # Build with German as default language"
- # Install dependencies
- .PHONY: install
- install:
- @echo "$(BOLD)$(BLUE)Installing dependencies...$(RESET)"
- @bash scripts/setup-deps.sh --yes
- @echo "$(GREEN)✓ Dependencies installed successfully$(RESET)"
- # Check if dependencies are installed
- .PHONY: check-deps
- check-deps:
- @echo "$(BOLD)$(BLUE)Checking dependencies...$(RESET)"
- @bash scripts/setup-deps.sh --dry-run
- # Create build directory
- build-dir:
- @mkdir -p $(BUILD_DIR)
- # Configure build with CMake
- .PHONY: configure
- configure: build-dir
- @echo "$(BOLD)$(BLUE)Configuring build with CMake...$(RESET)"
- @cd $(BUILD_DIR) && cmake -DENABLE_CLANG_TIDY=OFF -DDEFAULT_LANG=$(DEFAULT_LANG) ..
- @echo "$(GREEN)✓ Configuration complete$(RESET)"
- # Build the project
- .PHONY: build
- build: configure
- @echo "$(BOLD)$(BLUE)Building project...$(RESET)"
- @cd $(BUILD_DIR) && make -j$$(nproc)
- @echo "$(GREEN)✓ Build complete$(RESET)"
- # Build with clang-tidy enabled
- .PHONY: build-tidy
- build-tidy:
- @echo "$(BOLD)$(BLUE)Configuring build with clang-tidy enabled...$(RESET)"
- @mkdir -p $(BUILD_TIDY_DIR)
- @cd $(BUILD_TIDY_DIR) && cmake -DENABLE_CLANG_TIDY=ON -DDEFAULT_LANG=$(DEFAULT_LANG) ..
- @echo "$(BOLD)$(BLUE)Building with clang-tidy analysis...$(RESET)"
- @cd $(BUILD_TIDY_DIR) && make -j$$(nproc)
- @echo "$(GREEN)✓ Build with clang-tidy complete$(RESET)"
- # Build everything (alias for build)
- .PHONY: all
- all: build
- # Run the main application
- .PHONY: run
- run: build
- @echo "$(BOLD)$(BLUE)Running Standard of Iron...$(RESET)"
- @cd $(BUILD_DIR) && \
- BIN_PATH="./bin/$(BINARY_NAME)"; \
- if [ ! -x "$$BIN_PATH" ]; then \
- echo "$(RED)$(BINARY_NAME) not found at $$BIN_PATH$(RESET)"; \
- exit 127; \
- fi; \
- PLATFORM="$$(uname -s)"; \
- DEFAULT_QPA="offscreen"; \
- case "$$PLATFORM" in \
- Darwin) DEFAULT_QPA="cocoa" ;; \
- MINGW*|MSYS*|CYGWIN*) DEFAULT_QPA="windows" ;; \
- *) \
- if [ -n "$$WAYLAND_DISPLAY" ]; then \
- DEFAULT_QPA="wayland"; \
- elif [ -n "$$DISPLAY" ]; then \
- DEFAULT_QPA="xcb"; \
- fi ;; \
- esac; \
- if [ -z "$$QT_QPA_PLATFORM" ]; then \
- echo "$(YELLOW)QT_QPA_PLATFORM not set; defaulting to $$DEFAULT_QPA$(RESET)"; \
- QT_QPA_PLATFORM="$$DEFAULT_QPA" "$${BIN_PATH}"; \
- else \
- "$${BIN_PATH}"; \
- fi
- # Run with xvfb for headless environments (software rasterization)
- .PHONY: run-headless
- run-headless: build
- @echo "$(BOLD)$(BLUE)Running Standard of Iron under xvfb...$(RESET)"
- @if ! command -v xvfb-run >/dev/null 2>&1; then \
- echo "$(YELLOW)xvfb-run not found. Installing...$(RESET)"; \
- sudo apt-get update -y >/dev/null 2>&1 && sudo apt-get install -y xvfb >/dev/null 2>&1; \
- fi
- @cd $(BUILD_DIR) && \
- BIN_PATH="./bin/$(BINARY_NAME)"; \
- if [ ! -x "$$BIN_PATH" ]; then \
- echo "$(RED)$(BINARY_NAME) not found at $$BIN_PATH$(RESET)"; \
- exit 127; \
- fi; \
- xvfb-run -s "-screen 0 1280x720x24" "$$BIN_PATH"
- # Run the map editor
- .PHONY: editor
- editor: build
- @echo "$(BOLD)$(BLUE)Running Map Editor...$(RESET)"
- @cd $(BUILD_DIR) && ./tools/map_editor/$(MAP_EDITOR_BINARY)
- # Clean build directory
- .PHONY: clean
- clean:
- @echo "$(BOLD)$(YELLOW)Cleaning build directory...$(RESET)"
- @rm -rf $(BUILD_DIR) $(BUILD_TIDY_DIR)
- @echo "$(GREEN)✓ Clean complete$(RESET)"
- # Rebuild (clean + build)
- .PHONY: rebuild
- rebuild: clean build
- # Development setup (install + configure + build)
- .PHONY: dev
- dev: install build
- @echo "$(GREEN)✓ Development environment ready!$(RESET)"
- @echo "$(BOLD)You can now run:$(RESET)"
- @echo " make run # Run the game"
- @echo " make editor # Run the map editor"
- # Run tests (placeholder for future test implementation)
- .PHONY: test
- test: build
- @echo "$(BOLD)$(BLUE)Running tests...$(RESET)"
- @if [ -f "$(BUILD_DIR)/bin/standard_of_iron_tests" ]; then \
- cd $(BUILD_DIR) && ./bin/standard_of_iron_tests; \
- else \
- echo "$(RED)Test executable not found. Build may have failed.$(RESET)"; \
- exit 1; \
- fi
- # ---- Formatting: strip comments first, then format (strict) ----
- .PHONY: format format-check
- EXCLUDE_DIRS := ./$(BUILD_DIR) ./$(BUILD_TIDY_DIR) ./third_party
- EXCLUDE_FIND := $(foreach d,$(EXCLUDE_DIRS),-not -path "$(d)/*")
- format:
- @echo "$(BOLD)$(BLUE)Stripping comments in app/... game/... render/... tools/... ui/... assets/shaders/...$(RESET)"
- @if [ -x scripts/remove-comments.sh ]; then \
- ./scripts/remove-comments.sh app/ game/ render/ tools/ ui/ assets/shaders/; \
- elif [ -f scripts/remove-comments.sh ]; then \
- bash scripts/remove-comments.sh app/ game/ render/ tools/ ui/ assets/shaders/; \
- else \
- echo "$(RED)scripts/remove-comments.sh not found$(RESET)"; exit 1; \
- fi
- @echo "$(BOLD)$(BLUE)Applying clang-tidy auto fixes (git-only, nice)...$(RESET)"
- @bash $(CLANG_TIDY_FIXER) --nice --build-dir="$(BUILD_DIR)" --default-lang="$(DEFAULT_LANG)" $(if $(CLANG_TIDY_AUTO_FIX_CHECKS),--checks="$(CLANG_TIDY_AUTO_FIX_CHECKS)")
- @echo "$(BOLD)$(BLUE)Formatting C/C++ files with clang-format...$(RESET)"
- @if command -v $(CLANG_FORMAT) >/dev/null 2>&1; then \
- find . -type f \( $(FMT_GLOBS) \) $(EXCLUDE_FIND) -print0 \
- | xargs -0 -r $(CLANG_FORMAT) -i --style=file; \
- echo "$(GREEN)✓ C/C++ formatting complete$(RESET)"; \
- else \
- echo "$(RED)clang-format not found. Please install it.$(RESET)"; exit 1; \
- fi
- @echo "$(BOLD)$(BLUE)Formatting QML files...$(RESET)"
- @if command -v $(QMLFORMAT) >/dev/null 2>&1 || [ -x "$(QMLFORMAT)" ]; then \
- find . -type f \( $(QML_GLOBS) \) $(EXCLUDE_FIND) -print0 \
- | xargs -0 -r $(QMLFORMAT) -i; \
- echo "$(GREEN)✓ QML formatting complete$(RESET)"; \
- else \
- echo "$(YELLOW)⚠ qmlformat not found. Skipping QML formatting.$(RESET)"; \
- fi
- @echo "$(BOLD)$(BLUE)Formatting shader files (.frag, .vert)...$(RESET)"
- @if command -v $(CLANG_FORMAT) >/dev/null 2>&1; then \
- find . -type f \( $(SHADER_GLOBS) \) $(EXCLUDE_FIND) -print0 \
- | xargs -0 -r $(CLANG_FORMAT) -i --style=file; \
- echo "$(GREEN)✓ Shader formatting complete$(RESET)"; \
- else \
- echo "$(YELLOW)⚠ clang-format not found. Shader files not formatted.$(RESET)"; \
- fi
- @echo "$(GREEN)✓ All formatting complete$(RESET)"
- format-check:
- @echo "$(BOLD)$(BLUE)Checking formatting compliance...$(RESET)"
- @FAILED=0; \
- if command -v $(CLANG_FORMAT) >/dev/null 2>&1; then \
- echo "$(BLUE)Checking C/C++ files...$(RESET)"; \
- find . -type f \( $(FMT_GLOBS) \) $(EXCLUDE_FIND) -print0 \
- | xargs -0 -r $(CLANG_FORMAT) --dry-run -Werror --style=file || FAILED=1; \
- echo "$(BLUE)Checking shader files...$(RESET)"; \
- find . -type f \( $(SHADER_GLOBS) \) $(EXCLUDE_FIND) -print0 \
- | xargs -0 -r $(CLANG_FORMAT) --dry-run -Werror --style=file || FAILED=1; \
- fi; \
- if command -v $(QMLFORMAT) >/dev/null 2>&1 || [ -x "$(QMLFORMAT)" ]; then \
- echo "$(BLUE)Checking QML files...$(RESET)"; \
- for file in $$(find . -type f \( $(QML_GLOBS) \) $(EXCLUDE_FIND)); do \
- $(QMLFORMAT) "$$file" > /tmp/qmlformat_check.tmp 2>/dev/null; \
- if ! diff -q "$$file" /tmp/qmlformat_check.tmp >/dev/null 2>&1; then \
- echo "$(RED)QML file needs formatting: $$file$(RESET)"; \
- FAILED=1; \
- fi; \
- done; \
- rm -f /tmp/qmlformat_check.tmp; \
- fi; \
- if [ $$FAILED -eq 0 ]; then \
- echo "$(GREEN)✓ All formatting checks passed$(RESET)"; \
- else \
- echo "$(RED)✗ Formatting check failed. Run 'make format' to fix.$(RESET)"; \
- exit 1; \
- fi
- # ---- Static analysis: clang-tidy (driven by fixer script) ----
- .PHONY: tidy tidy-all
- tidy:
- @echo "$(BOLD)$(BLUE)Running clang-tidy fixes on changed files (vs $${CLANG_TIDY_GIT_BASE:-origin/main})...$(RESET)"
- @bash $(CLANG_TIDY_FIXER) \
- --nice \
- --build-dir="$(BUILD_DIR)" \
- --default-lang="$(DEFAULT_LANG)" \
- $(if $(CLANG_TIDY_JOBS),--jobs="$(CLANG_TIDY_JOBS)") \
- $(if $(CLANG_TIDY_FIX_PATHS),--paths="$(CLANG_TIDY_FIX_PATHS)") \
- $(if $(CLANG_TIDY_AUTO_FIX_CHECKS),--checks="$(CLANG_TIDY_AUTO_FIX_CHECKS)")
- tidy-all:
- @echo "$(BOLD)$(BLUE)Running clang-tidy fixes on ALL source files...$(RESET)"
- @bash $(CLANG_TIDY_FIXER) \
- --all \
- --nice \
- --build-dir="$(BUILD_DIR)" \
- --default-lang="$(DEFAULT_LANG)" \
- $(if $(CLANG_TIDY_JOBS),--jobs="$(CLANG_TIDY_JOBS)") \
- $(if $(CLANG_TIDY_FIX_PATHS),--paths="$(CLANG_TIDY_FIX_PATHS)") \
- $(if $(CLANG_TIDY_AUTO_FIX_CHECKS),--checks="$(CLANG_TIDY_AUTO_FIX_CHECKS)")
- # Debug build
- .PHONY: debug
- debug: build-dir
- @echo "$(BOLD)$(BLUE)Configuring debug build with GDB support...$(RESET)"
- @cd $(BUILD_DIR) && cmake -DCMAKE_BUILD_TYPE=Debug -DENABLE_CLANG_TIDY=OFF -DDEFAULT_LANG=$(DEFAULT_LANG) ..
- @echo "$(BOLD)$(BLUE)Building debug version...$(RESET)"
- @cd $(BUILD_DIR) && make -j$$(nproc)
- @echo "$(GREEN)✓ Debug build complete$(RESET)"
- @echo "$(BOLD)Debug Info:$(RESET)"
- @echo " Debug symbols: $(GREEN)Enabled (-g3 -ggdb3)$(RESET)"
- @echo " Optimizations: $(YELLOW)Disabled (-O0)$(RESET)"
- @echo " Frame pointers: $(GREEN)Preserved$(RESET)"
- @echo " Inlining: $(YELLOW)Disabled$(RESET)"
- @echo ""
- @echo "$(BOLD)Run with GDB:$(RESET)"
- @echo " cd $(BUILD_DIR) && gdb ./$(BINARY_NAME)"
- @echo " cd $(BUILD_DIR) && gdb --args ./$(BINARY_NAME) [args]"
- # Release build
- .PHONY: release
- release: build-dir
- @echo "$(BOLD)$(BLUE)Configuring release build...$(RESET)"
- @cd $(BUILD_DIR) && cmake -DCMAKE_BUILD_TYPE=Release -DENABLE_CLANG_TIDY=OFF ..
- @cd $(BUILD_DIR) && make -j$$(nproc)
- @echo "$(GREEN)✓ Release build complete$(RESET)"
- # Show build info
- .PHONY: info
- info:
- @echo "$(BOLD)Project Information:$(RESET)"
- @echo " Build directory: $(BUILD_DIR)"
- @echo " Binary name: $(BINARY_NAME)"
- @echo " Map editor: $(MAP_EDITOR_BINARY)"
- @echo " CMake version: $$(cmake --version | head -1)"
- @echo " GCC version: $$(gcc --version | head -1)"
- @if [ -f "$(BUILD_DIR)/$(BINARY_NAME)" ]; then \
- echo " Binary built: $(GREEN)✓$(RESET)"; \
- else \
- echo " Binary built: $(RED)✗$(RESET)"; \
- fi
- # Quick start for new developers
- .PHONY: quickstart
- quickstart:
- @echo "$(BOLD)$(GREEN)Quick Start Guide:$(RESET)"
- @echo "1. Install dependencies: $(BLUE)make install$(RESET)"
- @echo "2. Build the project: $(BLUE)make build$(RESET)"
- @echo "3. Run the game: $(BLUE)make run$(RESET)"
- @echo ""
- @echo "Or use the shortcut: $(BLUE)make dev$(RESET)"
|