...
1A quick primer on GNU Make syntax
2=================================
3
4This tries to cover the syntax that is hard to ctrl-f for in
5<https://www.gnu.org/software/make/manual/make.html> (err, hard to
6C-s for in `M-: (info "Make")`).
7
8 At the core is a "rule":
9
10 target: dependency1 dependency2
11 command to run
12
13 If `target` something that isn't a real file (like 'build', 'lint', or
14 'test'), then it should be marked as "phony":
15
16 target: dependency1 dependency2
17 command to run
18 .PHONY: target
19
20 You can write reusable "pattern" rules:
21
22 %.o: %.c
23 command to run
24
25 Of course, if you don't have variables for the inputs and outputs,
26 it's hard to write a "command to run" for a pattern rule. The
27 variables that you should know are:
28
29 $@ = the target
30 $^ = the list of dependencies (space separated)
31 $< = the first (left-most) dependency
32 $* = the value of the % glob in a pattern rule
33
34 Each of these have $(@D) and $(@F) variants that are the
35 directory-part and file-part of each value, respectively.
36
37 I think those are easy enough to remember mnemonically:
38 - $@ is where you should direct the output at.
39 - $^ points up at the dependency list
40 - $< points at the left-most member of the dependency list
41 - $* is the % glob; "*" is well-known as the glob char in other languages
42
43 Make will do its best to guess whether to apply a pattern rule for a
44 given file. Or, you can explicitly tell it by using a 3-field
45 (2-colon) version:
46
47 foo.o bar.o: %.o: %.c
48 command to run
49
50 In a non-pattern rule, if there are multiple targets listed, then it
51 is as if rule were duplicated for each target:
52
53 target1 target2: deps
54 command to run
55
56 # is the same as
57
58 target1: deps
59 command to run
60 target2: deps
61 command to run
62
63 Because of this, if you have a command that generates multiple
64 outputs, it _must_ be a pattern rule:
65
66 %.c %.h: %.y
67 command to run
68
69 Normally, Make crawls the entire tree of dependencies, updating a file
70 if any of its dependencies have been updated. There's a really poorly
71 named feature called "order-only" dependencies:
72
73 target: normal-deps | order-only-deps
74
75 Dependencies after the `|` are created if they don't exist, but if
76 they already exist, then don't bother updating them.
77
78Tips:
79-----
80
81 - Use absolute filenames; it's silly, but can often reduce headaches.
82 Use `$(OSS_HOME)` to spell the absolute filenames.
83
84 Though, this isn't so helpful in Emissary anymore. The main case
85 where this helps is when the same directory-specific Makefile might
86 be `include`d from several different top-level directories; as the
87 Helm chart Makefile used to be from the main Emissary Makefile, or
88 the Emissary Makefile used to be from Edge Stack. But Emissary no
89 longer does this.
90
91 - If you have a multiple-output command where the output files have
92 dissimilar names, have `%` be just the directory (the above tip
93 about using absolute filenames makes this easier--this is a real
94 pain if you have such a target in the top-level directory and
95 aren't using absolute filenames).
96
97 - It can be useful to use the 2-colon form of a pattern rule when
98 writing a rule for just one file; it lets you use `%` and `$*` to
99 avoid repeating yourself, which can be especially useful with long
100 filenames.
View as plain text