-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmakefile
More file actions
155 lines (119 loc) · 4.93 KB
/
Copy pathmakefile
File metadata and controls
155 lines (119 loc) · 4.93 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
152
153
154
155
#=============================================
# 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)
# =====================================================
# Recursive source discovery for everything under src/
# =====================================================
CPPM_SRCS := $(shell find $(SRC_DIR) -type f -name '*.cppm' | sort)
CPP_SRCS := $(shell find $(SRC_DIR) -type f -name '*.cpp' | sort)
MODULE_SRCS := $(CPPM_SRCS)
MODULE_OBJS := $(patsubst $(SRC_DIR)/%.cppm,$(OBJ_DIR)/%.o,$(MODULE_SRCS))
CPP_OBJS := $(patsubst $(SRC_DIR)/%.cpp,$(OBJ_DIR)/%.o,$(CPP_SRCS))
ALL_OBJS := $(MODULE_OBJS) $(CPP_OBJS)
# Point linker/consumers at every discovered prebuilt module.
LINK_MOD_FLAGS := $(foreach src,$(MODULE_SRCS),-fmodule-file=$(basename $(notdir $(src)))=$(MOD_DIR)/$(patsubst $(SRC_DIR)/%.cppm,%.pcm,$(src)))
# 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 bench bench-debug bench-release bench-lto bench-instrument clean docs clean_all bear
N ?= 1000
ARGS ?= 2015 2
all: $(TARGET)
debug:
@$(MAKE) MODE=debug all
release:
@$(MAKE) MODE=release all
lto:
@$(MAKE) MODE=lto all
instrument:
@$(MAKE) MODE=instrument all
bench: $(MODE)
@./bench_nanos.sh $(N) $(MODE) $(ARGS)
bench-debug: debug
@./bench_nanos.sh $(N) debug $(ARGS)
bench-release: release
@./bench_nanos.sh $(N) release $(ARGS)
bench-lto: lto
@./bench_nanos.sh $(N) lto $(ARGS)
bench-instrument: instrument
@./bench_nanos.sh $(N) instrument $(ARGS)
# 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: Compile any module interface unit discovered under src/
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.cppm
@$(MKDIR) $(dir $(MOD_DIR)/$*.pcm) $(@D) $(if $(GENERATE_COMPDB),$(COMPDB_DIR))
$(CXX) $(CXXFLAGS) $(MOD_FLAGS) $(LINK_MOD_FLAGS) $(MJFLAGS) -fmodule-output=$(MOD_DIR)/$*.pcm -c $< -o $@
# rule B: Compile any translation unit discovered under src/
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.cpp $(MODULE_OBJS)
@$(MKDIR) $(@D) $(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)