commit 08bea15
shrub
·
2026-06-30 16:14:11 +0000 UTC
parent 1ec538a
add deps script
1 files changed,
+97,
-0
A
deps
A
deps
+97,
-0
1@@ -0,0 +1,97 @@
2+#!/bin/sh
3+# emit makefile dependencies for a list of C sources using the compiler's .d output. having a bunch of
4+# autogenerated .d files and -include's is flaky and ugly, and might not work on all make
5+# implementations. this way you can generate the deps once and ship the makefile.
6+# it takes a list of files from stdin and prints to stdout. you might also want to append
7+# you CFLAGS/CPPFLAGS if that will change the deps.
8+#
9+# example:
10+# find . -type f -name '*.c' | CPPFLAGS='-Iinclude' deps >> Makefile
11+#
12+
13+set -eu
14+
15+cc=${CC:-cc}
16+cppflags=${CPPFLAGS:-}
17+cflags=${CFLAGS:-}
18+tmpbase=${TMPDIR:-/tmp}
19+
20+cleanup() {
21+ rm -rf "$tmpdir"
22+}
23+
24+usage() {
25+ printf 'usage: %s [file.c ...]\n' "${0##*/}" >&2
26+ printf ' %s < file-list\n' "${0##*/}" >&2
27+ exit 2
28+}
29+
30+list() {
31+ if [ "$#" -gt 0 ]; then
32+ for src do
33+ case $src in
34+ *.c) printf '%s\n' "$src" ;;
35+ *) printf '%s: not a .c file: %s\n' "${0##*/}" "$src" >&2; exit 2 ;;
36+ esac
37+ done
38+ return
39+ fi
40+
41+ while IFS= read -r src; do
42+ [ -n "$src" ] || continue
43+ case $src in
44+ *.c) printf '%s\n' "$src" ;;
45+ *) printf '%s: not a .c file: %s\n' "${0##*/}" "$src" >&2; exit 2 ;;
46+ esac
47+ done
48+}
49+
50+if [ "${1:-}" = "-h" ] || [ "${1:-}" = "--help" ]; then
51+ usage
52+fi
53+
54+tmpdir=$(mktemp -d "$tmpbase/deps.XXXXXX")
55+trap cleanup EXIT HUP INT TERM
56+
57+count=0
58+srcs=$tmpdir/sources
59+list "$@" > "$srcs"
60+
61+if [ ! -s "$srcs" ]; then
62+ printf '%s: no .c files provided\n' "${0##*/}" >&2
63+ exit 1
64+fi
65+
66+printf '\n'
67+printf '#AUTOGENERATED\n'
68+
69+while IFS= read -r src; do
70+ dep=$tmpdir/$count.d
71+ obj=${src%.c}.o
72+ "$cc" $cppflags $cflags -MMD -MF "$dep" -MT "$obj" -E -o /dev/null "$src"
73+ #flatten the block with one target: dep line per prereq
74+ awk '
75+ BEGIN {
76+ rule = ""
77+ }
78+ {
79+ line = $0
80+ sub(/\\$/, "", line)
81+ rule = rule line " "
82+ if ($0 !~ /\\$/) {
83+ sub(/^[[:space:]]*/, "", rule)
84+ split(rule, parts, ":")
85+ target = parts[1]
86+ deps = substr(rule, length(target) + 2)
87+ n = split(deps, items, /[[:space:]]+/)
88+ for (i = 1; i <= n; ++i) {
89+ if (items[i] == "")
90+ continue
91+ print target ": " items[i]
92+ }
93+ rule = ""
94+ }
95+ }
96+ ' "$dep"
97+ count=$((count + 1))
98+done < "$srcs"