@@ -0,0 +1,257 @@ |
| 1 | +# Makefile for gitswitch-c |
| 2 | +# Safe git identity switching with SSH/GPG isolation |
| 3 | + |
| 4 | +# Project configuration |
| 5 | +PROJECT_NAME = gitswitch-c |
| 6 | +VERSION = 1.0.0-dev |
| 7 | +TARGET = gitswitch |
| 8 | + |
| 9 | +# Directories |
| 10 | +SRCDIR = src |
| 11 | +BUILDDIR = build |
| 12 | +OBJDIR = $(BUILDDIR)/obj |
| 13 | +BINDIR = $(BUILDDIR)/bin |
| 14 | +TESTDIR = tests |
| 15 | +DOCDIR = docs |
| 16 | + |
| 17 | +# Compiler and flags |
| 18 | +CC = gcc |
| 19 | +CFLAGS = -std=c11 -Wall -Wextra -Wpedantic -Wstrict-prototypes \ |
| 20 | + -Wmissing-prototypes -Wold-style-definition -Wredundant-decls \ |
| 21 | + -Wbad-function-cast -Wnested-externs -Winit-self -Wlogical-op \ |
| 22 | + -Wshadow -Wwrite-strings -Wcast-align -Wstrict-aliasing=2 \ |
| 23 | + -Wmissing-include-dirs -Wdate-time -Wformat=2 -Winit-self \ |
| 24 | + -Wswitch-default -Wunused -Werror-implicit-function-declaration |
| 25 | + |
| 26 | +# Security hardening flags |
| 27 | +SECURITY_FLAGS_DEBUG = -fstack-protector-strong -fstack-clash-protection -fcf-protection \ |
| 28 | + -Wl,-z,relro -Wl,-z,now -Wl,-z,noexecstack |
| 29 | +SECURITY_FLAGS_RELEASE = -D_FORTIFY_SOURCE=2 -fstack-protector-strong \ |
| 30 | + -fstack-clash-protection -fcf-protection \ |
| 31 | + -Wl,-z,relro -Wl,-z,now -Wl,-z,noexecstack |
| 32 | + |
| 33 | +# Debug/Release configurations |
| 34 | +DEBUG_FLAGS = -g -O0 -DDEBUG -fsanitize=address -fsanitize=undefined \ |
| 35 | + -fno-omit-frame-pointer -Wno-pedantic $(SECURITY_FLAGS_DEBUG) |
| 36 | +RELEASE_FLAGS = -O2 -DNDEBUG -s $(SECURITY_FLAGS_RELEASE) |
| 37 | + |
| 38 | +# Default to debug build |
| 39 | +BUILD_TYPE ?= debug |
| 40 | +ifeq ($(BUILD_TYPE),release) |
| 41 | + CFLAGS += $(RELEASE_FLAGS) |
| 42 | +else |
| 43 | + CFLAGS += $(DEBUG_FLAGS) |
| 44 | +endif |
| 45 | + |
| 46 | +# Include directories |
| 47 | +INCLUDES = -I$(SRCDIR) |
| 48 | + |
| 49 | +# Libraries |
| 50 | +LIBS = -lssl -lcrypto |
| 51 | +# Note: TOML parsing library will be added (e.g., -ltoml or embedded parser) |
| 52 | + |
| 53 | +# Source files (Phase 2 - Configuration Management) |
| 54 | +PHASE2_SOURCES = $(SRCDIR)/main.c $(SRCDIR)/error.c $(SRCDIR)/utils.c \ |
| 55 | + $(SRCDIR)/display.c $(SRCDIR)/toml_parser.c $(SRCDIR)/config.c \ |
| 56 | + $(SRCDIR)/accounts.c |
| 57 | + |
| 58 | +# Source files (Phase 3 - Git Operations) |
| 59 | +PHASE3_SOURCES = $(PHASE2_SOURCES) $(SRCDIR)/git_ops.c |
| 60 | + |
| 61 | +# Source files (Phase 4 - SSH Security Framework) |
| 62 | +PHASE4_SOURCES = $(PHASE3_SOURCES) $(SRCDIR)/ssh_manager.c |
| 63 | + |
| 64 | +# Source files (Phase 5 - GPG Environment Isolation) |
| 65 | +PHASE5_SOURCES = $(PHASE4_SOURCES) $(SRCDIR)/gpg_manager.c |
| 66 | + |
| 67 | +SOURCES = $(PHASE5_SOURCES) |
| 68 | +OBJECTS = $(SOURCES:$(SRCDIR)/%.c=$(OBJDIR)/%.o) |
| 69 | +HEADERS = $(wildcard $(SRCDIR)/*.h) |
| 70 | + |
| 71 | +# Test files |
| 72 | +TEST_SOURCES = $(wildcard $(TESTDIR)/*.c) |
| 73 | +TEST_OBJECTS = $(TEST_SOURCES:$(TESTDIR)/%.c=$(OBJDIR)/test_%.o) |
| 74 | +TEST_TARGETS = $(TEST_SOURCES:$(TESTDIR)/%.c=$(BINDIR)/test_%) |
| 75 | + |
| 76 | +# Default target |
| 77 | +.PHONY: all |
| 78 | +all: $(BINDIR)/$(TARGET) |
| 79 | + |
| 80 | +# Create directories |
| 81 | +$(OBJDIR): |
| 82 | + @mkdir -p $(OBJDIR) |
| 83 | + |
| 84 | +$(BINDIR): |
| 85 | + @mkdir -p $(BINDIR) |
| 86 | + |
| 87 | +# Compile source files |
| 88 | +$(OBJDIR)/%.o: $(SRCDIR)/%.c $(HEADERS) | $(OBJDIR) |
| 89 | + @echo "Compiling $<..." |
| 90 | + $(CC) $(CFLAGS) $(INCLUDES) -c $< -o $@ |
| 91 | + |
| 92 | +# Link main executable |
| 93 | +$(BINDIR)/$(TARGET): $(OBJECTS) | $(BINDIR) |
| 94 | + @echo "Linking $@..." |
| 95 | + $(CC) $(CFLAGS) $(OBJECTS) -o $@ $(LIBS) |
| 96 | + @echo "Build complete: $@" |
| 97 | + |
| 98 | +# Install target |
| 99 | +.PHONY: install |
| 100 | +install: $(BINDIR)/$(TARGET) |
| 101 | + @echo "Installing $(TARGET)..." |
| 102 | + install -d $(DESTDIR)/usr/local/bin |
| 103 | + install -m 755 $(BINDIR)/$(TARGET) $(DESTDIR)/usr/local/bin/$(TARGET) |
| 104 | + @echo "Installation complete" |
| 105 | + |
| 106 | +# Uninstall target |
| 107 | +.PHONY: uninstall |
| 108 | +uninstall: |
| 109 | + @echo "Uninstalling $(TARGET)..." |
| 110 | + rm -f $(DESTDIR)/usr/local/bin/$(TARGET) |
| 111 | + @echo "Uninstall complete" |
| 112 | + |
| 113 | +# Test compilation |
| 114 | +$(OBJDIR)/test_%.o: $(TESTDIR)/%.c $(HEADERS) | $(OBJDIR) |
| 115 | + @echo "Compiling test $<..." |
| 116 | + $(CC) $(CFLAGS) $(INCLUDES) -c $< -o $@ |
| 117 | + |
| 118 | +# Test executables (exclude main.o to avoid multiple main functions) |
| 119 | +$(BINDIR)/test_%: $(OBJDIR)/test_%.o $(filter-out $(OBJDIR)/main.o,$(OBJECTS)) | $(BINDIR) |
| 120 | + @echo "Linking test $@..." |
| 121 | + $(CC) $(CFLAGS) $^ -o $@ $(LIBS) |
| 122 | + |
| 123 | +# Build and run tests |
| 124 | +.PHONY: test |
| 125 | +test: $(TEST_TARGETS) |
| 126 | + @echo "Running tests..." |
| 127 | + @for test in $(TEST_TARGETS); do \ |
| 128 | + echo "Running $$test..."; \ |
| 129 | + $$test || exit 1; \ |
| 130 | + done |
| 131 | + @echo "All tests passed!" |
| 132 | + |
| 133 | +# Static analysis |
| 134 | +.PHONY: analyze |
| 135 | +analyze: |
| 136 | + @echo "Running static analysis..." |
| 137 | + @command -v cppcheck >/dev/null 2>&1 && \ |
| 138 | + cppcheck --enable=all --std=c11 --suppress=missingIncludeSystem $(SRCDIR) || \ |
| 139 | + echo "cppcheck not found - skipping static analysis" |
| 140 | + |
| 141 | +# Code formatting |
| 142 | +.PHONY: format |
| 143 | +format: |
| 144 | + @echo "Formatting code..." |
| 145 | + @command -v clang-format >/dev/null 2>&1 && \ |
| 146 | + clang-format -i $(SOURCES) $(HEADERS) || \ |
| 147 | + echo "clang-format not found - skipping formatting" |
| 148 | + |
| 149 | +# Security scan |
| 150 | +.PHONY: security-scan |
| 151 | +security-scan: |
| 152 | + @echo "Running security scan..." |
| 153 | + @command -v flawfinder >/dev/null 2>&1 && \ |
| 154 | + flawfinder $(SRCDIR) || \ |
| 155 | + echo "flawfinder not found - skipping security scan" |
| 156 | + |
| 157 | +# Memory check (requires valgrind) |
| 158 | +.PHONY: memcheck |
| 159 | +memcheck: $(BINDIR)/$(TARGET) |
| 160 | + @echo "Running memory check..." |
| 161 | + @command -v valgrind >/dev/null 2>&1 && \ |
| 162 | + valgrind --tool=memcheck --leak-check=full --show-leak-kinds=all \ |
| 163 | + --track-origins=yes --verbose --log-file=valgrind.log \ |
| 164 | + $(BINDIR)/$(TARGET) --help || \ |
| 165 | + echo "valgrind not found - skipping memory check" |
| 166 | + |
| 167 | +# Documentation generation |
| 168 | +.PHONY: docs |
| 169 | +docs: |
| 170 | + @echo "Generating documentation..." |
| 171 | + @mkdir -p $(DOCDIR) |
| 172 | + @command -v doxygen >/dev/null 2>&1 && \ |
| 173 | + doxygen Doxyfile || \ |
| 174 | + echo "doxygen not found - skipping documentation generation" |
| 175 | + |
| 176 | +# Clean targets |
| 177 | +.PHONY: clean |
| 178 | +clean: |
| 179 | + @echo "Cleaning build files..." |
| 180 | + rm -rf $(BUILDDIR) |
| 181 | + rm -f valgrind.log |
| 182 | + rm -f *.core core.* |
| 183 | + |
| 184 | +.PHONY: distclean |
| 185 | +distclean: clean |
| 186 | + @echo "Cleaning all generated files..." |
| 187 | + rm -rf $(DOCDIR) |
| 188 | + |
| 189 | +# Development helpers |
| 190 | +.PHONY: debug |
| 191 | +debug: BUILD_TYPE=debug |
| 192 | +debug: all |
| 193 | + |
| 194 | +.PHONY: release |
| 195 | +release: BUILD_TYPE=release |
| 196 | +release: all |
| 197 | + |
| 198 | +# Quick development cycle |
| 199 | +.PHONY: dev |
| 200 | +dev: clean debug test |
| 201 | + |
| 202 | +# Show build information |
| 203 | +.PHONY: info |
| 204 | +info: |
| 205 | + @echo "Project: $(PROJECT_NAME) v$(VERSION)" |
| 206 | + @echo "Target: $(TARGET)" |
| 207 | + @echo "Build type: $(BUILD_TYPE)" |
| 208 | + @echo "Compiler: $(CC)" |
| 209 | + @echo "CFLAGS: $(CFLAGS)" |
| 210 | + @echo "Sources: $(SOURCES)" |
| 211 | + @echo "Objects: $(OBJECTS)" |
| 212 | + |
| 213 | +# Dependencies check |
| 214 | +.PHONY: deps |
| 215 | +deps: |
| 216 | + @echo "Checking dependencies..." |
| 217 | + @echo "Required tools:" |
| 218 | + @command -v $(CC) >/dev/null 2>&1 && echo " $(CC)" || echo " $(CC) - REQUIRED" |
| 219 | + @command -v make >/dev/null 2>&1 && echo " make" || echo " make - REQUIRED" |
| 220 | + @echo "Optional tools:" |
| 221 | + @command -v cppcheck >/dev/null 2>&1 && echo " cppcheck" || echo " cppcheck - for static analysis" |
| 222 | + @command -v clang-format >/dev/null 2>&1 && echo " clang-format" || echo " clang-format - for formatting" |
| 223 | + @command -v valgrind >/dev/null 2>&1 && echo " valgrind" || echo " valgrind - for memory checking" |
| 224 | + @command -v flawfinder >/dev/null 2>&1 && echo " flawfinder" || echo " flawfinder - for security scanning" |
| 225 | + @command -v doxygen >/dev/null 2>&1 && echo " doxygen" || echo " doxygen - for documentation" |
| 226 | + |
| 227 | +# Help target |
| 228 | +.PHONY: help |
| 229 | +help: |
| 230 | + @echo "$(PROJECT_NAME) Makefile" |
| 231 | + @echo "" |
| 232 | + @echo "Targets:" |
| 233 | + @echo " all Build the project (default)" |
| 234 | + @echo " debug Build debug version" |
| 235 | + @echo " release Build release version" |
| 236 | + @echo " test Build and run tests" |
| 237 | + @echo " install Install to system" |
| 238 | + @echo " uninstall Remove from system" |
| 239 | + @echo " clean Remove build files" |
| 240 | + @echo " distclean Remove all generated files" |
| 241 | + @echo " format Format source code" |
| 242 | + @echo " analyze Run static analysis" |
| 243 | + @echo " security-scan Run security scan" |
| 244 | + @echo " memcheck Run memory checker" |
| 245 | + @echo " docs Generate documentation" |
| 246 | + @echo " deps Check dependencies" |
| 247 | + @echo " info Show build information" |
| 248 | + @echo " dev Quick development cycle (clean + debug + test)" |
| 249 | + @echo " help Show this help" |
| 250 | + @echo "" |
| 251 | + @echo "Variables:" |
| 252 | + @echo " BUILD_TYPE debug (default) or release" |
| 253 | + @echo " CC Compiler (default: gcc)" |
| 254 | + @echo " DESTDIR Installation prefix" |
| 255 | + |
| 256 | +# Prevent make from removing intermediate files |
| 257 | +.SECONDARY: $(OBJECTS) $(TEST_OBJECTS) |