master
ninqu.rules
1; genconfig.sh config produces four files from build.cfg in one
2; invocation: config.set (read by ninqu), config.kv (read by mkman),
3; nofork_list.h (included by wexec.c), and features.h (-included
4; into every compile). only CONFIG_SET actually runs the script;
5; NOFORK_LIST_H and FEATURES_H depend on its output instead of
6; re-running genconfig.sh themselves, so ninja never schedules two
7; invocations of the same script concurrently. running it twice in
8; parallel raced both invocations' truncate-then-append writes to
9; the same files, byte-interleaving their output into invalid C
10;
11(rule CONFIG_SET
12 (out "scripts/mk/config.set")
13 (dep "build.cfg" "scripts/genconfig.sh")
14 (exec sh scripts/genconfig.sh config))
15
16(rule NOFORK_LIST_H
17 (out "shared/libutil/nofork_list.h")
18 (dep "scripts/mk/config.set")
19 (exec true))
20
21(rule FEATURES_H
22 (out "scripts/mk/features.h")
23 (dep "scripts/mk/config.set")
24 (exec true))
25
26(set-file "scripts/mk/config.set")
27
28; static libraries: compile every .c in each lib dir then AR
29;
30(rule LIBUTF_OBJ
31 (glob "shared/libutf/*.c")
32 (dep $(MATCH))
33 (out "$(STEM).o")
34 (exec $(CC) $(CPPFLAGS) -Ishared/libutf $(CFLAGS) -c -o $(OUT) $(MATCH)))
35
36 (rule LIBUTF
37 (dep LIBUTF_OBJ)
38 (out "shared/libutf/libutf.a")
39 (description "utf-8 and rune handling, linked into every aruu tool")
40 (feature core-lib)
41 (exec $(AR) $(ARFLAGS) $(OUT) $(IN)))
42
43 (rule LIBUTIL_OBJ
44 (glob "shared/libutil/*.c")
45 (dep $(MATCH))
46 (after NOFORK_LIST_H FEATURES_H)
47 (out "$(STEM).o")
48 (exec $(CC) $(CPPFLAGS_LIBUTIL) -Ishared/libutil $(CFLAGS) -c -o $(OUT) $(MATCH)))
49
50 (rule LIBUTIL
51 (dep LIBUTIL_OBJ)
52 (out "shared/libutil/libutil.a")
53 (description "allocation, error reporting, and string helpers shared by every tool")
54 (feature core-lib)
55 (exec $(AR) $(ARFLAGS) $(OUT) $(IN)))
56
57 (rule LIBREDLINE_OBJ
58 (glob "shared/libredline/*.c")
59 (dep $(MATCH))
60 (out "$(STEM).o")
61 (exec $(CC) $(CPPFLAGS) -Ishared/libredline $(CFLAGS) -c -o $(OUT) $(MATCH)))
62
63 (rule LIBREDLINE
64 (dep LIBREDLINE_OBJ)
65 (out "shared/libredline/libredline.a")
66 (description "line editing used by sh and any other interactive tool")
67 (feature core-lib)
68 (exec $(AR) $(ARFLAGS) $(OUT) $(IN)))
69
70 (rule LIBBLAKE3_OBJ
71 (glob "shared/libblake3/*.c")
72 (dep $(MATCH))
73 (out "$(STEM).o")
74 (exec $(CC) $(CPPFLAGS) -Ishared/libblake3 $(CFLAGS) -c -o $(OUT) $(MATCH)))
75
76 (rule LIBBLAKE3
77 (dep LIBBLAKE3_OBJ)
78 (out "shared/libblake3/libblake3.a")
79 (description "the BLAKE3 hash algorithm, linked into b3sum, not embedded in it")
80 (feature core-lib)
81 (exec $(AR) $(ARFLAGS) $(OUT) $(IN)))
82
83 (group lib LIBUTF LIBUTIL LIBREDLINE LIBBLAKE3)
84
85 ; perfile: every *.c directly inside one of these dirs becomes its
86 ; own binary of the same name, individually gated by
87 ; build_<category>_<ident> (lowercase, hyphens and dots turned to
88 ; underscores, see the $(IDENT) comment above BOX_OBJ below for why)
89 ; (skip) excludes files that belong to a multi-file tool below instead
90 ;
91 ; -lcrypt and -lresolv used to be blanket LDLIBS entries, linked into
92 ; every single utility whether it called crypt(3)/resolver functions
93 ; or not. tracing real callers of shared/libutil/passwd.c's pw_check/
94 ; pw_gensalt (not just direct crypt() calls) turns up exactly four:
95 ; passwd, mkpasswd, login, su need -lcrypt; host needs -lresolv
96 ; narrowing this here, not just for tidiness, is what makes aruu
97 ; buildable on a host whose libc ships a static libresolv/libm but no
98 ; static libcrypt. b3sum is the one EXTRA_BIN file with its own extra
99 ; library dependency for a different reason: BLAKE3 used to be
100 ; implemented inline in b3sum.c itself, which meant anything else
101 ; that wanted the same algorithm (ports/pkgtools/libpkg, for hashing
102 ; package archives) had no real library to link against and carried
103 ; its own separate copy instead, with no way to notice the two had
104 ; drifted until one of them turned out to have a bug the other one
105 ; didn't. shared/libblake3 exists so there is exactly one copy
106 (map EXTRA_LIBS
107 (diff "-lm")
108 (wget $(LDLIBS_TLS))
109 (passwd "-lcrypt")
110 (mkpasswd "-lcrypt")
111 (login "-lcrypt")
112 (su "-lcrypt")
113 (host "-lresolv")
114 (b3sum "-Lshared/libblake3 -lblake3"))
115
116 ; every .c file in a category builds into its own binary. (PERFILE)
117 ; only EXTRA_AFTER differs cuz POSIX waits for GETCONF_H, the rest pass ""
118 ; cmd/posix/bc.c overrides this with its own yacc-based rule, so no need for
119 ; PERFILE to have that as a special case
120 ;
121 (template PERFILE (NAME CATEGORY DESC EXTRA_AFTER)
122 (rule $(NAME)
123 (glob "cmd/$(CATEGORY)/*.c")
124 (gate build_$(CATEGORY)_$(IDENT))
125 (dep $(MATCH) LIBUTIL LIBUTF LIBBLAKE3)
126 (after $(EXTRA_AFTER))
127 (out $(STEM))
128 (description $(DESC))
129 (feature perfile)
130 (exec $(CC) $(CPPFLAGS) $(CFLAGS) -o $(OUT) $(IN) $(LDFLAGS) $(LDLIBS) $(EXTRA_LIBS:$(BASESTEM)))))
131
132 (use PERFILE POSIX_BIN posix "one POSIX2024 utility per source file under cmd/posix" GETCONF_H)
133 (use PERFILE LINUX_BIN linux "linux-only utility, one source file per binary under cmd/linux" "")
134 (use PERFILE NET_BIN net "networking utility, one source file per binary under cmd/net" "")
135 (use PERFILE XSI_BIN xsi "xsi-specified utility, one source file per binary under cmd/xsi" "")
136 (use PERFILE PSEUDO_BIN pseudo "common but undefined utility, one source file per binary under cmd/pseudo" "")
137 (use PERFILE EXTRA_BIN extra "extra utility outside POSIX/XSI scope, one source file per binary under cmd/extra" "")
138
139 (group posix lib POSIX_BIN POSIX_BC POSIX_AWK POSIX_SH POSIX_MAKE)
140 (group linux lib LINUX_BIN)
141 (group net lib NET_BIN)
142 (group xsi lib XSI_BIN)
143 (group pseudo lib PSEUDO_BIN)
144 (group extra lib EXTRA_BIN EXTRA_YAP)
145
146 ; codegen: generate sources consumed by the build rules below. ungated
147 ; ones always run. conditional ones use (req) so they only run when
148 ; their inputs exists in this checkout
149 ;
150 (rule GETCONF_H
151 (gate build_posix_getconf)
152 (out "cmd/posix/getconf.h")
153 (dep "scripts/getconf.sh")
154 (exec sh scripts/genconfig.sh getconf))
155
156 (rule POSIX_BC_C
157 (gate build_posix_bc)
158 (req "cmd/posix/bc.y")
159 (out "cmd/posix/bc.c")
160 (dep "cmd/posix/bc.y")
161 (exec sh scripts/genconfig.sh bc))
162
163 (rule POSIX_AWK_C
164 (gate build_posix_awk)
165 (out "cmd/posix/awk/awkgram.tab.c")
166 (dep "cmd/posix/awk/awkgram.y")
167 (exec sh scripts/genconfig.sh awk))
168
169 (rule POSIX_SH_C
170 (gate build_posix_sh)
171 (out "cmd/posix/sh/syntax.c")
172 (dep "cmd/posix/sh/mksyntax.c" "cmd/posix/sh/mknodes.c" "cmd/posix/sh/mkbuiltins" "cmd/posix/sh/mktokens")
173 (exec sh scripts/genconfig.sh sh))
174
175 (rule DEVCONF
176 (req "cmd/dev/configure")
177 (out "cmd/dev/config.h")
178 (dep "cmd/dev/configure")
179 (phony)
180 (exec sh cmd/dev/configure))
181
182 (group codegen GETCONF_H POSIX_BC_C POSIX_AWK_C POSIX_SH_C DEVCONF)
183
184 ; multi: one binary from all .c files in one or more dirs (minus skip)
185 ; codegen must run first so generated sources are present before these
186 ; globs collect them
187 ;
188 (rule POSIX_BC_OBJ
189 (glob "cmd/posix/bc.c")
190 (gate build_posix_bc)
191 (dep $(MATCH))
192 (after POSIX_BC_C)
193 (out "$(STEM).o")
194 (exec $(CC) $(CPPFLAGS) $(CFLAGS) -c -o $(OUT) $(MATCH)))
195
196 (rule POSIX_BC
197 (gate build_posix_bc)
198 (member posix bc)
199 (dep POSIX_BC_OBJ LIBUTIL LIBUTF)
200 (out "cmd/posix/bc")
201 (exec $(CC) -o $(OUT) $(IN) $(LDFLAGS) $(LDLIBS) -lm))
202
203 (rule POSIX_AWK_OBJ
204 (glob "cmd/posix/awk/*.c")
205 (gate build_posix_awk)
206 (skip "maketab.c")
207 (dep $(MATCH))
208 (after POSIX_AWK_C)
209 (out "$(STEM).o")
210 (exec $(CC) $(CPPFLAGS) -Icmd/posix/awk $(CFLAGS) -c -o $(OUT) $(MATCH)))
211
212 (rule POSIX_AWK
213 (gate build_posix_awk)
214 (member posix awk)
215 (dep POSIX_AWK_OBJ LIBUTIL LIBUTF)
216 (out "cmd/posix/awk/awk")
217 (exec $(CC) -o $(OUT) $(IN) $(LDFLAGS) $(LDLIBS) -lm))
218
219 (rule POSIX_SH_OBJ
220 (glob "cmd/posix/sh/*.c")
221 (gate build_posix_sh)
222 (skip "mknodes.c" "mksyntax.c")
223 (dep $(MATCH))
224 (after POSIX_SH_C)
225 (out "$(STEM).o")
226 (exec $(CC) $(CPPFLAGS) -DSHELL -Icmd/posix/sh $(CFLAGS) -c -o $(OUT) $(MATCH)))
227
228 (rule POSIX_SH
229 (gate build_posix_sh)
230 (member posix sh)
231 (dep POSIX_SH_OBJ LIBUTIL LIBUTF LIBREDLINE)
232 (out "cmd/posix/sh/sh")
233 (exec $(CC) -o $(OUT) $(IN) $(LDFLAGS) $(LDLIBS)))
234
235 (rule POSIX_MAKE_OBJ
236 (glob "cmd/posix/make/*.c")
237 (gate build_posix_make)
238 (dep $(MATCH))
239 (out "$(STEM).o")
240 (exec $(CC) $(CPPFLAGS) $(CFLAGS) -c -o $(OUT) $(MATCH)))
241
242 (rule POSIX_MAKE
243 (gate build_posix_make)
244 (member posix make)
245 (dep POSIX_MAKE_OBJ LIBUTIL LIBUTF)
246 (out "cmd/posix/make/make")
247 (exec $(CC) -o $(OUT) $(IN) $(LDFLAGS) $(LDLIBS)))
248
249 (rule EXTRA_YAP_OBJ
250 (glob "cmd/extra/yap/*.c")
251 (gate build_extra_yap)
252 (dep $(MATCH))
253 (out "$(STEM).o")
254 (exec $(CC) $(CPPFLAGS) $(CFLAGS) -c -o $(OUT) $(MATCH)))
255
256 (rule EXTRA_YAP
257 (gate build_extra_yap)
258 (member extra yap)
259 (dep EXTRA_YAP_OBJ LIBUTIL LIBUTF)
260 (out "cmd/extra/yap/yap")
261 (exec $(CC) -o $(OUT) $(IN) $(LDFLAGS) $(LDLIBS) -ltinfo))
262
263 ; (member GROUP ALIAS) gives a rule a qualified user-facing name
264 ; (e.g. posix/bc) while keeping its internal name (POSIX_BC) for deps,
265 ; gates, and other references
266 ;
267
268 ; dev: the aruu toolchain. ar/as/ld are standalone and cc
269 ; shares one object pool linked into three frontends
270 ;
271 (rule AR_OBJ
272 (glob "cmd/dev/ar/*.c")
273 (gate build_dev_ar)
274 (skip "tinyar.c")
275 (dep $(MATCH))
276 (out "$(STEM).o")
277 (exec $(CC) $(CPPFLAGS) -Icmd/dev/ar $(CFLAGS) -c -o $(OUT) $(MATCH)))
278
279 (rule AR
280 (gate build_dev_ar)
281 (dep AR_OBJ LIBUTIL LIBUTF)
282 ; static: these tools run inside whatever rootfs they target via
283 ; nac, not just the host that built them, and never need the
284 ; project-wide LDLIBS default (openssl, unused by any of them)
285 (out "cmd/dev/ar/ar")
286 (exec $(CC) -static -o $(OUT) $(IN) $(LDFLAGS)))
287
288 (rule TCUTIL_OBJ
289 (glob "shared/libtcutil/*.c" "shared/libtcutil/elf/*.c" "shared/libtcutil/ar/*.c")
290 (gate build_dev_cc)
291 (dep $(MATCH))
292 (out "$(STEM).o")
293 (exec $(CC) $(CPPFLAGS) -Ishared/libtcutil -Ishared/libtcutil/elf -Ishared/libtcutil/ar -Icmd/dev $(CFLAGS) -c -o $(OUT) $(MATCH)))
294
295 (rule AS_OBJ
296 (glob "cmd/dev/as/*.c" "cmd/dev/as/arch/x64/*.c")
297 (gate build_dev_cc)
298 (dep $(MATCH))
299 (out "$(STEM).o")
300 (exec $(CC) $(CPPFLAGS) -Ishared/libtcutil -Ishared/libtcutil/elf -Ishared/libtcutil/ar -Icmd/dev -Icmd/dev/as -Icmd/dev/as/arch/x64 -Ishared $(CFLAGS) -c -o $(OUT) $(MATCH)))
301
302 (rule AS
303 (gate build_dev_cc)
304 (dep AS_OBJ TCUTIL_OBJ LIBUTIL LIBUTF)
305 (out "cmd/dev/as/as")
306 (exec $(CC) -static -o $(OUT) $(IN) $(LDFLAGS)))
307
308 (rule LD_OBJ
309 (glob "cmd/dev/ld/*.c" "cmd/dev/ld/arch/*/*.c")
310 (gate build_dev_ld)
311 (dep $(MATCH))
312 (out "$(STEM).o")
313 (exec $(CC) $(CPPFLAGS) -Icmd/dev/ld $(CFLAGS) -c -o $(OUT) $(MATCH)))
314
315 (rule LD
316 (gate build_dev_ld)
317 (dep LD_OBJ LIBUTIL LIBUTF)
318 (out "cmd/dev/ld/ld")
319 (exec $(CC) -static -o $(OUT) $(IN) $(LDFLAGS)))
320
321 ; CCPOOL_OBJ globs the whole directory. the entry points below use
322 ; literal globs, so the override excludes them automatically
323 (rule CCPOOL_OBJ
324 (glob "cmd/dev/cc/*.c")
325 (gate build_dev_cc)
326 (dep $(MATCH))
327 (out "$(STEM).o")
328 (exec $(CC) $(CPPFLAGS) -Icmd/dev/cc $(CFLAGS) -c -o $(OUT) $(MATCH)))
329
330 (rule CC1_OBJ
331 (glob "cmd/dev/cc/cc1.c")
332 (gate build_dev_cc)
333 (dep $(MATCH))
334 (out "$(STEM).o")
335 (exec $(CC) $(CPPFLAGS) -Icmd/dev/cc $(CFLAGS) -c -o $(OUT) $(MATCH)))
336
337 ; util.c is its own rule, not folded into CCPOOL_OBJ's wildcard or
338 ; CCDRV_OBJ's own glob: cc1, cpp, and cc (the driver) all call its
339 ; helpers (fatal, xmalloc, arrayadd, ...), but only cc has its own
340 ; main(), so driver.c cannot be a shared link input the other two
341 ; binaries pull in too
342 (rule UTIL_OBJ
343 (glob "cmd/dev/cc/util.c")
344 (gate build_dev_cc)
345 (dep $(MATCH))
346 (out "$(STEM).o")
347 (exec $(CC) $(CPPFLAGS) -Icmd/dev/cc $(CFLAGS) -c -o $(OUT) $(MATCH)))
348
349 (rule CC1
350 (gate build_dev_cc)
351 (dep CC1_OBJ CCPOOL_OBJ UTIL_OBJ LIBUTIL LIBUTF)
352 (out "cmd/dev/cc/cc1")
353 (exec $(CC) -static -o $(OUT) $(IN) $(LDFLAGS)))
354
355 (rule CPP_OBJ
356 (glob "cmd/dev/cc/cpp.c")
357 (gate build_dev_cc)
358 (dep $(MATCH))
359 (out "$(STEM).o")
360 (exec $(CC) $(CPPFLAGS) -Icmd/dev/cc $(CFLAGS) -c -o $(OUT) $(MATCH)))
361
362 (rule CPP
363 (gate build_dev_cc)
364 (dep CPP_OBJ CCPOOL_OBJ UTIL_OBJ LIBUTIL LIBUTF)
365 (out "cmd/dev/cc/cpp")
366 (exec $(CC) -static -o $(OUT) $(IN) $(LDFLAGS)))
367
368 (rule CCDRV_OBJ
369 (glob "cmd/dev/cc/driver.c")
370 (gate build_dev_cc)
371 (dep $(MATCH))
372 (out "$(STEM).o")
373 (exec $(CC) $(CPPFLAGS) -Icmd/dev/cc $(CFLAGS) -c -o $(OUT) $(MATCH)))
374
375 (rule CCDRV
376 (gate build_dev_cc)
377 (dep CCDRV_OBJ UTIL_OBJ LIBUTIL LIBUTF)
378 (out "cmd/dev/cc/cc")
379 (exec $(CC) -static -o $(OUT) $(IN) $(LDFLAGS)))
380
381 ; like BOX_OBJ: rename main and hide other globals so ninqu can link
382 ; into aruu-box. it is still not reentrant, so it stays out of
383 ; NOFORK_LIST
384 ;
385 (rule NINQU_BOX_OBJ
386 (glob "cmd/dev/ninqu/*.c")
387 (gate build_dev_ninqu)
388 (dep $(MATCH))
389 (after LIBUTIL LIBUTF LIBREDLINE NOFORK_LIST_H FEATURES_H GETCONF_H)
390 (out ".box/cmd/dev/$(BASESTEM).o")
391 (description "ninqu as a box builtin, main renamed for the box dispatch table")
392 (shell "$(CC) $(CPPFLAGS) $(CFLAGS) -c -o $(OUT) $(MATCH) && sym=`echo $(BASESTEM) | tr '.-' '__'`_main && $(OBJCOPY) --redefine-sym main=$sym $(OUT) && $(OBJCOPY) --keep-global-symbol=$sym $(OUT)")
393 (group box))
394
395 (group dev lib DEVCONF AR AS LD CC1 CPP CCDRV)
396
397 ; man pages: build mdoc and text pages from ?man-marked sources
398 ;
399 (rule MKMAN
400 (dir "scripts/mkman")
401 (dep "glob:scripts/mkman/*.go")
402 (out "scripts/mkman/mkman")
403 (exec go build -o mkman .))
404
405 (rule MAN_MDOC
406 (glob "cmd/**/*.c")
407 (mark "?man")
408 (dep (after MKMAN))
409 (out "man/man$(SEC_OF:$(DIR))/$(BASESTEM).$(SEC_OF:$(DIR))")
410 (exec scripts/mkman/mkman -fmt mdoc -config scripts/mk/config.kv $(MATCH))
411 (redirect))
412
413 (rule MAN_TXT
414 (glob "cmd/**/*.c")
415 (mark "?man")
416 (dep (after MKMAN))
417 (out "man/man$(SEC_OF:$(DIR))/$(BASESTEM).$(SEC_OF:$(DIR)).txt")
418 (exec scripts/mkman/mkman -fmt txt -config scripts/mk/config.kv $(MATCH))
419 (redirect))
420
421 (map SEC_OF
422 (cmd/posix 1)
423 (cmd/linux 8)
424 (cmd/net 8)
425 (cmd/xsi 1)
426 (cmd/pseudo 1)
427 (cmd/extra 1)
428 (cmd/dev 1))
429
430 (group man MAN_MDOC MAN_TXT)
431
432 (rule CLEAN
433 (phony)
434 (shell "
435 printf ' CLEAN object files\n'
436 find shared cmd -name '*.o' -exec rm -f {} +
437
438 printf ' CLEAN static libraries\n'
439 find shared -name '*.a' -exec rm -f {} +
440
441 printf ' CLEAN compiled binaries\n'
442 find cmd -type f ! -name '*.*' -perm -100 -exec rm -f {} +
443
444 sh scripts/genconfig.sh clean
445 rm -f scripts/mk/config.mk scripts/mk/config.kv scripts/mk/rules.mk shared/libutil/nofork_list.h
446
447 printf ' CLEAN build tools\n'
448 rm -f scripts/mkman/mkman
449
450 printf ' CLEAN dev artifacts\n'
451 rm -f cmd/dev/cc/cc1 cmd/dev/cc/cpp cmd/dev/as/as cmd/dev/ld/ld cmd/dev/ar/ar
452 rm -f shared/libaruuelf.so
453 rm -f cmd/dev/config.h cmd/dev/cc/config.h cmd/dev/version.h
454
455 printf ' CLEAN misc\n'
456 rm -rf man/man1 man/man8
457 rm -rf aruu-box .box
458 rm -rf .ninja_log .ninja_deps
459
460 printf ' CLEAN done\n'
461 "))
462
463 (group clean CLEAN)
464
465 ; install every built executable and generated man page, plus
466 ; shared/libutil itself as a real linkable library: other MICE
467 ; components (ports/pkgtools, nac) should link against this, not carry
468 ; their own copy of ealloc/eprintf/wexec/etc alongside it
469 (rule INSTALL
470 (phony)
471 (after ALL_BINS LIBUTIL MAN_MDOC MAN_TXT)
472 (shell "
473 d=\"${DESTDIR:-}$(PREFIX)\"
474 m=\"${DESTDIR:-}$(MANPREFIX)\"
475 mkdir -p \"$d/bin\" \"$m/man1\" \"$m/man8\" \"$d/lib\" \"$d/include/aruu\"
476
477 find cmd -type f ! -name '*.*' -perm -100 | while read -r bin; do
478 name=${bin##*/}
479 printf ' INSTALL %s/bin/%s\n' '$(PREFIX)' \"$name\"
480 cp \"$bin\" \"$d/bin/$name\"
481 chmod 755 \"$d/bin/$name\"
482 done
483
484 find man/man1 man/man8 -type f -name '*.[18]' 2>/dev/null | while read -r f; do
485 sec=${f%/*}; sec=${sec##*/}
486 name=${f##*/}
487 cp \"$f\" \"$m/$sec/$name\"
488 done
489
490 printf ' INSTALL %s/lib/libaruu.a\n' '$(PREFIX)'
491 cp shared/libutil/libutil.a \"$d/lib/libaruu.a\"
492 chmod 644 \"$d/lib/libaruu.a\"
493 for h in shared/util.h shared/wexec.h shared/arg.h shared/compat.h; do
494 printf ' INSTALL %s/include/aruu/%s\n' '$(PREFIX)' \"${h##*/}\"
495 cp \"$h\" \"$d/include/aruu/${h##*/}\"
496 chmod 644 \"$d/include/aruu/${h##*/}\"
497 done
498 "))
499
500(group install INSTALL)
501
502; same body as INSTALL, minus the dev (compiler toolchain) category:
503; what a MICE port needs to put a shell and coreutils on a rootfs,
504; not a hard dependency on the separate, not-yet-portable dev build
505(rule INSTALL_BASE
506 (phony)
507 (after POSIX_BIN LINUX_BIN NET_BIN XSI_BIN PSEUDO_BIN EXTRA_BIN
508 POSIX_BC POSIX_AWK POSIX_SH POSIX_MAKE EXTRA_YAP
509 LIBUTIL MAN_MDOC MAN_TXT)
510 (shell "
511 d=\"${DESTDIR:-}$(PREFIX)\"
512 m=\"${DESTDIR:-}$(MANPREFIX)\"
513 mkdir -p \"$d/bin\" \"$m/man1\" \"$m/man8\" \"$d/lib\" \"$d/include/aruu\"
514
515 find cmd -type f ! -name '*.*' -perm -100 ! -path 'cmd/dev/*' | while read -r bin; do
516 name=${bin##*/}
517 printf ' INSTALL %s/bin/%s\n' '$(PREFIX)' \"$name\"
518 cp \"$bin\" \"$d/bin/$name\"
519 chmod 755 \"$d/bin/$name\"
520 done
521
522 find man/man1 man/man8 -type f -name '*.[18]' 2>/dev/null | while read -r f; do
523 sec=${f%/*}; sec=${sec##*/}
524 name=${f##*/}
525 cp \"$f\" \"$m/$sec/$name\"
526 done
527
528 printf ' INSTALL %s/lib/libaruu.a\n' '$(PREFIX)'
529 cp shared/libutil/libutil.a \"$d/lib/libaruu.a\"
530 chmod 644 \"$d/lib/libaruu.a\"
531 for h in shared/util.h shared/wexec.h shared/arg.h shared/compat.h; do
532 printf ' INSTALL %s/include/aruu/%s\n' '$(PREFIX)' \"${h##*/}\"
533 cp \"$h\" \"$d/include/aruu/${h##*/}\"
534 chmod 644 \"$d/include/aruu/${h##*/}\"
535 done
536 "))
537
538(group install-base INSTALL_BASE)
539
540; remove exactly what install would have copied
541(rule REMOVE
542 (phony)
543 (shell "
544 find cmd -type f ! -name '*.*' -perm -100 | while read -r bin; do
545 name=${bin##*/}
546 printf ' REMOVE %s/bin/%s\n' '$(PREFIX)' \"$name\"
547 rm -f \"$(PREFIX)/bin/$name\"
548 done
549
550 find man/man1 man/man8 -type f -name '*.[18]' 2>/dev/null | while read -r f; do
551 sec=${f%/*}; sec=${sec##*/}
552 name=${f##*/}
553 printf ' REMOVE %s/%s/%s\n' '$(MANPREFIX)' \"$sec\" \"$name\"
554 rm -f \"$(MANPREFIX)/$sec/$name\"
555 done
556
557 printf ' REMOVE %s/lib/libaruu.a\n' '$(PREFIX)'
558 rm -f \"$(PREFIX)/lib/libaruu.a\"
559 for h in util.h wexec.h arg.h compat.h; do
560 printf ' REMOVE %s/include/aruu/%s\n' '$(PREFIX)' \"$h\"
561 rm -f \"$(PREFIX)/include/aruu/$h\"
562 done
563 rmdir \"$(PREFIX)/include/aruu\" 2>/dev/null || :
564 "))
565
566(group remove REMOVE)
567(group uninstall REMOVE)
568
569(rule FMT
570 (phony)
571 (shell "
572 printf ' FMT cmd and shared (skipping dir tools)\n'
573 find cmd shared -type f \( -name '*.c' -o -name '*.h' \) \
574 ! -path 'cmd/posix/awk/*' \
575 ! -path 'cmd/posix/sh/*' \
576 ! -path 'cmd/posix/make/*' \
577 ! -path 'cmd/extra/yap/*' \
578 ! -path 'cmd/posix/bc.c' \
579 -print | xargs -r clang-format -i
580 "))
581
582 (rule FMT_ALL
583 (phony)
584 (shell "
585 printf ' FMT cmd and shared (including dir tools)\n'
586 find cmd shared -type f \( -name '*.c' -o -name '*.h' \) -print \
587 | xargs -r clang-format -i
588 "))
589
590 (group fmt FMT)
591 (group fmt-all FMT_ALL)
592
593 ; box: one executable containing every enabled tool, dispatched through
594 ; a table. a single-file tool just gets its main renamed by BOX_OBJ
595 ; multi-file tools (POSIX_BC, POSIX_AWK, POSIX_SH, POSIX_MAKE, EXTRA_YAP)
596 ; go through a partial link (ld -r) first, merging their objects into
597 ; one before main gets renamed and helper symbols hidden. replaces
598 ; scripts/mkbox
599 ;
600 ; object files live under .box/, mirroring the cmd/ layout
601 ;
602 ; ninqu determines which tools enter the box using the gate on BOX_OBJ
603 ; BOX_DISPATCH reads the object paths passed on argv rather than consulting
604 ; build.cfg or config.set directly
605 ;
606
607 ; CATEGORY_OF maps a directory path to its category name, matching the toggles
608 ; in build.cfg. since BOX_OBJ globs multiple directories, its gate evaluates the
609 ; category dynamically based on the match directory
610 ;
611 ; gates evaluate $(IDENT) instead of $(BASESTEM) because toggle names must be
612 ; valid shell variables. genconfig.sh replaces hyphens and periods with
613 ; underscores, and $(IDENT) applies the same normalization so they match
614 ;
615 (map CATEGORY_OF
616 (cmd/posix posix)
617 (cmd/linux linux)
618 (cmd/net net)
619 (cmd/pseudo pseudo)
620 (cmd/xsi xsi)
621 (cmd/extra extra))
622
623 ; tool basestems match their c symbols using a shell transform (tr '.-' '__'
624 ; and appending _main) in both the objcopy step and in genbox.sh. a static map
625 ; is unnecessary because no current tools require custom overrides, and
626 ; genbox.sh only receives paths via argv
627 ;
628
629 ; the match directory picks the gate and output path, so one rule covers
630 ; all six categories. bc.c inside cmd/posix is excluded automatically by
631 ; the literal-glob override mechanism
632 ;
633 (rule BOX_OBJ
634 (glob "cmd/posix/*.c" "cmd/linux/*.c" "cmd/net/*.c" "cmd/pseudo/*.c"
635 "cmd/xsi/*.c" "cmd/extra/*.c")
636 (gate build_$(CATEGORY_OF:$(DIR))_$(IDENT))
637 (dep $(MATCH))
638 (after LIBUTIL LIBUTF LIBREDLINE NOFORK_LIST_H FEATURES_H GETCONF_H)
639 (out ".box/$(DIR)/$(BASESTEM).o")
640 (description "one object per enabled tool, main renamed for the box dispatch table")
641 (shell "$(CC) $(CPPFLAGS) $(CFLAGS) -c -o $(OUT) $(MATCH) && sym=`echo $(BASESTEM) | tr '.-' '__'`_main && $(OBJCOPY) --redefine-sym main=$sym $(OUT) && $(OBJCOPY) --keep-global-symbol=$sym $(OUT)")
642 (group box))
643
644 ; POSIX_BC, POSIX_AWK, POSIX_SH, POSIX_MAKE, and EXTRA_YAP cant go through
645 ; the single-file objcopy step, their global helper symbols would collide
646 ; once linked into one binary. a partial link (ld -r) resolves those
647 ; internal references first, then main gets renamed and the rest hidden
648 ;
649 ; combined objects use the layout .box/cmd/<category>/<tool>.o so genbox.sh
650 ; can parse them without structural modifications
651 ;
652 (rule POSIX_BC_BOX_OBJ
653 (glob "cmd/posix/bc.c")
654 (gate build_posix_bc)
655 (dep $(MATCH))
656 (after POSIX_BC_C)
657 (out ".box/parts/$(STEM).o")
658 (exec $(CC) $(CPPFLAGS) $(CFLAGS) -c -o $(OUT) $(MATCH)))
659
660 (rule POSIX_BC_BOX
661 (gate build_posix_bc)
662 (dep POSIX_BC_BOX_OBJ)
663 (out ".box/cmd/posix/bc.o")
664 (description "bc's objects combined into one relocatable object, main renamed for the box dispatch table")
665 (shell "$(LD) -r -o $(OUT) $(IN) && $(OBJCOPY) --redefine-sym main=bc_main $(OUT) && $(OBJCOPY) --keep-global-symbol=bc_main $(OUT)")
666 (group box))
667
668 (rule POSIX_AWK_BOX_OBJ
669 (glob "cmd/posix/awk/*.c")
670 (gate build_posix_awk)
671 (skip "maketab.c")
672 (dep $(MATCH))
673 (after POSIX_AWK_C)
674 (out ".box/parts/$(STEM).o")
675 (exec $(CC) $(CPPFLAGS) -Icmd/posix/awk $(CFLAGS) -c -o $(OUT) $(MATCH)))
676
677 (rule POSIX_AWK_BOX
678 (gate build_posix_awk)
679 (dep POSIX_AWK_BOX_OBJ)
680 (out ".box/cmd/posix/awk.o")
681 (description "awk's objects combined into one relocatable object, main renamed for the box dispatch table")
682 (shell "$(LD) -r -o $(OUT) $(IN) && $(OBJCOPY) --redefine-sym main=awk_main $(OUT) && $(OBJCOPY) --keep-global-symbol=awk_main $(OUT)")
683 (group box))
684
685 (rule POSIX_SH_BOX_OBJ
686 (glob "cmd/posix/sh/*.c")
687 (gate build_posix_sh)
688 (skip "mknodes.c" "mksyntax.c")
689 (dep $(MATCH))
690 (after POSIX_SH_C)
691 (out ".box/parts/$(STEM).o")
692 (exec $(CC) $(CPPFLAGS) -DSHELL -Icmd/posix/sh $(CFLAGS) -c -o $(OUT) $(MATCH)))
693
694 (rule POSIX_SH_BOX
695 (gate build_posix_sh)
696 (dep POSIX_SH_BOX_OBJ)
697 (out ".box/cmd/posix/sh.o")
698 (description "sh's objects combined into one relocatable object, main renamed for the box dispatch table")
699 (shell "$(LD) -r -o $(OUT) $(IN) && $(OBJCOPY) --redefine-sym main=sh_main $(OUT) && $(OBJCOPY) --keep-global-symbol=sh_main $(OUT)")
700 (group box))
701
702 (rule POSIX_MAKE_BOX_OBJ
703 (glob "cmd/posix/make/*.c")
704 (gate build_posix_make)
705 (dep $(MATCH))
706 (out ".box/parts/$(STEM).o")
707 (exec $(CC) $(CPPFLAGS) $(CFLAGS) -c -o $(OUT) $(MATCH)))
708
709 (rule POSIX_MAKE_BOX
710 (gate build_posix_make)
711 (dep POSIX_MAKE_BOX_OBJ)
712 (out ".box/cmd/posix/make.o")
713 (description "make's objects combined into one relocatable object, main renamed for the box dispatch table")
714 (shell "$(LD) -r -o $(OUT) $(IN) && $(OBJCOPY) --redefine-sym main=make_main $(OUT) && $(OBJCOPY) --keep-global-symbol=make_main $(OUT)")
715 (group box))
716
717 (rule EXTRA_YAP_BOX_OBJ
718 (glob "cmd/extra/yap/*.c")
719 (gate build_extra_yap)
720 (dep $(MATCH))
721 (out ".box/parts/$(STEM).o")
722 (exec $(CC) $(CPPFLAGS) $(CFLAGS) -c -o $(OUT) $(MATCH)))
723
724 (rule EXTRA_YAP_BOX
725 (gate build_extra_yap)
726 (dep EXTRA_YAP_BOX_OBJ)
727 (out ".box/cmd/extra/yap.o")
728 (description "yap's objects combined into one relocatable object, main renamed for the box dispatch table")
729 (shell "$(LD) -r -o $(OUT) $(IN) && $(OBJCOPY) --redefine-sym main=yap_main $(OUT) && $(OBJCOPY) --keep-global-symbol=yap_main $(OUT)")
730 (group box))
731
732 ; genbox.sh relies on arguments passed by ninqu, where each argument matches
733 ; an output from BOX_OBJ or a custom box rule. the script derives categories
734 ; and tool names directly from these paths and outputs the dispatch code
735 ;
736 (rule BOX_DISPATCH
737 (dep BOX_OBJ POSIX_BC_BOX POSIX_AWK_BOX POSIX_SH_BOX POSIX_MAKE_BOX EXTRA_YAP_BOX NINQU_BOX_OBJ)
738 (out ".box/aruu-box.c")
739 (description "dispatch table and main() for aruu-box, generated from the enabled tool list")
740 (exec scripts/genbox.sh $(IN))
741 (redirect)
742 (group box))
743
744 ; libm is linked unconditionally because bc requires it, and unused library
745 ; references are safe. modern toolchains omit unreferenced archive components
746 ; yap requires terminfo, which is an optional system dependency. linking it
747 ; unconditionally breaks builds on systems without ncurses-dev when yap is
748 ; disabled. genconfig.sh exports BOX_EXTRA_LIBS as "-ltinfo" or an empty string
749 ; based on whether yap is enabled
750 ;
751 (rule BOX
752 (dep BOX_DISPATCH BOX_OBJ POSIX_BC_BOX POSIX_AWK_BOX POSIX_SH_BOX POSIX_MAKE_BOX EXTRA_YAP_BOX NINQU_BOX_OBJ LIBUTIL LIBUTF LIBREDLINE)
753 (out "aruu-box")
754 (description "single multi-call binary, one dispatch table for every enabled tool")
755 (shell "$(CC) $(CPPFLAGS) $(CFLAGS) -o $(OUT) $(IN) $(LDFLAGS) $(LDLIBS) $(BOX_EXTRA_LIBS)")
756 (group box))
757
758 (group box BOX)
759
760 ; -------------------------------------------------------------------
761 ; top level. (group all) contains every build target except clean
762 ; and box. box is separate because it produces a different binary
763 ; with different .o files, and mixing it with standalone builds
764 ; would cause confusion. clean is never in all because it removes
765 ; what all builds
766 ; -------------------------------------------------------------------
767
768 (rule ALL_BINS
769 (phony)
770 (after LIBUTIL LIBUTF LIBREDLINE
771 POSIX_BIN LINUX_BIN NET_BIN XSI_BIN
772 PSEUDO_BIN EXTRA_BIN
773 POSIX_BC POSIX_AWK POSIX_SH POSIX_MAKE EXTRA_YAP
774 AR AS LD CC1 CPP CCDRV)
775 (exec true))
776
777 (group all ALL_BINS)
778
779 (group default all)
780
781 ; meta-targets: apply an override, then build a normal target under
782 ; it. invoke as `ninqu META.TARGET` (`ninqu debug.posix`) or bare
783 ; `ninqu META` to apply the override and build (group default)
784 ;
785 (meta debug
786 (set CFLAGS "$(CFLAGS) -g -O0"))
787
788 (meta release
789 (set CFLAGS "$(CFLAGS) -O2 -DNDEBUG"))