english_knight - english_knight - A ninja replacement. | |
git clone git://bitreich.org/english_knight git://enlrupgkhuxnvlhsf6lc3fziv5h2h… | |
Log | |
Files | |
Refs | |
Tags | |
README | |
LICENSE | |
--- | |
english_knight (10124B) | |
--- | |
1 #!/bin/sh | |
2 | |
3 if [ -f Makefile -o -f makefile -o -f GNUmakefile ]; | |
4 then | |
5 make "$@" | |
6 exit $? | |
7 fi | |
8 | |
9 cat <<EOF | |
10 #[1]Seninha's notes | |
11 | |
12 A Template for Portable Idiomatic Makefiles | |
13 | |
14 [2]seninha.org | |
15 2022-04-07 | |
16 | |
17 In this post, I present the template I use to write portable, idiomatic | |
18 Makefiles for building C programs. | |
19 | |
20 I use ${MYVAR}, with curly braces, rather than $(MYVAR), with parenthese… | |
21 both notations are supported. In this document I identify two different … | |
22 the developer or Makefile author, who writes the Makefile; and the user … | |
23 package maintainer, who defines the proper variables and run make(1). | |
24 | |
25 The Project Files | |
26 | |
27 There are several files involved in the building process: the target fil… | |
28 built, the source files, and the intermediate files. They may be referen… | |
29 several times by different rules, so it is a good practice to name them … | |
30 variables. Suppose we're building a program called myprog composed of th… | |
31 modules. These are the variables to be defined: | |
32 PROG = myprog | |
33 SRCS = main.c parse.c util.c | |
34 OBJS = main.o parse.o util.o | |
35 | |
36 The varialbe PROG is the final file; SRCS lists the source files; and OB… | |
37 the intermediate, object files. Note that both the list of source files … | |
38 object files are almost equal, differing only by the extension of the fi… | |
39 POSIX make(1) has a notation for changing the ending of each word in a v… | |
40 In order to avoid repeating ourselves, we can use this notation to define | |
41 ${OBJS}. | |
42 PROG = myprog | |
43 SRCS = main.c parse.c util.c | |
44 OBJS = ${SRCS:.c=.o} | |
45 | |
46 We want to build our program when we call make without any arguments. To… | |
47 this, the first target should be ${PROG} itself. However, it is a common | |
48 practice to use the target all to build the final files. So the first ta… | |
49 all, which just has ${PROG} as prerequisite. | |
50 all: ${PROG} | |
51 | |
52 Next we need to declare the dependencies between the program modules. Th… | |
53 done with rules without commands. | |
54 main.o: parse.h util.h | |
55 parse.o: parse.h util.h | |
56 util.o: util.h | |
57 | |
58 The Compilation Rules | |
59 | |
60 The compilation process is split in two parts: generate the object files… | |
61 the source files, and generate the program from the object files. So we … | |
62 rules. | |
63 | |
64 The following rule builds object files (.o) from source files (.c). The … | |
65 a inference rule that declare each .c file to be the prerequisite of a | |
66 homonymous .o file. This notation is defined by POSIX and is, therefore, | |
67 portable (different from the %.o: %.c rule, which is a GNU extension). I… | |
68 command of an inference rule (and only in the command of an inference ru… | |
69 $< variable evaluates to the prerequisite file. | |
70 .c.o: | |
71 ${CC} -I/usr/X11R6/include ${CFLAGS} ${CPPFLAGS} -c $< | |
72 | |
73 We use the variable ${CC} to expand to the proper C compiler command. Th… | |
74 variable is set by default to the proper command. We should use this var… | |
75 rather than hardcoding it to gcc, for example. | |
76 | |
77 The variables ${CFLAGS} and ${CPPFLAGS} contains options that the user or | |
78 package maintainer wants to pass to the compiler or preprocessor. It is … | |
79 practice to define those variables in a Makefile; let the user (or packa… | |
80 maintainer) define them. Any option that must be passed to the compiler … | |
81 -I/usr/X11R6/include above) should be passed before those variables. If … | |
82 Makefile author, for example, define ${CFLAGS} to -I/usr/X11R6/include, … | |
83 this value may override the values set by the user, or the values set by… | |
84 user may shadow the option set by the Makefile author. | |
85 | |
86 The following rule links all object files into the program. We define ${… | |
87 be the prerequisites of ${PROG}. The $@ variable evaluates to the target… | |
88 (${PROG} in our case). Since this is not an inference rule, the $< varia… | |
89 cannot be used; we must write ${OBJS} both in the rule and in the comman… | |
90 ${PROG}: ${OBJS} | |
91 ${CC} -o $@ ${OBJS} -L/usr/X11R6/lib -lX11 ${LDFLAGS} | |
92 | |
93 The variable ${LDFLAGS} contains options that the user or package mainta… | |
94 wants to pass to the linker. Again, it is a bad practice to define it in… | |
95 Makefile. The options -L/usr/X11R6/lib and -lX11 are passed before this … | |
96 (so the user can override or increment them if necessary). | |
97 | |
98 The Installation rules | |
99 | |
100 Your Makefile may include rules for installing the final files in the sy… | |
101 this example, two files are installed, ${PROG} (the final, compiled prog… | |
102 and ${PROG}.1 (the manpage, named as the program followed by .1). The fo… | |
103 rule performs the installation. | |
104 PREFIX = /usr/local | |
105 MANPREFIX = ${PREFIX}/share/man | |
106 | |
107 install: all | |
108 mkdir -p ${DESTDIR}${PREFIX}/bin | |
109 mkdir -p ${DESTDIR}${MANPREFIX}/man1 | |
110 install -m 755 ${PROG} ${DESTDIR}${PREFIX}/bin/${PROG} | |
111 install -m 644 ${PROG}.1 ${DESTDIR}${MANPREFIX}/man1/${PROG}.1 | |
112 | |
113 Before installing, the program should have been built; therefore all mus… | |
114 prerequisite for install. | |
115 | |
116 The user or package maintainer can set the variable ${DESTDIR} to specif… | |
117 different installation destination. This variable must be prepended to e… | |
118 installation path; and the Makefile author should not define it (it is l… | |
119 the user or package maintainer to define it). Note that there is no bar | |
120 separating ${DESTDIR} from what follows, because the ${PREFIX} and ${MAN… | |
121 variables should already begin with a bar. | |
122 | |
123 The Makefile author, however, is expected to define two variables pointi… | |
124 installation prefixes: ${PREFIX}, pointing to the general installation p… | |
125 and ${MANPREFIX}, pointing to the manual page installation prefix. There… | |
126 other commonly defined prefixes, such as ${bindir}, set to ${PREFIX}/bin… | |
127 user or package maintainer can then invoke make(1) with those variables … | |
128 to different prefixes. On most GNU/Linux systems, for example, ${PREFIX}… | |
129 assigned to /usr; and on OpenBSD, ${MANPREFIX} is assigned to ${PREFIX}/… | |
130 (without the share/ part). | |
131 | |
132 The variables ${PREFIX} and ${MANPREFIX} are not automatically assigned,… | |
133 they can be changed by the user or package maintainer. These variables a… | |
134 commonly assigned in the Makefile by the Makefile author with the ?= ope… | |
135 which assign them only if not already defined, rather than with the comm… | |
136 operator. Thus, the values of these variables can be inherited from the | |
137 environment, and the user need not have to assign them on each invocatio… | |
138 operator is a non-POSIX extension, however, although supported by both G… | |
139 BSD make implementations. | |
140 | |
141 Looking back at the installation commands, we first use mkdir(1) to crea… | |
142 destination directories, and then use install(1) to install them. We cou… | |
143 simply call install with the -D flag, which automatically creates the | |
144 destination directories if necessary. However, this option is an extensi… | |
145 is not supported by some implementations (such as FreeBSD's). Remember to | |
146 install each file with its proper permission modes with the -m option. | |
147 | |
148 The Makefile author can also create a uninstallation rule, which simply … | |
149 the files from their destination directories. | |
150 uninstall: | |
151 rm ${DESTDIR}${PREFIX}/bin/${PROG} | |
152 rm ${DESTDIR}${MANPREFIX}/man1/${PROG}.1 | |
153 | |
154 The Cleaning Rule | |
155 | |
156 The Makefile author can define a rule to clean the build directory and r… | |
157 to its original state. Such rule is commonly called clean. It removes the | |
158 intermediate object files and the final files. As convenience, for the d… | |
159 to clean the build directory from core files that may be created by the … | |
160 during the development, the clean rule can also delete .core files. | |
161 clean: | |
162 -rm -f ${OBJS} ${PROG} ${PROG:=.core} | |
163 | |
164 Note that the command of this rule begins with an hyphen -. This causes … | |
165 not return error (non-zero) exit status when the command fails. This is … | |
166 for cleaning an already cleaned build directory to not print errors. | |
167 | |
168 The Phony Targets | |
169 | |
170 In a Makefile, some rules specify “virtual” targets which do not cor… | |
171 any file to be created. These are the “phony” targets. The .PHONY sp… | |
172 is used to mark its prerequisites as phony targets. In our Makefile, we … | |
173 four phony targets: all, install, uninstall, and clean. | |
174 .PHONY: all clean install uninstall | |
175 | |
176 The Makefile | |
177 | |
178 In the end, our Makefile should look like this: | |
179 PROG = myprog | |
180 SRCS = main.c util.c | |
181 OBJS = ${SRCS:.c=.o} | |
182 | |
183 PREFIX = /usr/local | |
184 MANPREFIX = ${PREFIX}/share/man | |
185 | |
186 all: ${PROG} | |
187 | |
188 main.o: parse.h util.h | |
189 parse.o: parse.h util.h | |
190 util.o: util.h | |
191 | |
192 .c.o: | |
193 ${CC} -I/usr/X11R6/include ${CFLAGS} ${CPPFLAGS} -c $< | |
194 | |
195 ${PROG}: ${OBJS} | |
196 ${CC} -o $@ ${OBJS} -L/usr/X11R6/lib -lX11 ${LDFLAGS} | |
197 | |
198 install: all | |
199 mkdir -p ${DESTDIR}${PREFIX}/bin | |
200 mkdir -p ${DESTDIR}${MANPREFIX}/man1 | |
201 install -m 755 ${PROG} ${DESTDIR}${PREFIX}/bin/${PROG} | |
202 install -m 644 ${PROG}.1 ${DESTDIR}${MANPREFIX}/man1/${PROG}.1 | |
203 | |
204 uninstall: | |
205 rm ${DESTDIR}${PREFIX}/bin/${PROG} | |
206 rm ${DESTDIR}${MANPREFIX}/man1/${PROG}.1 | |
207 | |
208 clean: | |
209 -rm -f ${OBJS} ${PROG} ${PROG:=.core} | |
210 | |
211 .PHONY: all clean install uninstall | |
212 | |
213 tl;dr | |
214 | |
215 * Define variables for the final files to be built, the source files, … | |
216 intermediate object files created by the building process. Those are com… | |
217 named ${PROG}, ${SRCS} and ${OBJS}, respectively. | |
218 * Include in the Makefile, but do not assign them, the variables ${CFL… | |
219 ${CPPFLAGS}, ${LDFLAGS} and ${DESTDIR}. They should be assigned by the u… | |
220 package maintainer. | |
221 * Evaluate the flag variables (${CFLAGS}, ${CPPFLAGS}, and ${LDFLAGS})… | |
222 any hardcoded flag, so the user or package maintainer can override it. | |
223 * Include the all and clean phony targets. Optionally include install … | |
224 uninstall phony targets. Always mark them as .PHONY. | |
225 * Do not use $< on anything but on the command of inference rules. | |
226 * Do not use -D with install(1). | |
227 * Do not call c99 or gcc manually. Call the command set in ${CC} inste… | |
228 * Assign ${PREFIX} and ${MANPREFIX} to the proper installation prefixe… | |
229 can assign them with the ?= operator for the user convenience, but this | |
230 assignment operatior is not portable, although commonly supported. | |
231 | |
232 References | |
233 | |
234 1. file:///feed.xml | |
235 2. https://seninha.org/ | |
236 EOF | |
237 |