-
Notifications
You must be signed in to change notification settings - Fork 19
Expand file tree
/
Copy pathMakefile
More file actions
132 lines (114 loc) · 4.89 KB
/
Makefile
File metadata and controls
132 lines (114 loc) · 4.89 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
CC ?= clang
STD = c17
AR = ar
TARGET = rayforce
# Version is authoritative in include/rayforce.h — extract it here
VERSION_MAJOR := $(shell grep 'RAY_VERSION_MAJOR' include/rayforce.h | head -1 | awk '{print $$3}')
VERSION_MINOR := $(shell grep 'RAY_VERSION_MINOR' include/rayforce.h | head -1 | awk '{print $$3}')
VERSION_PATCH := $(shell grep 'RAY_VERSION_PATCH' include/rayforce.h | head -1 | awk '{print $$3}')
VERSION = $(VERSION_MAJOR).$(VERSION_MINOR).$(VERSION_PATCH)
GIT_HASH := $(shell git rev-parse --short HEAD 2>/dev/null || echo "unknown")
BUILD_DATE := $(shell date -u +%Y-%m-%d)
WARNS = -Wall -Wextra -Werror -Wstrict-prototypes -Wno-unused-parameter
DEFS = -DRAYFORCE_GIT_COMMIT=\"$(GIT_HASH)\" -DRAYFORCE_BUILD_DATE=\"$(BUILD_DATE)\"
INCLUDES = -Iinclude -Isrc
UNAME_S := $(shell uname -s)
DEBUG_CFLAGS = -fPIC $(WARNS) -std=$(STD) -g -O0 -march=native -DDEBUG \
-fsanitize=address,undefined -fno-omit-frame-pointer
RELEASE_CFLAGS = -fPIC $(WARNS) -std=$(STD) -O3 -march=native \
-funroll-loops -fomit-frame-pointer -fno-math-errno
# Coverage: clang source-based instrumentation. Sanitizers conflict
# with the profile runtime, so we drop them; -O0 keeps line numbers
# and avoids dead-code regions getting marked uncovered for the
# wrong reason. See `make coverage` below.
COVERAGE_CFLAGS = -fPIC $(WARNS) -std=$(STD) -g -O0 -march=native -DDEBUG \
-fno-omit-frame-pointer -fprofile-instr-generate -fcoverage-mapping
COVERAGE_LDFLAGS = -fprofile-instr-generate -fcoverage-mapping
ifeq ($(UNAME_S),Linux)
LIBS = -lm -lpthread
RELEASE_LDFLAGS = -Wl,--gc-sections -Wl,--as-needed
else
LIBS = -lm
RELEASE_LDFLAGS = -Wl,-dead_strip
endif
DEBUG_LDFLAGS = -fsanitize=address,undefined
CFLAGS = $(DEBUG_CFLAGS)
LDFLAGS = $(DEBUG_LDFLAGS)
# Sources
LIB_SRC = $(wildcard src/*/*.c)
LIB_SRC := $(filter-out src/app/main.c, $(LIB_SRC))
LIB_OBJ = $(LIB_SRC:.c=.o)
MAIN_SRC = src/app/main.c
MAIN_OBJ = $(MAIN_SRC:.c=.o)
TEST_SRC = $(wildcard test/*.c)
TEST_OBJ = $(TEST_SRC:.c=.o)
# Default target
default: debug
%.o: %.c
$(CC) -c $(CFLAGS) $(DEFS) $(INCLUDES) -o $@ $<
# Main binary — shared by debug/release/test (test/rfl/system/ipc_diff.rfl
# spawns ./$(TARGET) as a server, so test depends on it too).
$(TARGET): $(LIB_OBJ) $(MAIN_OBJ)
$(CC) $(CFLAGS) -o $(TARGET) $(LIB_OBJ) $(MAIN_OBJ) $(LIBS) $(LDFLAGS)
# Debug build
debug: CFLAGS = $(DEBUG_CFLAGS)
debug: LDFLAGS = $(DEBUG_LDFLAGS)
debug: $(TARGET)
# Release build
release: CFLAGS = $(RELEASE_CFLAGS)
release: LDFLAGS = $(RELEASE_LDFLAGS)
release: $(TARGET)
# Static library
lib: CFLAGS = $(RELEASE_CFLAGS)
lib: $(LIB_OBJ)
$(AR) rc lib$(TARGET).a $(LIB_OBJ)
# Tests. Depends on $(TARGET) because test/rfl/system/ipc_diff.rfl
# spawns ./$(TARGET) as an IPC server via .sys.exec — both binaries
# must exist on disk and share the build flavour (sanitizers, coverage).
test: CFLAGS = $(DEBUG_CFLAGS)
test: LDFLAGS = $(DEBUG_LDFLAGS)
test: $(TARGET) $(LIB_OBJ) $(TEST_OBJ)
$(CC) $(CFLAGS) -o $(TARGET).test $(LIB_OBJ) $(TEST_OBJ) $(LIBS) $(LDFLAGS) -Itest
./$(TARGET).test
# Coverage report. Builds both binaries with clang source-based
# instrumentation, runs the test suite (writing one .profraw per
# process — the test binary AND every IPC server it spawns —
# thanks to LLVM_PROFILE_FILE='%p' giving each pid a unique file),
# merges, and emits an HTML report under coverage_html/.
#
# Requires clang + llvm-profdata + llvm-cov. Sanitizers are dropped
# for this build (incompatible with the profile runtime).
coverage:
@command -v clang >/dev/null || { echo "coverage: clang not found"; exit 1; }
@command -v llvm-profdata >/dev/null || { echo "coverage: llvm-profdata not found"; exit 1; }
@command -v llvm-cov >/dev/null || { echo "coverage: llvm-cov not found"; exit 1; }
$(MAKE) clean
rm -f cov-*.profraw default.profraw coverage.profdata
rm -rf coverage_html
LLVM_PROFILE_FILE='cov-%p.profraw' $(MAKE) test \
CC=clang \
DEBUG_CFLAGS='$(COVERAGE_CFLAGS)' \
DEBUG_LDFLAGS='$(COVERAGE_LDFLAGS)'
llvm-profdata merge -sparse cov-*.profraw -o coverage.profdata
llvm-cov show ./$(TARGET).test \
-instr-profile=coverage.profdata \
-format=html -output-dir=coverage_html \
-show-line-counts-or-regions \
-ignore-filename-regex='test/.*|/usr/.*'
@echo
@echo "=== coverage summary ==="
@llvm-cov report ./$(TARGET).test \
-instr-profile=coverage.profdata \
-ignore-filename-regex='test/.*|/usr/.*' 2>/dev/null | tail -3
@echo
@echo "→ coverage_html/index.html"
clean:
-rm -f $(LIB_OBJ) $(MAIN_OBJ) $(TEST_OBJ)
-rm -f $(TARGET) $(TARGET).test lib$(TARGET).a
-rm -rf build build_release
# Test-generated fixtures (see test/rfl/system/*.rfl) — should not linger after a run.
-rm -f rf_test_*.csv
# Coverage artefacts (see `make coverage`).
-rm -f cov-*.profraw default.profraw coverage.profdata
-rm -rf coverage_html
.PHONY: default debug release lib test coverage clean