makefile-guideline.txt - bitreich-style - Style guide for programmers. | |
git clone git://bitreich.org/bitreich-style | |
Log | |
Files | |
Refs | |
Tags | |
README | |
LICENSE | |
--- | |
makefile-guideline.txt (8924B) | |
--- | |
1 Title: Guidelines for writing simple portable Makefiles | |
2 | |
3 | |
4 This page describes some guidelines and good practices for writing simpl… | |
5 portable POSIX Makefiles. It assumes a basic level of understanding in | |
6 writing Makefiles and focuses on projects that use the C programming | |
7 language. | |
8 | |
9 make is used because it has been around for a long time, is available | |
10 on many systems, is a POSIX standard and has been proven to work well | |
11 for most projects. | |
12 | |
13 | |
14 Targets | |
15 ------- | |
16 | |
17 The following targets should be defined in the Makefile: | |
18 | |
19 * all or the "default": build the project. | |
20 * clean: clean files used by compilation, such as: object files, compiled | |
21 binaries. | |
22 * install: install the built project. | |
23 * uninstall (optional): uninstall the project. | |
24 * dist (optional): create a source tarball of the project intended as | |
25 redistribution for source packages. | |
26 * tests (optional): run unit tests. | |
27 | |
28 | |
29 Portability | |
30 ----------- | |
31 | |
32 Do not use GNUisms in Makefiles. Testing with different make | |
33 implementations, such as BSD make, which mostly respects POSIX, is very | |
34 useful. Use POSIX Makefile rules: | |
35 https://pubs.opengroup.org/onlinepubs/9699919799/utilities/make.html | |
36 | |
37 Try to place yourself in the shoes of a package maintainer / porter. This | |
38 helps make sure that the package is easy to maintain: | |
39 | |
40 * https://www.openbsd.org/faq/ports/ | |
41 * https://www.netbsd.org/docs/pkgsrc/ | |
42 * https://www.freebsd.org/doc/en_US.ISO8859-1/books/porters-handbook/boo… | |
43 * https://wiki.voidlinux.org/A_General_Introduction_To_Package_Creation | |
44 | |
45 | |
46 Variables | |
47 --------- | |
48 | |
49 It is recommended to respect the following commonly-used variables. | |
50 | |
51 * $DESTDIR: make use of the $DESTDIR variable for the install targets. T… | |
52 makes it simpler to install the package to another location and make b… | |
53 packages. It is the prefix destination directory to install to (before… | |
54 It should be unset by default. | |
55 | |
56 * $PREFIX: this variable specifies the prefix location to install to, it… | |
57 "/usr/local" by default since this is most commonly used for ports. | |
58 | |
59 * $MANPREFIX or $MANDIR: | |
60 * Distributions can use different locations for man pages for ports or… | |
61 * Some distributions package documentation in a separate package (proj… | |
62 | |
63 Specifying compiler and linker flags: | |
64 | |
65 * $CC, $CFLAGS, $LDFLAGS, $CPPFLAGS: make sure to respect the default se… | |
66 as specified in POSIX: | |
67 https://pubs.opengroup.org/onlinepubs/9699919799/utilities/make.html u… | |
68 section "Default rules". This make it easier for the ports build syste… | |
69 the set variables and not having to patch the Makefile in some way. | |
70 | |
71 * $CFLAGS: do not hard-code optimization flags like (-O2) or diagnostic … | |
72 such as -Wall, -Wextra, -pedantic. Even more importantly, do not | |
73 specify unportable compiler flags. | |
74 | |
75 * $LDFLAGS: do not hard-code linker flags like -s (symbol stripping) or … | |
76 -static or such flags. | |
77 | |
78 * Libraries: using separate variables for compile and link per library (… | |
79 example libpng, libjpeg) can be useful for building in ports. | |
80 For example a variable LIBPNG_CFLAGS, LIBPNG_LDFLAGS for the header fi… | |
81 library location. | |
82 | |
83 | |
84 Considerations | |
85 -------------- | |
86 | |
87 * It is not recommended to suppress compilation output with the @ prefix… | |
88 example to make output look nicer aligned). The verbose output is very… | |
89 for debugging and suppressing it only adds debugging abstractions. | |
90 | |
91 * Try to use a single-file Makefile, at least for small projects. If ne… | |
92 configuration could be included from the Makefile: config.mk. Keep in… | |
93 that reducing abstractions will increase readability and debugability.… | |
94 maintainers/porters do not want to have to relearn a new system for ea… | |
95 software package. | |
96 | |
97 * As specified above, different systems can use different locations for … | |
98 things like man pages, X11 header files and libraries and ports instal… | |
99 | |
100 Examples: | |
101 * X11: commonly uses /usr/X11R6 on BSD-like platforms. | |
102 * Man page directories: on OpenBSD: /usr/local/man. | |
103 | |
104 Testing on many different systems is useful! For example: Linux, OpenBSD… | |
105 | |
106 | |
107 Examples | |
108 -------- | |
109 | |
110 Below is an example of a Makefile from the json2tsv project. It is | |
111 line-numbered and annotated with remarks on why things are done the way | |
112 they are. | |
113 | |
114 1 .POSIX: | |
115 | |
116 Specify POSIX compatibility: "To receive exactly the behavior described … | |
117 section, the user shall ensure that a portable makefile shall: Include t… | |
118 special target .POSIX" | |
119 | |
120 2 | |
121 3 NAME = json2tsv | |
122 4 VERSION = 0.5 | |
123 5 | |
124 | |
125 Define a name and version variable of the project which can be reused, f… | |
126 example for the dist tarball. | |
127 | |
128 6 # paths | |
129 7 PREFIX = /usr/local | |
130 8 MANPREFIX = ${PREFIX}/man | |
131 9 DOCPREFIX = ${PREFIX}/share/doc/${NAME} | |
132 10 | |
133 | |
134 Specify default sane paths. | |
135 | |
136 11 RANLIB = ranlib | |
137 12 | |
138 | |
139 This variable is not specified by default in POSIX. It is commonly "ranl… | |
140 but can be overwritten. | |
141 | |
142 13 BIN = ${NAME} | |
143 | |
144 In this case it's simple: the binary is the program name. | |
145 | |
146 14 SRC = ${BIN:=.c} | |
147 | |
148 C source files, so just json2tsv.c here. | |
149 | |
150 15 HDR = json.h | |
151 | |
152 Header files. | |
153 | |
154 16 MAN1 = ${BIN:=.1} | |
155 | |
156 Man section 1 pages. | |
157 | |
158 17 DOC = \ | |
159 18 LICENSE\ | |
160 19 README | |
161 20 | |
162 | |
163 Other documentation and license files. | |
164 | |
165 21 LIBJSON = libjson.a | |
166 22 LIBJSONSRC = json.c | |
167 23 LIBJSONOBJ = ${LIBJSONSRC:.c=.o} | |
168 24 | |
169 25 LIB = ${LIBJSON} | |
170 26 | |
171 | |
172 Build the json.c file as a local reusable linkable library (libjson.a). | |
173 | |
174 27 all: ${BIN} | |
175 28 | |
176 | |
177 The default build rule: build the binary. | |
178 | |
179 29 ${BIN}: ${LIB} ${BIN:=.o} | |
180 30 | |
181 | |
182 The binary depends on the libjson library and its own object file. | |
183 | |
184 31 OBJ = ${SRC:.c=.o} ${LIBJSONOBJ} | |
185 32 | |
186 | |
187 The object files are all C source-code substituted to from .c to .o and … | |
188 local libjson library files, so: json2tsv.o json.o | |
189 | |
190 33 ${OBJ}: ${HDR} | |
191 34 | |
192 | |
193 Ensure the object files are recompiled if the header file contents chang… | |
194 | |
195 35 .o: | |
196 36 ${CC} ${LDFLAGS} -o $@ $< ${LIB} | |
197 | |
198 Linking, use the system specified LDFLAGS. | |
199 | |
200 37 | |
201 38 .c.o: | |
202 39 ${CC} ${CFLAGS} ${CPPFLAGS} -c $< | |
203 | |
204 Compiling, use the system specified CFLAGS and CPPFLAGS. | |
205 | |
206 40 | |
207 41 ${LIBJSON}: ${LIBJSONOBJ} | |
208 42 ${AR} -rc $@ $? | |
209 43 ${RANLIB} $@ | |
210 44 | |
211 | |
212 Create an archive of the libjson object files. Note that ar -s is an ext… | |
213 so ranlib is called as a separate command. It is also useful to be speci… | |
214 separately for cross-compiling. | |
215 | |
216 45 dist: | |
217 46 rm -rf "${NAME}-${VERSION}" | |
218 47 mkdir -p "${NAME}-${VERSION}" | |
219 48 cp -f ${MAN1} ${DOC} ${HDR} \ | |
220 49 ${SRC} ${LIBJSONSRC} Makefile "${NAME}-${V… | |
221 | |
222 Use the -f (force) options for rm ensures make does not return an error | |
223 on failure. For cp it ensures to overwrite the file even if it is busy. … | |
224 mkdir the -p flag is used to create all intermediary directories and to … | |
225 return an error if the directory already exists. | |
226 | |
227 50 # make tarball | |
228 51 tar cf - "${NAME}-${VERSION}" | gzip -c > "${NAME}… | |
229 | |
230 Make a tarball. gzip from stdin is used for portability (tar z is non-PO… | |
231 https://pubs.opengroup.org/onlinepubs/007908799/xcu/tar.html | |
232 | |
233 52 rm -rf "${NAME}-${VERSION}" | |
234 53 | |
235 | |
236 54 clean: | |
237 55 rm -f ${BIN} ${OBJ} ${LIB} | |
238 | |
239 Remove the binary, object files and the local archive library (.a) file. | |
240 | |
241 56 | |
242 57 install: all | |
243 58 # installing executable files. | |
244 59 mkdir -p "${DESTDIR}${PREFIX}/bin" | |
245 60 cp -f ${BIN} "${DESTDIR}${PREFIX}/bin" | |
246 | |
247 cp's -f flag ensures overwriting the file even if it is busy. | |
248 | |
249 61 for f in ${BIN}; do chmod 755 "${DESTDIR}${PREFIX}… | |
250 62 # installing example files. | |
251 63 mkdir -p "${DESTDIR}${DOCPREFIX}" | |
252 64 cp -f ${DOC} "${DESTDIR}${DOCPREFIX}" | |
253 65 for d in ${DOC}; do chmod 644 "${DESTDIR}${DOCPREF… | |
254 66 # installing manual pages for general commands: se… | |
255 67 mkdir -p "${DESTDIR}${MANPREFIX}/man1" | |
256 68 cp -f ${MAN1} "${DESTDIR}${MANPREFIX}/man1" | |
257 69 for m in ${MAN1}; do chmod 644 "${DESTDIR}${MANPRE… | |
258 70 | |
259 | |
260 Explicitly set permissions for executable files and for documentation. | |
261 | |
262 71 uninstall: | |
263 72 # removing executable files. | |
264 73 for f in ${BIN}; do rm -f "${DESTDIR}${PREFIX}/bin… | |
265 74 # removing example files. | |
266 75 for d in ${DOC}; do rm -f "${DESTDIR}${DOCPREFIX}/… | |
267 | |
268 76 -rmdir "${DESTDIR}${DOCPREFIX}" | |
269 | |
270 Try to remove the doc directory, but if it is shared by other packages a… | |
271 rmdir returns an error code then that is ok and make still proceeds. | |
272 | |
273 77 # removing manual pages. | |
274 78 for m in ${MAN1}; do rm -f "${DESTDIR}${MANPREFIX}… | |
275 79 | |
276 80 .PHONY: all clean dist install uninstall | |
277 | |
278 | |
279 References | |
280 ---------- | |
281 | |
282 - https://www.gnu.org/prep/standards/standards.html#DESTDIR | |
283 - https://nullprogram.com/blog/2017/08/20/ | |
284 - https://pubs.opengroup.org/onlinepubs/9699919799/utilities/make.html | |
285 - https://pubs.opengroup.org/onlinepubs/9699919799/ |