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