1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
|
# Copyright © Tavian Barnes <tavianator@tavianator.com>
# SPDX-License-Identifier: 0BSD
# Common makefile utilities. Compatible with both GNU make and most BSD makes.
# BSD make will chdir into ${.OBJDIR} by default, unless we tell it not to
.OBJDIR: .
# We don't use any suffix rules
.SUFFIXES:
# GNU make has $^ for the full list of targets, while BSD make has $> and the
# long-form ${.ALLSRC}. We could write $^ $> to get them both, but that would
# break if one of them implemented support for the other. So instead, bring
# BSD's ${.ALLSRC} to GNU.
.ALLSRC ?= $^
# For out-of-tree builds, e.g.
#
# $ make config BUILDDIR=/path/to/build/dir
# $ make BUILDDIR=/path/to/build/dir
BUILDDIR ?= .
# Shorthand for build subdirectories
BIN := ${BUILDDIR}/bin
GEN := ${BUILDDIR}/gen
OBJ := ${BUILDDIR}/obj
# GNU make strips a leading ./ from target names, so do the same for BSD make
BIN := ${BIN:./%=%}
GEN := ${GEN:./%=%}
OBJ := ${OBJ:./%=%}
# The configuration file generated by `make config`
CONFIG := ${GEN}/config.mk
# Installation paths
DESTDIR ?=
PREFIX ?= /usr
MANDIR ?= ${PREFIX}/share/man
# GNU make supports `export VAR`, but BSD make requires `export VAR=value`.
# Sadly, GNU make gives a recursion error on `export VAR=${VAR}`.
_BUILDDIR := ${BUILDDIR}
export BUILDDIR=${_BUILDDIR}
# Configurable executables; can be overridden with
#
# $ make config CC=clang
CC ?= cc
INSTALL ?= install
MKDIR ?= mkdir -p
PKG_CONFIG ?= pkg-config
RM ?= rm -f
# GNU and BSD make have incompatible syntax for conditionals, but we can do a
# lot with just nested variable expansion. We use "y" as the canonical
# truthy value, and "" (the empty string) as the canonical falsey value.
#
# To normalize a boolean, use ${TRUTHY,${VAR}}, which expands like this:
#
# VAR=y ${TRUTHY,${VAR}} => ${TRUTHY,y} => y
# VAR=1 ${TRUTHY,${VAR}} => ${TRUTHY,1} => y
# VAR=n ${TRUTHY,${VAR}} => ${TRUTHY,n} => [empty]
# VAR=other ${TRUTHY,${VAR}} => ${TRUTHY,other} => [empty]
# VAR= ${TRUTHY,${VAR}} => ${TRUTHY,} => [emtpy]
#
# Inspired by https://github.com/wahern/autoguess
TRUTHY,y := y
TRUTHY,1 := y
# Boolean operators are also implemented with nested expansion
NOT,y :=
NOT, := y
# Support up to 5 arguments
AND,y := y
AND,y,y := y
AND,y,y,y := y
AND,y,y,y,y := y
AND,y,y,y,y,y := y
# NOR can be defined without combinatorial explosion.
# OR is just ${NOT,${NOR,...}}
NOR, := y
NOR,, := y
NOR,,, := y
NOR,,,, := y
NOR,,,,, := y
# Normalize ${V} to either "y" or ""
IS_V := ${TRUTHY,${V}}
# Suppress output unless V=1
Q, := @
Q := ${Q,${IS_V}}
# The current target, with ${BUILDDIR} stripped for shorter messages
TGT = ${@:${BUILDDIR}/%=%}
# Show full commands with `make V=1`, otherwise short summaries
MSG = @msg() { \
MSG="$$1"; \
shift; \
test "${IS_V}" || printf '%s\n' "$$MSG"; \
test "$${1:-}" || return 0; \
test "${IS_V}" && printf '%s\n' "$$*"; \
"$$@"; \
}; \
msg
# Maximum width of a short message, to align the [X]
MSG_WIDTH := 24
# cat a file if V=1
VCAT,y := @cat
VCAT, := @:
VCAT := ${VCAT,${IS_V}}
# List all object files here, as they're needed by both `make config` and `make`
# All object files except the entry point
LIBBFS := \
${OBJ}/src/alloc.o \
${OBJ}/src/bar.o \
${OBJ}/src/bfstd.o \
${OBJ}/src/bftw.o \
${OBJ}/src/color.o \
${OBJ}/src/ctx.o \
${OBJ}/src/diag.o \
${OBJ}/src/dir.o \
${OBJ}/src/dstring.o \
${OBJ}/src/eval.o \
${OBJ}/src/exec.o \
${OBJ}/src/expr.o \
${OBJ}/src/fsade.o \
${OBJ}/src/ioq.o \
${OBJ}/src/mtab.o \
${OBJ}/src/opt.o \
${OBJ}/src/parse.o \
${OBJ}/src/printf.o \
${OBJ}/src/pwcache.o \
${OBJ}/src/stat.o \
${OBJ}/src/thread.o \
${OBJ}/src/trie.o \
${OBJ}/src/typo.o \
${OBJ}/src/xregex.o \
${OBJ}/src/xspawn.o \
${OBJ}/src/xtime.o \
${OBJ}/gen/version.o
# Unit test objects
UNIT_OBJS := \
${OBJ}/tests/alloc.o \
${OBJ}/tests/bfstd.o \
${OBJ}/tests/bit.o \
${OBJ}/tests/ioq.o \
${OBJ}/tests/main.o \
${OBJ}/tests/trie.o \
${OBJ}/tests/xspawn.o \
${OBJ}/tests/xtime.o
# All object files
OBJS := \
${OBJ}/src/main.o \
${OBJ}/tests/mksock.o \
${OBJ}/tests/xspawnee.o \
${OBJ}/tests/xtouch.o \
${LIBBFS} \
${UNIT_OBJS}
|