Commit | Line | Data |
---|---|---|
e36b4f25 MW |
1 | ### -*-makefile-*- |
2 | ### | |
3 | ### Main maintenance script for chroots | |
4 | ### | |
5 | ### (c) 2018 Mark Wooding | |
6 | ### | |
7 | ||
8 | ###----- Licensing notice --------------------------------------------------- | |
9 | ### | |
10 | ### This file is part of the distorted.org.uk chroot maintenance tools. | |
11 | ### | |
12 | ### distorted-chroot is free software: you can redistribute it and/or | |
13 | ### modify it under the terms of the GNU General Public License as | |
14 | ### published by the Free Software Foundation; either version 2 of the | |
15 | ### License, or (at your option) any later version. | |
16 | ### | |
17 | ### distorted-chroot is distributed in the hope that it will be useful, | |
18 | ### but WITHOUT ANY WARRANTY; without even the implied warranty of | |
19 | ### MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
20 | ### General Public License for more details. | |
21 | ### | |
22 | ### You should have received a copy of the GNU General Public License | |
23 | ### along with distorted-chroot. If not, write to the Free Software | |
24 | ### Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, | |
25 | ### USA. | |
26 | ||
a914e882 | 27 | all: |
e36b4f25 | 28 | clean:: |
3e5b03e2 | 29 | check:: |
408e5644 MW |
30 | help:: |
31 | .PHONY: all clean check help | |
e36b4f25 MW |
32 | .SECONDEXPANSION: #sorry |
33 | ||
34 | ###-------------------------------------------------------------------------- | |
35 | ### Configuration. | |
36 | ||
37 | CONFIG_VARS = | |
38 | ||
408e5644 MW |
39 | help:: |
40 | @echo "Configuration variables" | |
41 | ||
856d5147 MW |
42 | ## Make verbosity. |
43 | V = 0 | |
408e5644 | 44 | help::; @echo " V build verbosity" |
856d5147 | 45 | |
3e5b03e2 MW |
46 | ## Level of pickiness to aspire to. |
47 | NOTIFY_FATAL = 1 | |
408e5644 MW |
48 | help:: |
49 | @echo " NOTIFY_FATAL report fatal error on ..." && \ | |
50 | echo " 1 = error" && \ | |
51 | echo " 2 = warning" && \ | |
52 | echo " 3 = info" | |
3e5b03e2 | 53 | |
e36b4f25 MW |
54 | ## Volume group from which to allocate chroot volumes and snapshots. |
55 | CONFIG_VARS += VG LVPREFIX | |
afb5d051 | 56 | VG := vg-$(shell hostname) |
e36b4f25 MW |
57 | LVPREFIX = |
58 | ||
59 | ## Logical volume size, as an LVM option. | |
3e5b03e2 | 60 | CONFIG_VARS += LVSZ SNAPOPT |
e36b4f25 | 61 | LVSZ = -L8G |
3e5b03e2 | 62 | SNAPOPT = -L8G |
e36b4f25 MW |
63 | |
64 | ## Debian mirror. | |
65 | CONFIG_VARS += DEBMIRROR | |
66 | DEBMIRROR = http://deb.debian.org/debian/ | |
67 | ||
68 | ## APT sources configurations. (Also, $($d_APTSRC) for each $d in $(DISTS).) | |
69 | CONFIG_VARS += APTSRC | |
70 | APTSRC = etc/aptsrc.conf $(wildcard etc/aptsrc.local.conf) | |
71 | ||
72 | ## APT configuration fragment names. These will be linked into | |
73 | ## `/etc/apt/apt.conf.d' in each chroot. To put a fragment f in a surprising | |
a98c9dba MW |
74 | ## place, set $(_$f_APTCONFSRC). |
75 | CONFIG_VARS += APTCONF $(foreach f,$(APTCONF),_$f_APTCONFSRC) | |
76 | APTCONF = $(notdir $(wildcard etc/apt-conf.d/[0-9]*[!~])) | |
e36b4f25 MW |
77 | |
78 | ## Proxy setting. | |
79 | CONFIG_VARS += PROXY | |
4d529157 | 80 | PROXY = $(shell \ |
a98c9dba | 81 | eval $$(apt-config $(foreach a,$(APTCONF),-cetc/apt-conf.d/$a) \ |
e36b4f25 MW |
82 | shell proxy Acquire::http::proxy); \ |
83 | case $${proxy+t} in (t) echo "$$proxy" ;; (*) echo nil ;; esac) | |
84 | ||
85 | ## Debian distributions to support. | |
86 | CONFIG_VARS += PRIMARY_DIST DISTS | |
87 | PRIMARY_DIST = stretch | |
168cdcfe | 88 | DISTS = $(PRIMARY_DIST) buster bullseye bookworm sid |
e36b4f25 MW |
89 | |
90 | ## Host's native architecture(s). | |
91 | CONFIG_VARS += MYARCH NATIVE_ARCHS | |
afb5d051 MW |
92 | MYARCH := $(shell dpkg --print-architecture) |
93 | OTHERARCHS := $(shell dpkg --print-foreign-architectures) | |
e36b4f25 MW |
94 | NATIVE_ARCHS = $(MYARCH) $(OTHERARCHS) |
95 | ||
96 | ## Foreign (emulated) architectures to support. | |
97 | CONFIG_VARS += FOREIGN_ARCHS | |
98 | FOREIGN_ARCHS = | |
99 | ||
100 | ## Master lists of chroots to build and maintain. | |
a98c9dba | 101 | CONFIG_VARS += NATIVE_CHROOTS FOREIGN_CHROOTS |
e36b4f25 MW |
102 | NATIVE_CHROOTS = $(foreach a,$(NATIVE_ARCHS), \ |
103 | $(foreach d,$(or $($a_DISTS) $(DISTS)), \ | |
104 | $d-$a)) | |
105 | FOREIGN_CHROOTS = $(foreach a,$(FOREIGN_ARCHS), \ | |
106 | $(foreach d,$(or $($a_DISTS) $(DISTS)), \ | |
107 | $d-$a)) | |
108 | ||
a98c9dba MW |
109 | ## Extra packages to be installed in chroots. `BASE_PACKAGES' are installed |
110 | ## through `debootstrap'; `EXTRA_PACKAGES' are installed later, using Apt, | |
111 | ## which is faster in foreign chroots. | |
112 | CONFIG_VARS += BASE_PACKAGES EXTRA_PACKAGES | |
113 | BASE_PACKAGES = eatmydata | |
114 | EXTRA_PACKAGES = build-essential | |
115 | EXTRA_PACKAGES += ccache | |
116 | EXTRA_PACKAGES += fakeroot | |
117 | EXTRA_PACKAGES += libfile-fcntllock-perl | |
118 | EXTRA_PACKAGES += locales | |
119 | ||
120 | ## Extra packages from which to install the cross tools. | |
121 | CONFIG_VARS += CROSS_PACKAGES | |
122 | CROSS_PACKAGES = bash coreutils dash findutils | |
123 | CROSS_PACKAGES += gzip m4 mawk sed tar xz-utils | |
124 | CROSS_PACKAGES += apt ccache eatmydata fakeroot make | |
125 | CROSS_PACKAGES += qemu-user-static | |
126 | CROSS_PACKAGES += $(foreach a,$(FOREIGN_GNUARCHS),\ | |
127 | gcc-$a g++-$a binutils-$a) | |
128 | ||
129 | ## Native files to install in place of the foreign versions. `MULTI' here | |
130 | ## stands for the donor's GNU multiarch name. | |
131 | CONFIG_VARS += CROSS_PATHS | |
132 | CROSS_PATHS += \ | |
133 | $(addprefix /usr/bin/, \ | |
134 | apt apt-cache apt-config apt-get apt-key apt-mark) \ | |
135 | $(addprefix /usr/lib/apt/, \ | |
136 | methods/ solvers/) \ | |
137 | $(addprefix /bin/, \ | |
138 | cat chgrp chown cp date dd df dir echo false ln ls mkdir \ | |
139 | mknod mktemp mv pwd readlink rm rmdir sleep stty sync touch \ | |
140 | true uname vdir) \ | |
141 | $(addprefix /usr/bin/, \ | |
142 | [ arch b2sum base32 base64 basename chcon cksum comm \ | |
143 | csplit cut dircolors dirname du env expand expr factor fmt \ | |
144 | fold groups head hostid id install join link logname md5sum \ | |
145 | mkfifo nice nl nohup nproc numfmt od paste pathchk pinky pr \ | |
146 | printenv printf ptx realpath runcon seq sha1sum sha224sum \ | |
147 | sha256sum sha384sum sha512sum shred shuf sort split stat \ | |
148 | stdbuf sum tac tail tee test timeout tr truncate tsort tty \ | |
149 | unexpand uniq unlink users wc who whoami yes) \ | |
1965c971 | 150 | ?/usr/lib/MULTI/coreutils/ \ |
a98c9dba MW |
151 | $(addprefix /lib/MULTI/, \ |
152 | libnsl.so.* libnss_*.so.*) \ | |
153 | /usr/bin/gpgv \ | |
154 | /usr/bin/qemu-*-static \ | |
155 | $(addprefix /bin/, \ | |
156 | bash dash gzip sed tar) \ | |
157 | $(addprefix /usr/bin/, \ | |
158 | ccache find m4 make mawk xargs xz) \ | |
159 | $(addprefix /usr/lib/MULTI/, \ | |
160 | libeatmydata.so* libfakeroot/) \ | |
161 | $(addprefix /etc/ld.so.conf.d/, \ | |
162 | MULTI.conf fakeroot*.conf) \ | |
163 | $(foreach a,$(FOREIGN_GNUARCHS), \ | |
164 | $(addprefix /usr/bin/$a-, \ | |
165 | addr2line ar as c++filt dwp elfedit gprof ld ld.* \ | |
166 | nm objcopy objdump ranlib readelf size strings \ | |
167 | strip) \ | |
168 | $(addprefix /usr/bin/$a-, \ | |
169 | cpp gcc g++ gcov gcov-dump gcov-tool gprof \ | |
170 | gcc-ar gcc-nm gcc-ranlib) \ | |
44dfbdf5 MW |
171 | /usr/lib/gcc-cross/$a/ \ |
172 | /usr/$a/include/c++) | |
3e5b03e2 MW |
173 | |
174 | ## Local packages to be compiled and installed in chroots. Archives can be | |
175 | ## found in `pkg/'. | |
a98c9dba | 176 | CONFIG_VARS += LOCALPKGS $(foreach p,$(LOCALPKGS),$p_DEPS) |
3e5b03e2 | 177 | LOCALPKGS = mLib checkpath |
a98c9dba MW |
178 | mLib_DEPS = |
179 | checkpath_DEPS = mLib | |
3e5b03e2 | 180 | |
e36b4f25 MW |
181 | ## Which host architecture to use for foreign architectures. It turns out |
182 | ## that it's best to use a Qemu with the same host bitness as the target | |
183 | ## architecture; otherwise it has to do a difficult job of converting | |
184 | ## arguments and results between kernel ABI flavours. | |
185 | 32BIT_QEMUHOST = $(or $(filter i386,$(NATIVE_ARCHS)),$(TOOLSARCH)) | |
186 | 64BIT_QEMUHOST = $(or $(filter amd64,$(NATIVE_ARCHS)),$(TOOLSARCH)) | |
187 | ||
a98c9dba | 188 | CONFIG_VARS += $(foreach a,$(FOREIGN_ARCHS),$a_QEMUHOST) |
e36b4f25 MW |
189 | armel_QEMUHOST = $(32BIT_QEMUHOST) |
190 | armhf_QEMUHOST = $(32BIT_QEMUHOST) | |
191 | arm64_QEMUHOST = $(64BIT_QEMUHOST) | |
192 | i386_QEMUHOST = $(32BIT_QEMUHOST) | |
193 | amd64_QEMUHOST = $(64BIT_QEMUHOST) | |
194 | ||
d9f036c4 MW |
195 | ## Which distribution of Qemu to use. |
196 | CONFIG_VARS += $(foreach d,$(DISTS),$d_QEMUDIST) | |
a02fd5c0 | 197 | stretch_QEMUDIST = buster |
d9f036c4 | 198 | |
e36b4f25 MW |
199 | ## Qemu architecture names. These tell us which Qemu binary to use for a |
200 | ## particular Debian architecture. | |
a98c9dba | 201 | CONFIG_VARS += $(foreach a,$(FOREIGN_ARCHS),$a_QEMUARCH) |
e36b4f25 MW |
202 | armel_QEMUARCH = arm |
203 | armhf_QEMUARCH = arm | |
204 | arm64_QEMUARCH = aarch64 | |
205 | i386_QEMUARCH = i386 | |
206 | amd64_QEMUARCH = x86_64 | |
207 | ||
208 | ## Alias mapping for chroots. | |
a98c9dba | 209 | CONFIG_VARS += $(foreach d,$(DISTS),$d_ALIASES) |
e36b4f25 MW |
210 | stretch_ALIASES = oldstable |
211 | buster_ALIASES = stable | |
a98c9dba | 212 | bullseye_ALIASES = testing |
e36b4f25 MW |
213 | sid_ALIASES = unstable |
214 | ||
215 | ## Which host architecture to use for commonly used tools in foreign chroots. | |
216 | CONFIG_VARS += TOOLSARCH | |
217 | TOOLSARCH = $(MYARCH) | |
218 | ||
219 | ## A directory in which we can maintain private files and state. | |
220 | CONFIG_VARS += STATE | |
221 | STATE = state | |
408e5644 | 222 | help::; @echo " STATE directory for state files" |
e36b4f25 MW |
223 | |
224 | ## A directory which will be spliced into chroots as `/usr/local.schroot/'. | |
225 | ## This will be our primary point of contact with the chroot. | |
8918e451 | 226 | CONFIG_VARS += LOCAL ABSLOCAL |
e36b4f25 | 227 | LOCAL = local.schroot |
8918e451 | 228 | ABSLOCAL = $(abspath $(LOCAL)) |
408e5644 | 229 | help::; @echo " LOCAL directory for chroot /usr/local" |
e36b4f25 MW |
230 | |
231 | ## How to run a command as a privileged user. | |
a98c9dba | 232 | CONFIG_VARS += ROOTLY |
e36b4f25 MW |
233 | ROOTLY = sudo |
234 | ||
235 | ## Files to be copied into a chroot from the host. | |
236 | SCHROOT_COPYFILES = /etc/resolv.conf | |
237 | SCHROOT_NSSDATABASES = passwd shadow group gshadow | |
238 | ||
239 | ## Local configuration hook. | |
240 | -include local.mk | |
241 | ||
242 | ## All chroot names. | |
3e5b03e2 MW |
243 | CONFIG_VARS += ALL_ARCHS ALL_CHROOTS |
244 | ALL_ARCHS = $(NATIVE_ARCHS) $(FOREIGN_ARCHS) | |
e36b4f25 MW |
245 | ALL_CHROOTS = $(NATIVE_CHROOTS) $(FOREIGN_CHROOTS) |
246 | ||
a98c9dba MW |
247 | ## GNU names for foreign architectures. |
248 | CONFIG_VARS += FOREIGN_GNUARCHS | |
249 | FOREIGN_GNUARCHS := $(foreach a,$(FOREIGN_ARCHS),\ | |
250 | $(shell dpkg-architecture -A$a \ | |
251 | -qDEB_TARGET_GNU_TYPE)) | |
252 | ||
e36b4f25 | 253 | ###-------------------------------------------------------------------------- |
408e5644 MW |
254 | ### Basic help. |
255 | ||
256 | help:: | |
257 | @echo "Basic targets" && \ | |
258 | echo " all build and install the infrastructure" && \ | |
259 | echo " clean delete build files" && \ | |
260 | echo " check verify correct installation" | |
261 | ||
262 | ###-------------------------------------------------------------------------- | |
e36b4f25 MW |
263 | ### Utilities. |
264 | ||
3e5b03e2 MW |
265 | ## Hack to force rebuilding. |
266 | _force: | |
267 | .PHONY: _force | |
268 | ||
269 | ## Hack to not delimit function arguments. (Ugh!) | |
270 | comma = , | |
271 | ||
272 | ## Silent-rules machinery. | |
3e5b03e2 MW |
273 | V_AT = $(V_AT_$V) |
274 | V_AT_0 = @ | |
275 | v_print = $(call v_print_$V,$1,$2) | |
276 | v_print_0 = printf " %-8s %s\n" "$1" $(call squote,$2); | |
277 | v_tag = $(V_AT)$(call v_print,$1,$@) | |
278 | v_log = $(call v_log_$V,$1,$2) | |
279 | v_log_ = $(call v_log_1,$1,$2) | |
280 | v_log_0 = $2 >log/$1.log 2>&1 | |
281 | v_log_1 = $(call catchrc,$(call throwrc,$2) 2>&1 | tee log/$1.log) | |
282 | v_echo = $(call v_echo_$V,$1) | |
283 | v_echo_0 = : | |
284 | v_echo_1 = printf "%s\n" $1 | |
285 | CLEANFILES += log/*.log | |
286 | ||
287 | ## Oh, shut up. | |
288 | SILENCE_LVM = \ | |
289 | LVM_SUPPRESS_FD_WARNINGS=1; export LVM_SUPPRESS_FD_WARNINGS | |
290 | ||
800139e6 MW |
291 | ## $(call file-name,PATH) |
292 | ## | |
293 | ## Strip any trailing `/' from the PATH. | |
294 | file-name = $(1:/=) | |
295 | ||
296 | ## $(call base-name,PATH) | |
297 | ## | |
298 | ## Expand to the last component of PATH, whether or not it's a directory | |
299 | ## name with a trailing `/'. | |
300 | base-name = $(notdir $(call file-name,$1)) | |
301 | ||
302 | ## $(call parent-dir,PATH) | |
303 | ## | |
304 | ## Expand to the parent directory of PATH, whether or not it's a directory | |
305 | ## name with a trailing `/'. | |
306 | ## `/'. | |
307 | parent-dir = $(dir $(call file-name,$1)) | |
308 | ||
a98c9dba MW |
309 | ## $(call definedp,VAR) |
310 | ## | |
311 | ## Expand non-empty if and only if VAR is defined (but possibly empty). | |
312 | definedp = $(filter-out undefined,$(origin $1)) | |
313 | ||
3e5b03e2 MW |
314 | ## $(call catchrc,...$(call throwrc,CMD)...) |
315 | ## | |
316 | ## Catch the exit status of some subpart of a complicated shell rune. | |
317 | catchrc = (exec 3>&1; exit $$({ $1; } 4>&1 >&3 3>&-)) | |
318 | throwrc = { $1; echo $$? >&4; } | |
319 | ||
320 | ## $(call squote,TXT) | |
321 | ## | |
322 | ## Single-quote TXT. | |
1727e3c6 MW |
323 | squote = '$(subst ','\'',$1)' |
324 | #' | |
3e5b03e2 | 325 | |
e36b4f25 MW |
326 | ## $(call chroot-dist,D-A) -> D |
327 | ## $(call chroot-arch,D-A) -> A | |
328 | ## | |
329 | ## Parse chroot descriptions. | |
330 | chroot-dist = $(patsubst %/,%,$(dir $(subst -,/,$1))) | |
331 | chroot-arch = $(notdir $(subst -,/,$1)) | |
332 | ||
3e5b03e2 MW |
333 | ## $(call package-dir-name,P-V) -> P |
334 | ## $(call package-dir-version,P-V) -> V | |
335 | ## | |
336 | ## Parse (source) package directory names. | |
337 | package-dir-name = $(sort $(foreach p,$(LOCALPKGS),$(if $(filter $p-$($p_VERSION),$1),$p))) | |
338 | package-dir-version = $($(call package-dir-name,$1)_VERSION) | |
339 | ||
340 | ## $(call package-dir,P-V.A) -> P-V | |
341 | ## $(call package-name,P-V.A) -> P | |
342 | ## $(call package-version,P-V.A) -> V | |
343 | ## $(call package-arch,P-V.A) -> A | |
344 | ## | |
345 | ## Parse package stamp names. | |
346 | package-dir = $(basename $1) | |
347 | package-name = $(call package-dir-name,$(call package-dir,$1)) | |
348 | package-version = $(call package-dir-version,$(call package-dir,$1)) | |
349 | package-arch = $(patsubst .%,%,$(suffix $1)) | |
350 | ||
e36b4f25 MW |
351 | ## $(call native-chroot-p,D-A) -> D | <empty> |
352 | ## | |
353 | ## Answer whether D-A is a native chroot. | |
3e5b03e2 | 354 | native-chroot-p = $(filter $(call chroot-arch,$1),$(NATIVE_ARCHS)) |
e36b4f25 MW |
355 | |
356 | ## $(call chroot-qemuhost,D-A) -> AA | |
357 | ## | |
358 | ## Answer the apporopriate Qemu host architecture for foreign chroot D-A. | |
359 | chroot-qemuhost = $($(call chroot-arch,$1)_QEMUHOST) | |
360 | ||
3e5b03e2 | 361 | ## $(call chroot-deps,PRE,D-A) -> PREDD-AA ... | <empty> |
e36b4f25 MW |
362 | ## |
363 | ## Answer a list of additional dependencies for the chroot D-A: specifically, | |
364 | ## if D-A is foreign then include PRE/DD-AA entries for the tools | |
365 | ## architecture, and Qemu host architecture (if that's different). | |
366 | chroot-deps = $(if $(call native-chroot-p,$2),, \ | |
3e5b03e2 MW |
367 | $(addprefix $1$(call chroot-dist,$2)-,\ |
368 | $(sort $(TOOLSARCH) \ | |
e36b4f25 MW |
369 | $(call chroot-qemuhost,$2)))) |
370 | ||
371 | ## Substituting placeholders in files. | |
372 | SUBSTITUTIONS := local=$(shell realpath $(LOCAL)) | |
373 | SUBSTITUTIONS += primary-dist=$(PRIMARY_DIST) | |
374 | subst-file = { \ | |
375 | echo "$1 GENERATED by distorted-chroot: do not edit"; \ | |
376 | substs=""; \ | |
377 | for v in $(SUBSTITUTIONS); do \ | |
378 | var=$${v%%=*} value=$${v\#*=}; \ | |
379 | substs="$$substs s\a@$$var@\a$$value\ag;"; \ | |
380 | done; \ | |
381 | sed "$$substs"; \ | |
382 | } | |
383 | ||
3e5b03e2 MW |
384 | ### $(call symlink-ok-p,LINK,DEST) |
385 | ### | |
386 | ### Expand to `t' if LINK is a symbolic link to DEST, and empty otherwise. | |
387 | symlink-ok-p = $(shell \ | |
388 | case $$(readlink 2>/dev/null $(patsubst %/,%,$1)) in ($2) echo t ;; esac) | |
389 | ||
390 | ### $(call general-notify,SEV,COLOUR,PREFIX,MSG) | |
391 | ### | |
392 | ### Report a message, highlighted in the right way, and maybe fail | |
393 | general-notify = { \ | |
394 | echo "$$(tput bold; tput setaf $2)$3 "$4"$$(tput sgr0; tput op)"; \ | |
395 | if [ "$1" -le "$(NOTIFY_FATAL)" ]; then exit 2; fi; \ | |
396 | } | |
397 | ||
398 | ### $(call report/SEV,MSG) | |
399 | ### | |
400 | ### Report a notification of a particular severity. | |
401 | notify/INFO = $(call general-notify,3,6,---,$1) | |
402 | notify/WARN = $(call general-notify,2,5,???,$1) | |
403 | notify/ERR = $(call general-notify,1,1,!!!,$1) | |
404 | ||
405 | ## $(call check,SEV,MSG,UNLESS) | |
406 | ## | |
407 | ## If UNLESS completes successfully, all is OK; otherwise print MSG to stderr | |
408 | ## and fail. | |
409 | check = @{ \ | |
410 | $(call v_echo,'check: '$(call squote,$3)''); \ | |
411 | if ! { $3; }; then $(call notify/$1,$2); fi; \ | |
412 | } | |
413 | ||
414 | ## $(call check-executable,SEV,PATH) | |
415 | ## | |
416 | ## Verify that PATH is an executable program. | |
417 | check-executable = $(call check,$1,"\`$2' is not an executable", \ | |
418 | [ -x "$2" ]) | |
419 | ||
420 | ## $(call check-mountpoint,SEV,DIR) | |
421 | ## | |
422 | ## Verify that DIR is a mountpoint. | |
423 | check-mountpoint = $(call check,$1,"\`$2' is not a mount point", \ | |
424 | mountpoint -q "$2") | |
425 | ||
426 | ## $(call check-symlink,SEV,LINK,DEST) | |
427 | ## | |
428 | ## Verify that LINK is a symbolic link pointing to DEST. | |
429 | check-symlink = $(call check,$1,"\`$2' is not a link to \`$3'", \ | |
430 | [ -L "$2" ] && [ "$$(readlink "$2")" = "$3" ]) | |
431 | ||
8905fb7a MW |
432 | ## DIR/ |
433 | ## | |
434 | ## Make a directory. Use as an order-only dependency. | |
435 | %/:; $(V_AT)mkdir -p $@ | |
436 | ||
3e5b03e2 | 437 | ###-------------------------------------------------------------------------- |
a4c5d71a MW |
438 | ### Python extensions. |
439 | ||
440 | CC = gcc | |
441 | CFLAGS = -O2 -g -Wall | |
442 | ||
443 | LD = $(CC) | |
444 | LDFLAGS = | |
445 | ||
446 | c-source = $(foreach c,$1,src/$c) | |
447 | c-object = $(foreach c,$1,$(STATE)/obj/$(basename $c).o) | |
448 | ||
449 | PYEXT_PKGFLAGS := $(shell pkg-config --cflags python2) | |
450 | PYEXT_CFLAGS = -fPIC -fno-strict-aliasing $(PYEXT_PKGFLAGS) | |
451 | PYEXT_LDFLAGS = -shared | |
452 | ||
453 | PYEXTS += jobclient | |
454 | jobclient_SOURCES = jobclient.c | |
455 | ||
456 | PYEXT_ALLSRC = $(foreach x,$(PYEXTS),\ | |
457 | $(call c-source,$($x_SOURCES))) | |
458 | PYEXT_ALLOBJ = $(foreach x,$(PYEXTS),\ | |
459 | $(call c-object,$($x_SOURCES))) | |
8905fb7a | 460 | $(PYEXT_ALLOBJ): $(STATE)/obj/%.o: src/%.c | $$(dir $$@) |
a4c5d71a MW |
461 | $(call v_tag,CC)$(CC) -c $(CFLAGS) $(PYEXT_CFLAGS) -o$@ $< |
462 | ||
463 | PYMODULES = $(foreach x,$(PYEXTS),$(STATE)/lib/python/$x.so) | |
a914e882 | 464 | all: $(PYMODULES) |
8905fb7a MW |
465 | $(PYMODULES): $(STATE)/lib/python/%.so: \ |
466 | $$(call c-object,$$($$*_SOURCES)) | $$(dir $$@) | |
a4c5d71a MW |
467 | $(call v_tag,LD)$(LD) $(LDFLAGS) $(PYEXT_LDFLAGS) -o$@ $^ |
468 | ||
469 | ###-------------------------------------------------------------------------- | |
3e5b03e2 MW |
470 | ### Scripts. |
471 | ||
a98c9dba | 472 | SCRIPTS += chroot-maint |
3e5b03e2 | 473 | SCRIPTS += mkchrootconf |
3e5b03e2 MW |
474 | |
475 | SUBST_SCRIPTS = $(addprefix $(STATE)/bin/,$(SCRIPTS)) | |
a914e882 | 476 | all: $(SUBST_SCRIPTS) |
8905fb7a | 477 | $(SUBST_SCRIPTS): $(STATE)/bin/%: bin/% $(STATE)/config.sh | $$(dir $$@) |
3e5b03e2 MW |
478 | $(call v_tag,SUBST){ \ |
479 | sed \ | |
480 | -e '2i### GENERATED by distorted-chroot: do not edit' \ | |
481 | -e '/@@@config@@@/ {' \ | |
482 | -e 'r $(STATE)/config.sh' \ | |
483 | -e 'd'\ | |
484 | -e '}' $<; \ | |
485 | } >$@.new && chmod +x $@.new && mv $@.new $@ | |
e36b4f25 MW |
486 | |
487 | ###-------------------------------------------------------------------------- | |
488 | ### APT configuration. | |
489 | ||
490 | ## In a chroot, `/etc/apt/sources.list' links to | |
491 | ## `/usr/local.schroot/etc/apt/sources.$d' for the appropriate distribution. | |
4004ed52 | 492 | APT_SOURCES = $(foreach d,$(DISTS),$(LOCAL)/etc/apt/sources.$d) |
a914e882 | 493 | all: $(APT_SOURCES) |
e36b4f25 | 494 | |
8905fb7a MW |
495 | $(foreach d,$(DISTS),$(STATE)/etc/apt/aptsrc.$d): \ |
496 | $(STATE)/etc/apt/aptsrc.%: | $$(dir $$@) | |
e36b4f25 MW |
497 | $(call v_tag,GEN){ \ |
498 | echo "### -*-conf-*- GENERATED by distorted-chroot: do not edit"; \ | |
499 | echo "subscribe"; \ | |
500 | echo " debian : $*"; \ | |
501 | } >$@.new && mv $@.new $@ | |
502 | ||
503 | $(APT_SOURCES): $(LOCAL)/etc/apt/sources.%: \ | |
8905fb7a MW |
504 | $$(APTSRC) $$($$*_APTSRC) $$(STATE)/etc/apt/aptsrc.$$* \ |
505 | | $$(dir $$@) | |
e36b4f25 MW |
506 | $(call v_tag,GEN)bin/mkaptsrc \ |
507 | $(APTSRC) $($*_APTSRC) $(STATE)/etc/apt/aptsrc.$* \ | |
508 | >$@.new && mv $@.new $@ | |
0539140c | 509 | CLEANFILES += $(APT_SOURCES) |
e36b4f25 MW |
510 | |
511 | ## In a chroot, a link `/etc/apt/apt.conf.d/FOO' is created for each file in | |
512 | ## `/usr/local.schroot/etc/apt/apt.conf.d/FOO'. | |
513 | APT_CONFIGS = $(addprefix $(LOCAL)/etc/apt/apt.conf.d/,$(APTCONF)) | |
a914e882 | 514 | all: $(APT_CONFIGS) |
e36b4f25 | 515 | $(APT_CONFIGS): $(LOCAL)/etc/apt/apt.conf.d/%: \ |
8905fb7a | 516 | $$(or $$(_$$*_APTCONFSRC) etc/apt-conf.d/$$*) | $$(dir $$@) |
e36b4f25 | 517 | $(call v_tag,COPY)cp $< $@.new && mv $@.new $@ |
3e5b03e2 MW |
518 | clean::; rm -f $(APT_CONFIGS) |
519 | ||
520 | ###-------------------------------------------------------------------------- | |
521 | ### Build hacks. | |
522 | ||
523 | check::; $(call check-executable,ERR,/usr/bin/eatmydata) | |
524 | ||
525 | EATMYDATA_HACKS += apt-get aptitude dpkg | |
526 | SYMLINK_EATMYDATA_HACKS = $(addprefix $(LOCAL)/hacks/,$(EATMYDATA_HACKS)) | |
a914e882 | 527 | all: $(SYMLINK_EATMYDATA_HACKS) |
3e5b03e2 | 528 | $(SYMLINK_EATMYDATA_HACKS): $(LOCAL)/hacks/%: \ |
8905fb7a MW |
529 | $$(if $$(call symlink-ok-p,$$@,/usr/bin/eatmydata),,_force) \ |
530 | | $$(dir $$@) | |
3e5b03e2 MW |
531 | $(call v_tag,SYMLINK)ln -sf /usr/bin/eatmydata $@.new && mv $@.new $@ |
532 | clean::; rm -f $(SYMLINK_EATMYDATA_HACKS) | |
533 | ||
534 | SCRIPT_HACKS += buildwrap | |
535 | COPY_SCRIPT_HACKS = $(addprefix $(LOCAL)/hacks/,$(SCRIPT_HACKS)) | |
a914e882 | 536 | all: $(COPY_SCRIPT_HACKS) |
8905fb7a | 537 | $(COPY_SCRIPT_HACKS): $(LOCAL)/hacks/%: bin/% | $$(dir $$@) |
3e5b03e2 MW |
538 | $(call v_tag,COPY)cp $< $@.new && mv $@.new $@ |
539 | clean::; rm -f $(COPY_SCRIPT_HACKS) | |
e36b4f25 MW |
540 | |
541 | ###-------------------------------------------------------------------------- | |
542 | ### `schroot' and `sbuild' configuration. | |
543 | ||
a914e882 MW |
544 | all: schroot-config |
545 | schroot-config: | |
e36b4f25 MW |
546 | .PHONY: schroot-config |
547 | ||
3e5b03e2 MW |
548 | check::; $(call check-mountpoint,WARN,/var/lib/sbuild/build) |
549 | check::; $(call check-symlink,WARN,/build,/var/lib/sbuild/build) | |
550 | check::; $(call check-symlink,ERR,/schroot,/run/schroot/mount) | |
551 | ||
e36b4f25 MW |
552 | %print-varlist = { \ |
553 | echo "\#\#\# -*-sh-*- GENERATED by distorted-chroot: do not edit"; \ | |
a98c9dba MW |
554 | $(foreach v,$1,$(if $(call definedp,$v),\ |
555 | echo $v=\'$(call squote,$($v))\';)) \ | |
fb28f2a8 | 556 | } |
e36b4f25 MW |
557 | schroot-config_HASH := \ |
558 | $(shell $(call %print-varlist,$(CONFIG_VARS)) | \ | |
559 | sha256sum | cut -c1-32) | |
560 | schroot-config_FILE = $(STATE)/config.sh-$(schroot-config_HASH) | |
8905fb7a | 561 | $(schroot-config_FILE): | $(STATE)/ |
e36b4f25 | 562 | $(V_AT)rm -f $(STATE)/config.sh-* |
6ccac28c | 563 | $(call v_tag,GEN)$(call %print-varlist,$(CONFIG_VARS)) \ |
e36b4f25 MW |
564 | >$@.new && mv $@.new $@ |
565 | ||
a914e882 | 566 | schroot-config: $(STATE)/config.sh |
e36b4f25 | 567 | $(STATE)/config.sh: $(schroot-config_FILE) |
8905fb7a | 568 | $(call v_tag,SYMLINK)ln -sf $(call base-name,$<) $@ |
e36b4f25 | 569 | |
a914e882 | 570 | schroot-config: $(LOCAL)/etc/schroot/sbuild.schroot |
8905fb7a | 571 | $(LOCAL)/etc/schroot/sbuild.schroot: $(STATE)/bin/mkchrootconf | $$(dir $$@) |
3e5b03e2 MW |
572 | $(call v_tag,GEN)$(STATE)/bin/mkchrootconf >$@.new && \ |
573 | $(ROOTLY) chown root:root $@.new && mv $@.new $@ | |
67a8479c | 574 | CLEANFILES += $(LOCAL)/etc/schroot/sbuild.schroot |
8918e451 | 575 | check::; $(call check-symlink,WARN,/etc/schroot/chroot.d/sbuild,$(ABSLOCAL)/etc/schroot/sbuild.schroot) |
e36b4f25 | 576 | |
a914e882 | 577 | schroot-config: $(LOCAL)/etc/schroot/sbuild.profile/copyfiles |
8905fb7a MW |
578 | $(LOCAL)/etc/schroot/sbuild.profile/copyfiles: \ |
579 | $(schroot-config_STAMP) | $$(dir $$@) | |
e36b4f25 MW |
580 | $(call v_tag,GEN){ \ |
581 | echo "### -*-conf-*- GENERATED by distorted-chroot: do not edit"; \ | |
582 | for i in $(SCHROOT_COPYFILES); do echo "$$i"; done; \ | |
583 | } >$@.new && mv $@.new $@ | |
67a8479c | 584 | CLEANFILES += $(LOCAL)/etc/schroot/sbuild.profile/copyfiles |
e36b4f25 | 585 | |
a914e882 | 586 | schroot-config: $(LOCAL)/etc/schroot/sbuild.profile/nssdatabases |
8905fb7a MW |
587 | $(LOCAL)/etc/schroot/sbuild.profile/nssdatabases: \ |
588 | $(schroot-config_STAMP) | $$(dir $$@) | |
e36b4f25 MW |
589 | $(call v_tag,GEN){ \ |
590 | echo "### -*-conf-*- GENERATED by distorted-chroot: do not edit"; \ | |
591 | for i in $(SCHROOT_NSSDATABASES); do echo "$$i"; done; \ | |
592 | } >$@.new && mv $@.new $@ | |
67a8479c | 593 | CLEANFILES += $(LOCAL)/etc/schroot/sbuild.profile/nssdatabases |
e36b4f25 | 594 | |
a914e882 | 595 | schroot-config: $(LOCAL)/etc/schroot/sbuild.profile/fstab |
67a8479c | 596 | $(LOCAL)/etc/schroot/sbuild.profile/fstab: \ |
8905fb7a | 597 | etc/sbuild.fstab.in $(schroot-config_STAMP) | $$(dir $$@) |
e36b4f25 MW |
598 | $(call v_tag,SUBST)$(call subst-file,### -*-conf-*-) \ |
599 | <$< >$@.new && mv $@.new $@ | |
67a8479c | 600 | CLEANFILES += $(LOCAL)/etc/schroot/sbuild.profile/fstab |
e36b4f25 | 601 | |
8918e451 | 602 | check::; $(call check-symlink,WARN,/etc/schroot/sbuild,$(ABSLOCAL)/etc/schroot/sbuild.profile) |
3e5b03e2 | 603 | |
a914e882 | 604 | schroot-config: $(LOCAL)/etc/sbuild.conf |
8905fb7a MW |
605 | $(LOCAL)/etc/sbuild.conf: etc/sbuild.conf.in \ |
606 | $(schroot-config_STAMP) | $$(dir $$@) | |
e36b4f25 MW |
607 | $(call v_tag,SUBST)$(call subst-file,### -*-perl-*-) \ |
608 | <$< >$@.new && mv $@.new $@ | |
67a8479c | 609 | CLEANFILES += $(LOCAL)/etc/sbuild.conf |
8918e451 | 610 | check::; $(call check-symlink,WARN,/etc/sbuild/sbuild.conf,$(ABSLOCAL)/etc/sbuild.conf) |
d56d9258 | 611 | check::; $(call check-executable,WARN,/usr/local.schroot/hacks/apt-get) |
e36b4f25 | 612 | |
3e5b03e2 MW |
613 | SCHROOT_SCRIPTS += 11private |
614 | SCHROOT_SCRIPTS += 15binfmt | |
615 | SCHROOT_SCRIPTS += 51chrootenv | |
67a8479c | 616 | COPY_SCHROOT_SCRIPTS = $(addprefix $(LOCAL)/etc/schroot/setup.d/,$(SCHROOT_SCRIPTS)) |
a914e882 | 617 | schroot-config: $(COPY_SCHROOT_SCRIPTS) |
3e5b03e2 | 618 | $(COPY_SCHROOT_SCRIPTS): \ |
8905fb7a MW |
619 | $(LOCAL)/etc/schroot/setup.d/%: etc/schroot-scripts/% \ |
620 | | $$(dir $$@) | |
3e5b03e2 | 621 | $(call v_tag,COPY)cp $< $@.new && mv $@.new $@ |
67a8479c | 622 | CLEANFILES += $(COPY_SCHROOT_SCRIPTS) |
3e5b03e2 MW |
623 | |
624 | CHECK_SCHROOT_SCRIPTS = $(addprefix check-script/,$(SCHROOT_SCRIPTS)) | |
625 | check:: $(CHECK_SCHROOT_SCRIPTS) | |
626 | $(CHECK_SCHROOT_SCRIPTS): check-script/%: | |
8918e451 | 627 | $(call check-symlink,WARN,/etc/schroot/setup.d/$*,$(ABSLOCAL)/etc/schroot/setup.d/$*) |
3e5b03e2 MW |
628 | .PHONY: $(addprefix check-script/,$(SCHROOT_SCRIPTS)) |
629 | ||
630 | ###-------------------------------------------------------------------------- | |
0a9fcbbc MW |
631 | ### Ccache setup. |
632 | ||
633 | CCACHE_CONFIGS = $(foreach r,$(ALL_CHROOTS), \ | |
634 | /var/lib/sbuild/build/.ccache/$(LVPREFIX)$r/ccache.conf) | |
a914e882 | 635 | all: $(CCACHE_CONFIGS) |
0a9fcbbc | 636 | $(CCACHE_CONFIGS): /var/lib/sbuild/build/.ccache/$(LVPREFIX)%/ccache.conf: \ |
8905fb7a | 637 | etc/ccache.conf | $$(dir $$@) |
0a9fcbbc MW |
638 | $(call v_tag,COPY)cp $< $@.new && mv $@.new $@ |
639 | ||
640 | ###-------------------------------------------------------------------------- | |
3e5b03e2 MW |
641 | ### `/usr/local/' structure. |
642 | ||
643 | LOCAL_COMMON_DIRS = share/ src/ | |
27922408 | 644 | LOCAL_EXTRA_DIRS = share/man/ |
a914e882 | 645 | all: $(foreach d,$(LOCAL_COMMON_DIRS) $(LOCAL_EXTRA_DIRS),$(LOCAL)/$d) |
3e5b03e2 | 646 | |
942fed18 MW |
647 | LOCAL_ARCH_DIRS = bin/ etc/ games/ include/ include.aside/ |
648 | LOCAL_ARCH_DIRS += lib/ libexec/ sbin/ | |
3e5b03e2 MW |
649 | LOCAL_ARCH_LINKS = man |
650 | man_LINKDEST = share/man | |
a914e882 | 651 | all: $(foreach a,$(ALL_ARCHS),\ |
3e5b03e2 MW |
652 | $(LOCAL)/$a/ \ |
653 | $(foreach d,$(LOCAL_ARCH_DIRS),$(LOCAL)/$a/$d) \ | |
654 | $(foreach d,$(LOCAL_ARCH_LINKS),$(LOCAL)/$a/$d) \ | |
655 | $(foreach d,$(LOCAL_COMMON_DIRS),$(LOCAL)/$a/$d)) | |
656 | ||
3e5b03e2 MW |
657 | $(foreach a,$(ALL_ARCHS),\ |
658 | $(foreach d,$(LOCAL_ARCH_LINKS),$(LOCAL)/$a/$d)): \ | |
800139e6 | 659 | $$(if $$(call symlink-ok-p,$$@,$$($$(call base-name,$$@)_LINKDEST)),,_force) \ |
8905fb7a | 660 | | $$(dir $$@) |
800139e6 | 661 | $(call v_tag,SYMLINK)ln -sf $($(call base-name,$@)_LINKDEST) $@ |
3e5b03e2 MW |
662 | $(foreach a,$(ALL_ARCHS),\ |
663 | $(foreach d,$(LOCAL_COMMON_DIRS),$(LOCAL)/$a/$d)): \ | |
800139e6 | 664 | $$(if $$(call symlink-ok-p,$$@,../$$(call base-name,$$@)),,_force) \ |
8905fb7a | 665 | | $$(call parent-dir,$$@) |
800139e6 | 666 | $(call v_tag,SYMLINK)ln -sf ../$(call base-name,$@) $(call file-name,$@) |
3e5b03e2 | 667 | |
e36b4f25 | 668 | ###-------------------------------------------------------------------------- |
a98c9dba | 669 | ### Main chroot maintenance. |
e36b4f25 | 670 | |
a98c9dba | 671 | OPTS = |
642f47f9 | 672 | FRESH = 1w |
a98c9dba MW |
673 | JOBS = chroot cross-tools pkg-build |
674 | ||
675 | MAINTQ_ = -q | |
676 | MAINTQ_0 = -q | |
fe87403b | 677 | MAINT = +$(call v_tag,MAINT)\ |
a98c9dba MW |
678 | PYTHONPATH=$(STATE)/lib/python $(STATE)/bin/chroot-maint \ |
679 | $(MAINTQ_$V) $(OPTS) | |
680 | ||
681 | maint: all check | |
682 | $(MAINT) -f$(FRESH) $(JOBS) | |
683 | .PHONY: maint | |
e36b4f25 | 684 | |
408e5644 MW |
685 | help:: |
686 | @echo "Maintenance targets" && \ | |
687 | echo " maint run chroot maintenance" && \ | |
688 | echo "Maintenance variables" && \ | |
689 | echo " FRESH max time between updates" && \ | |
690 | echo " N[smhdw] | create | force" && \ | |
691 | echo " JOBS maintenance jobs to run" && \ | |
692 | echo " ACT[.PAT,...][/FRESH]" && \ | |
693 | echo " OPTS additional options (bin/chroot-maint --help)" && \ | |
694 | echo "Maintenance actions" && \ | |
695 | echo " chroot create and populate chroot" && \ | |
696 | echo " cross-tools build cross-compilation toolchains" && \ | |
697 | echo " pkg-source download and unpack local utilities" && \ | |
698 | echo " pkg-build compile and install local utilities" | |
699 | ||
e36b4f25 | 700 | ###-------------------------------------------------------------------------- |
7443a1fb MW |
701 | ### Running random commands. |
702 | ||
703 | CMD = echo %d %a | |
704 | subst-command = $(subst %d,$(call chroot-dist,$1), \ | |
705 | $(subst %a,$(call chroot-arch,$1), \ | |
706 | $(subst %r,$1, $(CMD)))) | |
707 | ||
708 | run: $(foreach c,$(ALL_CHROOTS),run/$c) | |
709 | $(foreach c,$(ALL_CHROOTS),run/$c): run/%: | |
710 | $(V_AT)$(call v_print,RUN,$(call subst-command,$*))\ | |
711 | $(call subst-command,$*) | |
712 | ||
713 | ###-------------------------------------------------------------------------- | |
e36b4f25 MW |
714 | ### Other maintenance targets. |
715 | ||
716 | show:; : $x | |
717 | ||
718 | clean:: | |
719 | rm -f $(CLEANFILES) | |
720 | rm -rf $(STATE) | |
721 | ||
722 | realclean:: clean | |
723 | rm -rf $(LOCAL) | |
724 | ||
725 | ###----- That's all, folks -------------------------------------------------- |