Skip to content

Instantly share code, notes, and snippets.

@wonbyte
Created April 19, 2025 22:37
Show Gist options
  • Save wonbyte/eef605c5cd23b4042e96c204a27f60c3 to your computer and use it in GitHub Desktop.
Save wonbyte/eef605c5cd23b4042e96c204a27f60c3 to your computer and use it in GitHub Desktop.
C Makefile
# Debugging and tracing flags
TRACEFLAGS := -g -fno-omit-frame-pointer -funwind-tables
# Compiler and basic settings
CC := clang
VERSION := 1.0.0
DEVFLAGS := -Wall -Wextra -Wunused-parameter
INCLUDES := -I include
CFLAGS := $(DEVFLAGS) $(TRACEFLAGS) $(INCLUDES)
# Directories
SRC_DIR := src
HDR_DIR := include
OBJDIR := build
BINDIR := bin
# Targets
TARGET := $(BINDIR)/nugget
RELEASE_TARGET := $(BINDIR)/nugget-release
ASAN_TARGET := $(BINDIR)/nugget-asan
# Optimization flags for release builds
RELEASE_FLAGS := -O3 -DNDEBUG
# AddressSanitizer flags
ASAN_FLAGS := -fsanitize=address,leak $(TRACEFLAGS)
# Sources, objects, dependencies
SRCS := $(wildcard $(SRC_DIR)/*.c)
HDRS := $(wildcard $(HDR_DIR)/*.h)
OBJS := $(SRCS:$(SRC_DIR)/%.c=$(OBJDIR)/%.o)
DEPS := $(OBJS:.o=.d)
# Clang-tidy
CLANG_TIDY := clang-tidy
# Colors
COLOR_RESET := \033[0m
COLOR_GREEN := \033[32m
COLOR_YELLOW := \033[33m
# Core build and run
.PHONY: all run clean pristine
all: compile_commands $(TARGET)
run: $(TARGET)
@./$(TARGET)
clean:
@rm -rf $(OBJDIR) $(BINDIR) compile_commands.json \
$(HDR_DIR)/version.h .cache
pristine: clean
@echo "$(COLOR_YELLOW)[Running pristine clean]$(COLOR_RESET)"
@find . -name '.DS_Store' -delete
@find . -name '*~' -delete
@find . -name '*.swp' -delete
@if git rev-parse --is-inside-work-tree >/dev/null 2>&1; then \
echo "$(COLOR_YELLOW)[Git clean]$(COLOR_RESET)"; \
git clean -xfd; \
else \
echo "$(COLOR_YELLOW)[Not a git repo, skipping git clean]$(COLOR_RESET)"; \
fi
# Build final normal binary
$(TARGET): $(OBJS) | $(BINDIR)
@echo "$(COLOR_YELLOW)[Linking]$(COLOR_RESET) $@"
@$(CC) $(CFLAGS) $^ -o $@
# Build object files (depends on version_header and build/)
$(OBJDIR)/%.o: $(SRC_DIR)/%.c version_header | $(OBJDIR)
@echo "$(COLOR_GREEN)[Compiling]$(COLOR_RESET) $<"
@$(CC) $(CFLAGS) -MMD -c $< -o $@
# Create build and bin folders if needed
$(OBJDIR) $(BINDIR):
@mkdir -p $@
# Development tools
.PHONY: format tidy compile_commands
format:
@clang-format -i $(SRCS) $(HDRS)
tidy:
@$(CLANG_TIDY) $(SRCS) $(HDRS) \
--header-filter='^src/|^include/' \
--system-headers=false -- $(CFLAGS)
compile_commands:
@echo "$(COLOR_YELLOW)[Checking for compile_commands updates]$(COLOR_RESET)"
@if [ ! -f compile_commands.json ]; then \
echo "$(COLOR_GREEN)[Generating fresh compile_commands.json]$(COLOR_RESET)"; \
bear -- make clean all; \
else \
if find $(SRC_DIR) $(HDR_DIR) -type f \( -name '*.c' -o -name '*.h' \) \
-newer compile_commands.json | grep . >/dev/null; then \
echo "$(COLOR_GREEN)[Sources changed. Regenerating compile_commands.json]$(COLOR_RESET)"; \
bear -- make clean all; \
else \
echo "$(COLOR_GREEN)[Sources unchanged. Skipping regenerate]$(COLOR_RESET)"; \
fi \
fi
# Advanced builds
.PHONY: release asan
release: CFLAGS := $(DEVFLAGS) $(RELEASE_FLAGS) $(INCLUDES)
release: clean version_header $(RELEASE_TARGET)
@echo "$(COLOR_YELLOW)[Release build complete]$(COLOR_RESET)"
$(RELEASE_TARGET): $(OBJS) | $(BINDIR)
@echo "$(COLOR_YELLOW)[Linking Release]$(COLOR_RESET) $@"
@$(CC) $(CFLAGS) $^ -o $@
asan: CFLAGS += $(ASAN_FLAGS)
asan: clean $(ASAN_TARGET)
@echo "$(COLOR_YELLOW)[Running ASan Binary]$(COLOR_RESET)"
@./$(ASAN_TARGET)
$(ASAN_TARGET): $(OBJS) | $(BINDIR)
@echo "$(COLOR_YELLOW)[Linking ASan]$(COLOR_RESET) $@"
@$(CC) $(CFLAGS) $^ -o $@
# Version header generation
version_header:
@echo "$(COLOR_GREEN)[Generating version.h]$(COLOR_RESET)"
@mkdir -p $(HDR_DIR)
@echo '#pragma once' > $(HDR_DIR)/version.h
@echo '#define PROJECT_VERSION "$(VERSION)"' >> $(HDR_DIR)/version.h
# Help
.PHONY: help
help:
@echo "Usage: make [target]"
@echo ""
@echo "Available targets:"
@grep -E '^[a-zA-Z_-]+:.*' Makefile | grep -v '\.o:' | \
sed 's/:.*//' | sort | uniq
# Automatically include dependency files
-include $(DEPS)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment