-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmakefile
More file actions
151 lines (119 loc) · 5.53 KB
/
Copy pathmakefile
File metadata and controls
151 lines (119 loc) · 5.53 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
#=============================================
# Configuration and target swapping
#=============================================
.DEFAULT_GOAL := all
# Internal build mode selector (user-facing entry points are make targets).
MODE ?= debug
# Directory configuration
SRC_DIR := src
BUILD_DIR := build/$(MODE)
MOD_DIR := $(BUILD_DIR)/modules
OBJ_DIR := $(BUILD_DIR)/obj
DOC_DIR := docs
COMPDB_DIR := $(BUILD_DIR)/compdb
# Cross-platform utilities
RM := rm -rf
MKDIR := mkdir -p
# Binary outputs
TARGET := build/aoc_worker_$(MODE)
DOXYFILE := docs/Doxyfile
COMPDB_FILE := compile_commands.json
#=============================================
# Toolchain & hardware-aware compilation flags
#=============================================
CXX := clang++
BASE_FLAGS := -std=c++23 -fno-exceptions -fno-rtti -Wall -Wextra -Wpedantic
ifeq ($(MODE), release)
# High optimization release
CXXFLAGS := $(BASE_FLAGS) -O3 -march=native -DNDEBUG
else ifeq ($(MODE), lto)
# High optimization release with full LTO
CXXFLAGS := $(BASE_FLAGS) -O3 -march=native -DNDEBUG -flto=full
else ifeq ($(MODE), instrument)
# Sanitizer & Instrumentation matrix (bounds, memory, UB)
# Note: Banned raw new/delete means ASan tracks your OS file reads and Arena bounds
CXXFLAGS := $(BASE_FLAGS) -O0 -g -fsanitize=address,undefined -fno-omit-frame-pointer -DBUILD_INSTRUMENT
else
# Default Debug Target
MODE := debug
CXXFLAGS := $(BASE_FLAGS) -O0 -g -DBUILD_DEBUG
endif
# Clang module configuration flags
MOD_FLAGS := -fprebuilt-module-path=$(MOD_DIR)
MJFLAGS = $(if $(GENERATE_COMPDB),-MJ $(COMPDB_DIR)/$(subst /,_,$(patsubst $(OBJ_DIR)/%,%,$@)).json)
# =====================================================
# Dynamic Wildcard Ingestion & Automated File Layout
# =====================================================
# Ingest base engineering files from src/base/
BASE_SRCS := $(wildcard $(SRC_DIR)/base/core_*.cppm)
# Ingest nested puzzle paths: matches any year directory (y2015-y2025) and day files
PUZZLE_SRCS := $(wildcard $(SRC_DIR)/puzzles/y*/day*.cppm)
MAIN_SRCS := $(wildcard $(SRC_DIR)/main.cpp)
# Map discovered source paths directly into isolated build object targets
BASE_OBJS := $(patsubst $(SRC_DIR)/base/%.cppm,$(OBJ_DIR)/base/%.o,$(BASE_SRCS))
PUZZLE_OBJS := $(foreach src,$(PUZZLE_SRCS),$(patsubst $(SRC_DIR)/puzzles/%,$(OBJ_DIR)/puzzles/%,$(patsubst %.cppm,%.o,$(src))))
MAIN_OBJ := $(patsubst $(SRC_DIR)/%.cpp,$(OBJ_DIR)/%.o,$(MAIN_SRCS))
ALL_OBJS := $(BASE_OBJS) $(PUZZLE_OBJS) $(MAIN_OBJ)
MODULE_SRCS := $(BASE_SRCS) $(PUZZLE_SRCS)
# Dynamic Module File Flag Generator:
# Extracts module names from filenames and points Clang to their active .pcm caches
LINK_MOD_FLAGS := $(foreach src,$(BASE_SRCS),-fmodule-file=$(basename $(notdir $(src)))=$(MOD_DIR)/$(basename $(notdir $(src))).pcm) \
$(foreach src,$(PUZZLE_SRCS),-fmodule-file=$(basename $(notdir $(src)))=$(MOD_DIR)/$(basename $(notdir $(src))).pcm)
# Automatic module dependency extraction from `import <module>;` statements.
# Maps imported module names to local module object targets, so adding modules
# normally requires no makefile edits.
module_obj_from_name = $(patsubst $(SRC_DIR)/%.cppm,$(OBJ_DIR)/%.o,$(firstword $(filter %/$(1).cppm,$(MODULE_SRCS))))
imports_of_src = $(shell sed -n 's/^[[:space:]]*import[[:space:]]\([A-Za-z0-9_]*\)[[:space:]]*;.*/\1/p' $(1))
module_import_obj_deps = $(strip $(foreach m,$(call imports_of_src,$(1)),$(call module_obj_from_name,$(m))))
$(foreach src,$(MODULE_SRCS),$(eval $(patsubst $(SRC_DIR)/%.cppm,$(OBJ_DIR)/%.o,$(src)): $(call module_import_obj_deps,$(src))))
#====================================
# Phase execution and meta rules
#====================================
.PHONY: all debug release lto instrument clean docs clean_all bear
all: $(TARGET)
debug:
@$(MAKE) MODE=debug all
release:
@$(MAKE) MODE=release all
lto:
@$(MAKE) MODE=lto all
instrument:
@$(MAKE) MODE=instrument all
# The compilation database target: rebuilds with Clang -MJ fragments so
# module interface units are recorded correctly in compile_commands.json.
bear:
@$(RM) $(COMPDB_FILE)
@$(RM) $(BUILD_DIR)
@$(MKDIR) $(COMPDB_DIR)
@$(MAKE) MODE=$(MODE) GENERATE_COMPDB=1 all
@{ printf '[\n'; find $(COMPDB_DIR) -type f -name '*.json' | sort | xargs -r cat; } | sed '$$s/,$$//' > $(COMPDB_FILE)
@printf '\n]\n' >> $(COMPDB_FILE)
# final link
$(TARGET): $(ALL_OBJS)
@$(MKDIR) build
$(CXX) $(CXXFLAGS) $(ALL_OBJS) -o $(TARGET)
# rule A: Automatically compile core utilities inside src/base
$(OBJ_DIR)/base/core_%.o: $(SRC_DIR)/base/core_%.cppm
@$(MKDIR) $(MOD_DIR) $(OBJ_DIR)/base $(if $(GENERATE_COMPDB),$(COMPDB_DIR))
$(CXX) $(CXXFLAGS) $(MOD_FLAGS) $(LINK_MOD_FLAGS) $(MJFLAGS) -fmodule-output=$(MOD_DIR)/core_$*.pcm -c $< -o $@
# rule B: Automatically compile multi-year nested Puzzles
# Matches objects like build/debug/obj/puzzles/y2020/day01.o
$(OBJ_DIR)/puzzles/y%/day%.o: $(SRC_DIR)/puzzles/y%/day%.cppm $(BASE_OBJS)
@$(MKDIR) $(MOD_DIR) $(OBJ_DIR)/puzzles/y$* $(if $(GENERATE_COMPDB),$(COMPDB_DIR))
$(CXX) $(CXXFLAGS) $(MOD_FLAGS) $(LINK_MOD_FLAGS) $(MJFLAGS) -fmodule-output=$(MOD_DIR)/day$*.pcm -c $< -o $@
# rule C: The Application Entry Point Execution Block
$(OBJ_DIR)/main.o: $(SRC_DIR)/main.cpp $(BASE_OBJS) $(PUZZLE_OBJS)
@$(MKDIR) $(OBJ_DIR) $(if $(GENERATE_COMPDB),$(COMPDB_DIR))
$(CXX) $(CXXFLAGS) $(LINK_MOD_FLAGS) $(MJFLAGS) -c $< -o $@
# ===============================
# Tooling & Cleanup Operations
# ===============================
docs:
@$(MKDIR) $(DOC_DIR)
doxygen $(DOXYFILE)
clean:
$(RM) build/$(MODE)
$(RM) $(TARGET)
clean_all:
$(RM) build
$(RM) $(COMPDB_FILE)