-
Notifications
You must be signed in to change notification settings - Fork 0
/
GNUmakefile
172 lines (129 loc) · 5.48 KB
/
GNUmakefile
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
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
.SECONDARY:
APP = hello
#LDLIBS +=
#LDFLAGS +=
OBJS = hello.o main.o
#To add libraries to a test, use the "unitname/testname_LDLIBS" variable:
#hello/hello_LDLIBS=-lm
#hello/hello_LDFLAGS=
#Same goes to integration test:
#apptest1_LDLIBS=-lm
CLEAN_MORE =
#These defaults are really aggressive. You may want to tweak them.
WNO_ERROR = -Wno-error=unused-variable -Wno-error=unused-parameter
CFLAGS += -Wall -Wextra -Werror -std=c99 -pedantic-errors $(WNO_ERROR) -fPIC -ggdb
VALGRIND_EXTRA = --suppressions=/dev/null
#CPPCHECK_EXTRA = --suppress=...
SPLINT_EXTRA = -unrecog -fullinitblock -initallelements
#Strictly speaking you should rebuild your entire project if you change the
#GNUmakefile, but it can be quite cumbersome if your project is really big
#and you are debugging or hacking the GNUmakefile.
REBUILD_ON=GNUmakefile
# ===== MODIFICATIONS SHOULD NOT BE NEEDED BELOW THIS LINE =====
CC = gcc
VALGRIND_LINE = valgrind --error-exitcode=255 --leak-check=full -q --track-origins=yes
CPPCHECK_LINE = cppcheck --error-exitcode=1 --std=c99 --quiet
CLANG_LINE = clang --analyze -pedantic
SPLINT_LINE = splint +quiet -weak
# Disable builtin rules. This lets us avoid all kinds of surprises.
.SUFFIXES:
# ===== MODIFICATIONS SHOULD REALLY NOT BE NEEDED BELOW THIS LINE =====
# Copyright (c) 2013, Octavio Alvarez <alvarezp@alvarezp.com>
# Released under the Simplified BSD License. See the LICENSE file.
# Automatic dependency generation adapted from
# http://www.scottmcpeak.com/autodepend/autodepend.html
ifeq ($(.DEFAULT_GOAL),)
.DEFAULT_GOAL := $(APP)
endif
APP_TESTS = $(wildcard tests/*.t.c)
APP_TESTS_OBJ = $(patsubst tests/%.t.c,.caddeus/testobj/%.to,$(APP_TESTS))
APP_TESTS_BIN = $(patsubst tests/%.t.c,.caddeus/testbin/%.t,$(APP_TESTS))
APP_TESTS_TS = $(patsubst tests/%.t.c,.caddeus/timestamps/%.ts,$(APP_TESTS))
APP_TESTS_TT = $(wildcard tests/*.tt)
APP_TESTS_TTS = $(patsubst tests/%.tt,.caddeus/timestamps/%.tts,$(APP_TESTS_TT))
OBJ_TESTS = $(foreach d,$(patsubst %.o,tests/%/*.t.c,$(OBJS)),$(wildcard $(d)))
OBJ_TESTS_OBJ = $(patsubst tests/%.t.c,.caddeus/testobj/%.to,$(OBJ_TESTS))
OBJ_TESTS_BIN = $(patsubst tests/%.t.c,.caddeus/testbin/%.t,$(OBJ_TESTS))
OBJ_TESTS_TS = $(patsubst tests/%.t.c,.caddeus/timestamps/%.ts,$(OBJ_TESTS))
DONT_HAVE_VALGRIND = $(if $(shell which valgrind),,y)
VALGRIND = $(if $(or $(DONT_HAVE_VALGRIND),$(SKIP_VALGRIND)),,$(VALGRIND_LINE) $(VALGRIND_EXTRA))
DONT_HAVE_CPPCHECK = $(if $(shell which cppcheck),,y)
CPPCHECK = $(if $(or $(DONT_HAVE_CPPCHECK),$(SKIP_CPPCHECK)),true '-- skipping Cppcheck --',$(CPPCHECK_LINE) $(CPPCHECK_EXTRA))
DONT_HAVE_CLANG = $(if $(shell which clang),,y)
CLANG = $(if $(or $(DONT_HAVE_CLANG),$(SKIP_CLANG)),true '-- skipping Clang --',$(CLANG_LINE) $(CLANG_EXTRA))
DONT_HAVE_SPLINT = $(if $(shell which splint),,y)
SPLINT = $(if $(or $(DONT_HAVE_SPLINT),$(SKIP_SPLINT)),true '-- skipping Splint --',$(SPLINT_LINE) $(SPLINT_EXTRA))
DEFAULT_TIMEOUT=0
ifdef TIMEOUT
DEFAULT_TIMEOUT=$(TIMEOUT)
endif
.PHONY : strict
strict: $(OBJ_TESTS_TS) $(APP_TESTS_TS) $(APP_TESTS_TTS) $(APP)
@echo
@echo "Strict build completed successfully."
.PHONY : check
check: $(APP) $(OBJ_TESTS_TS) $(APP_TESTS_TS) $(APP_TESTS_TTS)
@echo
@echo "Test suite completed successfully."
.PHONY : cheat
cheat:
mkdir -p $(foreach ts,$(OBJ_TESTS_TS) $(APP_TESTS_TS) $(APP_TESTS_TTS),$(dir $(ts)))
touch $(foreach ts,$(OBJ_TESTS_TS) $(APP_TESTS_TS) $(APP_TESTS_TTS),$(ts))
@echo
@echo "Test suite timestamps generated successfully."
# Pull in dependency info for existing .o and .t files.
-include $(patsubst %.o,.caddeus/dependencies/%.d,$(OBJS))
-include $(patsubst .caddeus/testobj/%.to,.caddeus/dependencies/tests/%.t.d,$(OBJ_TESTS_OBJ) $(APP_TESTS_OBJ))
# All lower targets depend on $(REBUILD_ON) so everything rebuilds if $(REBUILD_ON)
# changes.
$(REBUILD_ON):
$(APP): $(OBJS)
@echo -e '\n'===== $@, building app...
$(CC) $(LDFLAGS) $(OBJS) -o $(APP) $(LDLIBS)
# Compile plus generate dependency information.
%.o: %.c $(REBUILD_ON)
@echo -e '\n'===== $@, building module...
$(CPPCHECK) $<
$(SPLINT) $<
@mkdir -p .caddeus/clang/$(*D)
$(CLANG) $(CFLAGS) -o .caddeus/clang/$*.plist $<
$(CC) $(CFLAGS) -o $@ -c $<
@echo -e '\n'===== $@, generating dependency information...
@mkdir -p .caddeus/dependencies/$(*D)
$(CC) $(CPPFLAGS) $(CFLAGS) -M $< | sed '1s,^\(.*\).o:,$*.o:,' \
> .caddeus/dependencies/$*.d
.caddeus/timestamps/%.ts: .caddeus/testbin/%.t
@echo -e '\n'===== running test \"$*\" with timeout=$(DEFAULT_TIMEOUT)...
@mkdir -p $(@D)
timeout $(DEFAULT_TIMEOUT) $(VALGRIND) $< && touch $@
.caddeus/timestamps/%.tts: tests/%.tt $(APP)
@echo -e '\n'===== running test \"$*\" test with timeout=$(DEFAULT_TIMEOUT)...
@mkdir -p $(@D)
timeout $(DEFAULT_TIMEOUT) $< && touch $@
.caddeus/testobj/%.to: tests/%.t.c $(REBUILD_ON)
@echo -e '\n'===== $@, building test module...
$(CPPCHECK) -I. $<
$(SPLINT) -I. $<
@mkdir -p .caddeus/clang/tests/$(*D)
$(CLANG) $(CFLAGS) -I. -o .caddeus/clang/tests/$*.t.plist $<
@mkdir -p $(@D)
$(CC) $(CFLAGS) -I. -o $@ -c $<
@echo -e '\n'===== $@, generating dependency information...
@mkdir -p .caddeus/dependencies/tests/$(*D)
$(CC) $(CPPFLAGS) $(CFLAGS) -I. -M $< | sed '1s,^\(.*\).t.o:,$@:,' \
> .caddeus/dependencies/tests/$*.t.d
.caddeus/testbin/%.t: .caddeus/testobj/%.to
@echo -e '\n'===== $@, building test...
@mkdir -p $(@D)
$(CC) $($*_LDFLAGS) $^ -o $@ $($*_LDLIBS)
.PHONY : clean
clean:
@echo -e '\n'===== Cleaning...
rm -fr .caddeus
rm -f $(APP)
rm -f $(OBJS)
rm -f $(CLEAN_MORE)
.PHONY : force
force:
$(MAKE) clean
$(MAKE)