-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathpagurus.mk
More file actions
112 lines (105 loc) · 5.38 KB
/
pagurus.mk
File metadata and controls
112 lines (105 loc) · 5.38 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
# pagurus.mk — Drop-in Makefile include for whole-project pagurus borrow checking.
#
# ── Quick-start ────────────────────────────────────────────────────────────────
#
# 1. In your project Makefile, after defining CC, CFLAGS, and SOURCES:
#
# SOURCES = src/main.c src/widget.c src/util.c
# include /path/to/pagurus.mk
#
# 2. Run any of these targets:
#
# make pagurus-check # borrow-check all PAGURUS_SOURCES
# make pagurus-dry-run # inspect-only: all diagnostics, no output files
# make pagurus-clean # remove *.pagurus.c artefacts
#
# See the "Multi-file project integration" section in README.md for more details.
#
# ── Variables (override BEFORE the include line) ───────────────────────────────
#
# PAGURUS_PLUGIN Path to pagurus_plugin.so
# [default: <dir of pagurus.mk>/build/pagurus_plugin.so]
# PAGURUS_CLANG Clang executable [default: clang]
# PAGURUS_SOURCES C files to check [default: $(SOURCES) if set, else *.c]
# PAGURUS_CFLAGS Extra clang flags forwarded to each invocation
# [default: $(CFLAGS)]
# PAGURUS_JOBS Parallel check jobs [default: 1]
# PAGURUS_IR_PASS Set to 1 to also run the LLVM IR pass (-fpass-plugin=)
# [default: 0]
#
# ── Implementation notes ──────────────────────────────────────────────────────
#
# Each source file is checked independently. The plugin processes one
# translation unit per clang invocation, so all checks (E001–E021) that
# operate within a single file work correctly. Cross-file function
# summaries (return-alias, effect propagation) are available when the
# called function's *definition* is visible in the same translation unit
# or via an included header with inline definitions.
#
# For whole-project cross-TU accuracy, generate a compilation database
# with `bear make` and pass it to the `pagurus-check` script:
#
# bear make
# /path/to/pagurus-check --compile-db=compile_commands.json \
# --plugin=$(PAGURUS_PLUGIN)
# ── Resolve the directory containing this file ────────────────────────────────
_PAGURUS_MK_DIR := $(dir $(lastword $(MAKEFILE_LIST)))
# ── Configurable variables ────────────────────────────────────────────────────
PAGURUS_PLUGIN ?= $(_PAGURUS_MK_DIR)build/pagurus_plugin.so
PAGURUS_CLANG ?= clang
PAGURUS_SOURCES ?= $(if $(SOURCES),$(SOURCES),$(wildcard *.c))
PAGURUS_CFLAGS ?= $(CFLAGS)
PAGURUS_JOBS ?= 1
PAGURUS_IR_PASS ?= 0
# ── Derived flags ─────────────────────────────────────────────────────────────
_PAGURUS_BASE_FLAGS := -fplugin=$(PAGURUS_PLUGIN)
_PAGURUS_DRY_FLAGS := $(_PAGURUS_BASE_FLAGS) \
-Xclang -plugin-arg-pagurus -Xclang dry-run
_PAGURUS_IR_FLAGS := $(if $(filter 1,$(PAGURUS_IR_PASS)), \
-fpass-plugin=$(PAGURUS_PLUGIN) -g -O0,)
.PHONY: pagurus-check pagurus-dry-run pagurus-clean
## pagurus-check: Borrow-check all PAGURUS_SOURCES (compile mode).
## Writes <file>.pagurus.c alongside each source; errors cause non-zero exit.
pagurus-check:
@if [ ! -f "$(PAGURUS_PLUGIN)" ]; then \
echo "pagurus: plugin not found: $(PAGURUS_PLUGIN)"; \
echo " Build with: cd $(or $(_PAGURUS_MK_DIR),.) && mkdir -p build && cd build && cmake .. && make"; \
exit 1; \
fi
@echo "=== pagurus: checking $(words $(PAGURUS_SOURCES)) file(s) ==="
@_errors=0; \
for _f in $(PAGURUS_SOURCES); do \
_out=$$($(PAGURUS_CLANG) $(_PAGURUS_BASE_FLAGS) $(_PAGURUS_IR_FLAGS) \
$(PAGURUS_CFLAGS) -c "$$_f" -o /dev/null 2>&1 || true); \
_diags=$$(echo "$$_out" | grep -E 'E[0-9]{3}\[' || true); \
if [ -n "$$_diags" ]; then \
echo "$$_out"; \
_errors=$$((_errors+1)); \
fi; \
done; \
echo "=== pagurus: $$_errors file(s) with errors ==="; \
[ "$$_errors" -eq 0 ]
## pagurus-dry-run: Inspect all PAGURUS_SOURCES (dry-run mode).
## Reports all diagnostics including E020; does NOT write .pagurus.c files.
pagurus-dry-run:
@if [ ! -f "$(PAGURUS_PLUGIN)" ]; then \
echo "pagurus: plugin not found: $(PAGURUS_PLUGIN)"; \
exit 1; \
fi
@echo "=== pagurus dry-run: checking $(words $(PAGURUS_SOURCES)) file(s) ==="
@_errors=0; \
for _f in $(PAGURUS_SOURCES); do \
_out=$$($(PAGURUS_CLANG) $(_PAGURUS_DRY_FLAGS) $(_PAGURUS_IR_FLAGS) \
$(PAGURUS_CFLAGS) -c "$$_f" -o /dev/null 2>&1 || true); \
_diags=$$(echo "$$_out" | grep -E 'E[0-9]{3}\[' || true); \
if [ -n "$$_diags" ]; then \
echo "$$_out"; \
_errors=$$((_errors+1)); \
fi; \
done; \
echo "=== pagurus: $$_errors file(s) with diagnostics ==="; \
[ "$$_errors" -eq 0 ]
## pagurus-clean: Remove .pagurus.c output files produced by compile mode.
pagurus-clean:
@echo "=== pagurus: removing .pagurus.c files ==="
@find . -name '*.pagurus.c' ! -path './.git/*' -print -delete