-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtemplate_Makefile
282 lines (200 loc) · 5.92 KB
/
template_Makefile
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
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
# XZ Make Template
# credits to tutorial: https://makefiletutorial.com/
# to debug
#make --debug --print-data-base
# `make` is constructed/separated by rules
# this will be the first rule, the default goal, until to next `target`
# or, set by `.DEFAULT_GOAL`
target: prerequisite prereq2
echo "recipe"
echo ">$(one)<, var one will be found if it is set"
# "TAB" is the default prefix, otherwise set by `.RECIPEPREFIX`
prerequisite:
echo "this will be run before 'target': prerequisite"
prereq2::
echo "double colon rule: prerequisites -- first"
prereq2::
echo "double colon rule: prerequisites -- second"
# intermediate files will be deleted after `make`
# https://www.gnu.org/software/make/manual/html_node/Chained-Rules.html
#
#.INTERMEDIATE:
#.NOTINTERMEDIATE:
#.PRECIOUS: %.o
# Recursive variable. This will print "later" below
one = one ${later_variable}
# Simply expanded variable. This will not print "later" below
two := two ${later_variable}
later_variable = later
# results:
#> one later
#> two
test_var_recursive:
echo $(one)
echo $(two)
# explanation for different ways to define variable
#immediate = deferred
#immediate ?= deferred
#immediate := immediate
#immediate ::= immediate
#immediate :::= immediate-with-escape
#immediate += deferred or immediate
#immediate != immediate
# only sets variables if they have not yet been set
three = hello
three ?= will not be set
four ?= will be set
# results:
#> hello
#> will be set
test_var_whether_set:
echo $(three)
echo $(four)
# space in after `hello` will be kept until to comments
with_spaces = hello # with_spaces has many spaces after "hello"
after = $(with_spaces)there # "hello there "
multiline = line1 \
line2
mutliresult = $(multiline) # "line1 line2 "
# any whitespaces preceding or after `\` will be condensed to one-whitespace
# however, `space1` will have no space, `space2` will have one space
nullstring =
space1 = $(nullstring)
space2 = $(nullstring) # a space inserted
# results:
#> =hello there=
#> ==
#> = =
test_var_space:
echo "=$(after)="
echo "=$(space1)="
echo "=$(space2)="
xzhey: xzone xztwo
# Outputs "xzhey", since this is the first target
echo $@
# Outputs all prerequisites newer than the target
echo $?
# Outputs all prerequisites
echo $^
touch hey
# use `make -s` to be silent
xzone:
@echo "This make line will not be printed"
echo "xzone"
xztwo:
echo "xztwo"
a := one two # a is set to the string "one two"
b := 'one two' # b is set to the string "'one two'"
# variable should be called by using ${var} or $(var)
c := $(b)
# $@ is an automatic variable that contains the target name.
f1.o f2.o:
echo $@
# Equivalent to:
# f1.o:
# echo f1.o
# f2.o:
# echo f2.o
thing_wrong := *.o # Don't do this! '*' will not get expanded
thing_right := $(wildcard *.o)
all2: pone ptwo pthree pfour
# Fails, because $(thing_wrong) is the string "*.o"
pone: $(thing_wrong)
# Stays as *.o if there are no files that match this pattern
ptwo: *.o
# Works as you would expect! In this case, it does nothing.
pthree: $(thing_right)
# Same as rule three
pfour: $(wildcard *.o)
# implicit rules
#
# Compiling a C program:
# `n.o` is made automatically from `n.c` with a command of the form $(CC) -c $(CFLAGS) $(CFLAGS)
# Compiling a C++ program:
# `n.o` is made automatically from `n.cc` or `n.cpp` with a command of the form $(CXX) -c $(CPPFLAGS) $(CXXFLAGS)
# Linking a single object file:
# `n` is made automatically from `n.o` by running the command $(CC) $(LDFLAGS) n.o $(LOADLIBES) $(LDLIBS)
CC = gcc # Flag for implicit rules
CFLAGS = -g # Flag for implicit rules. Turn on debug info
# Implicit rule #1: blah is built via the C linker implicit rule
# Implicit rule #2: blah.o is built via the C compilation implicit rule, because blah.c exists
blah: blah.o
# `nice.c` will be constructed by pattern rule
blah.c: nice.c
echo "in blah.c"
%.c:
echo "pattern rule for: *.c, if the target is not found"
# results:
#> 1 /home/xiang/test-make
#> 2 /home/xiang/test-make
#> 3 /home/xiang
#> 4 /home/xiang
test_subshell:
echo 1 `pwd`
cd ..
# The cd above does not affect this line, because each command is effectively run in a new shell
echo 2 `pwd`
# This cd command affects the next because they are on the same line
cd ..; echo 3 `pwd`
# Same as above
cd ..; \
echo 4 `pwd`
# add `-` before a command to suppress the error
test_error_handler:
# This error will be printed but ignored, and make will continue to run
-not_exist_command
# `.EXPORT_ALL_VARIABLES` exports all variables
# otherwise, use `export var` for subshell `make`
onef = export blah="I was set!"; echo $$blah
define twof
export blah=set
echo $$blah
endef
# results:
#> This prints 'I was set'
#> I was set!
#> This does not print 'I was set' because each command runs in a separate shell
#> [nothing]
test_list_commands:
@echo "This prints 'I was set'"
@$(onef)
@echo "This does not print 'I was set' because each command runs in a separate shell"
@$(twof)
# use functions with `$(fn, arguments)`
# Link: https://www.gnu.org/software/make/manual/html_node/Functions.html
foot = ok
test_ifeq:
ifeq ($(foot), ok)
echo "foot equals ok"
else
echo "nope"
endif
# `.PHONY` will prevent from confusing the phony target with a file name
some_file:
touch x_some_file
touch x_file_clean
.PHONY: x_clean
x_clean:
rm -f x_some_file
rm -f x_clean
# all var `basename.o` will be replaced to `basename.d`
# in the string substituted `$(VAR:pattern=replacement)`
STRIPPED_STR := $(ALL_TARGETS:.o=.d)
#
# Simple Makefile
#
CC := g++
CFLAGS := -Wall -g
TARGET := test
# $(wildcard *.cpp /xxx/xxx/*.cpp): get all .cpp files from the current directory and dir "/xxx/xxx/"
SRCS := $(wildcard *.cpp)
# $(patsubst %.cpp,%.o,$(SRCS)): substitute all ".cpp" file name strings to ".o" file name strings
OBJS := $(patsubst %.cpp,%.o,$(SRCS))
all: $(TARGET)
$(TARGET): $(OBJS)
$(CC) -o $@ $^
%.o: %.cpp
$(CC) $(CFLAGS) -c $<
clean:
rm -rf $(TARGET) *.o
.PHONY: all clean