Introduction
Introduction Statistics Contact Development Disclaimer Help
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
You are viewing proxied material from bitreich.org. The copyright of proxied material belongs to its original authors. Any comments or complaints in relation to proxied material should be directed to the original authors of the content concerned. Please see the disclaimer for more details.