commit 4a88c5b
shrub
·
2026-04-24 23:01:27 +0000 UTC
parent bd8ad09
error better and makefile portability
4 files changed,
+103,
-67
M
Makefile
+6,
-0
1@@ -1,3 +1,4 @@
2+.POSIX:
3 PREFIX = /usr
4 DESTDIR =
5 BINDIR = $(DESTDIR)$(PREFIX)/bin
6@@ -37,6 +38,11 @@ LDFLAGS = -static
7
8 all: $(BIN)
9
10+.SUFFIXES: .c .o
11+
12+.c.o:
13+ $(CC) $(CPPFLAGS) $(CFLAGS) -c -o $@ $<
14+
15 $(BIN): $(OBJS)
16 $(CC) $(LDFLAGS) -o $(BIN) $(OBJS) $(LDLIBS)
17
M
README
+1,
-1
1@@ -17,6 +17,6 @@ if you want to help out, there's lots to do. feel free to make a
2 contibution. some high-priority tasks are listed in the TODO file.
3
4 it is implemented in C99. the perl in this repo is just the gnu make
5-test suite (of which 820/3865 tests pass, at the time of writing)
6+test suite (of which 880/3865 tests pass, at the time of writing)
7
8 this is public domain software
+61,
-61
1@@ -242,11 +242,11 @@ main(int argc, char **argv)
2 } else if (strcmp(argv[i], "-g") == 0) {
3 dump_graph = 1;
4 } else if (strcmp(argv[i], "-G") == 0) {
5- if (i + 1 >= argc) {
6- fprintf(stderr, "specify a generator\n\n");
7- usage(stderr, argv[0]);
8- return 1;
9- }
10+ if (i + 1 >= argc) {
11+ fprintf(stderr, "specify a generator\n\n");
12+ usage(stderr, argv[0]);
13+ return 2;
14+ }
15 ++i;
16 if (strcmp(argv[i], "ninja") == 0) {
17 gen = GEN_NINJA;
18@@ -254,50 +254,50 @@ main(int argc, char **argv)
19 gen = GEN_DOT;
20 } else if (strcmp(argv[i], "compcmd") == 0) {
21 gen = GEN_COMPCMD;
22- } else {
23- fprintf(stderr, "unknown generator: %s\n\n", argv[i]);
24- usage(stderr, argv[0]);
25- return 1;
26- }
27+ } else {
28+ fprintf(stderr, "unknown generator: %s\n\n", argv[i]);
29+ usage(stderr, argv[0]);
30+ return 2;
31+ }
32 } else if (strcmp(argv[i], "-h") == 0 || strcmp(argv[i], "--help") == 0) {
33 usage(stdout, argv[0]);
34 return 0;
35- } else if (strcmp(argv[i], "-C") == 0) {
36- if (i + 1 >= argc) {
37- fprintf(stderr, "specify a directory\n\n");
38- usage(stderr, argv[0]);
39- return 1;
40- }
41+ } else if (strcmp(argv[i], "-C") == 0) {
42+ if (i + 1 >= argc) {
43+ fprintf(stderr, "specify a directory\n\n");
44+ usage(stderr, argv[0]);
45+ return 2;
46+ }
47 ++i;
48
49- if (chdir(argv[i]) != 0) {
50- fprintf(stderr, "failed to chdir to %s", argv[i]);
51- return 1;
52- }
53- } else if (strcmp(argv[i], "-f") == 0) {
54- if (i + 1 >= argc) {
55- fprintf(stderr, "specify a file\n\n");
56- usage(stderr, argv[0]);
57- return 1;
58- }
59+ if (chdir(argv[i]) != 0) {
60+ fprintf(stderr, "failed to chdir to %s", argv[i]);
61+ return 2;
62+ }
63+ } else if (strcmp(argv[i], "-f") == 0) {
64+ if (i + 1 >= argc) {
65+ fprintf(stderr, "specify a file\n\n");
66+ usage(stderr, argv[0]);
67+ return 2;
68+ }
69 ++i;
70 path = argv[i];
71 } else if (strcmp(argv[i], "-e") == 0) {
72 env_override = 1;
73- } else if (isvarassign(argv[i])) {
74- assigns = realloc(assigns, (nassigns + 1) * sizeof(assigns[0]));
75- if (!assigns) {
76- fprintf(stderr, "out of memory\n");
77- return 1;
78+ } else if (isvarassign(argv[i])) {
79+ assigns = realloc(assigns, (nassigns + 1) * sizeof(assigns[0]));
80+ if (!assigns) {
81+ fprintf(stderr, "out of memory\n");
82+ return 2;
83+ }
84+ assigns[nassigns++] = argv[i];
85+ } else if (argv[i][0] == '-') {
86+ usage(stderr, argv[0]);
87+ return 2;
88+ } else {
89+ usage(stderr, argv[0]);
90+ return 2;
91 }
92- assigns[nassigns++] = argv[i];
93- } else if (argv[i][0] == '-') {
94- usage(stderr, argv[0]);
95- return 1;
96- } else {
97- usage(stderr, argv[0]);
98- return 1;
99- }
100 }
101 for (i = 0; i < (int)nassigns; i++)
102 addstr(&sg.assigns, assigns[i]);
103@@ -305,15 +305,15 @@ main(int argc, char **argv)
104 char *mkpath;
105
106 mkpath = 0;
107- if (loadmakefile(path, &mkpath, &src) < 0) {
108- if (path)
109- fprintf(stderr, "could not read %s\n", path);
110- else
111- fprintf(stderr, "could not find a makefile\n");
112- free(assigns);
113- freesubgraph(&sg);
114- return 1;
115- }
116+ if (loadmakefile(path, &mkpath, &src) < 0) {
117+ if (path)
118+ fprintf(stderr, "could not read %s\n", path);
119+ else
120+ fprintf(stderr, "could not find a makefile\n");
121+ free(assigns);
122+ freesubgraph(&sg);
123+ return 2;
124+ }
125 path = mkpath;
126 pathbuf = mkpath;
127 src = appendassigns(src, &sg.assigns);
128@@ -343,15 +343,15 @@ main(int argc, char **argv)
129 }
130 }
131 }
132- if (eval(&ast, &rs) < 0) {
133- fprintf(stderr, "eval error in %s\n", path);
134- free(assigns);
135- freeast(&ast);
136- free(pathbuf);
137- free(src);
138- freesubgraph(&sg);
139- return 1;
140- }
141+ if (eval(&ast, &rs) < 0) {
142+ fprintf(stderr, "eval error in %s\n", path);
143+ free(assigns);
144+ freeast(&ast);
145+ free(pathbuf);
146+ free(src);
147+ freesubgraph(&sg);
148+ return 2;
149+ }
150 rs.envoverride = env_override;
151 dumpruleset(&rs);
152 freeruleset(&rs);
153@@ -380,7 +380,7 @@ main(int argc, char **argv)
154 fprintf(stderr, "expand error in %s\n", path ? path : "(default)");
155 free(pathbuf);
156 freesubgraph(&sg);
157- return 1;
158+ return 2;
159 }
160 if (dump_graph)
161 dumpgraph(&sg.graph);
162@@ -389,7 +389,7 @@ main(int argc, char **argv)
163 fprintf(stderr, "graphviz generation error\n");
164 free(pathbuf);
165 freesubgraph(&sg);
166- return 1;
167+ return 2;
168 }
169 }
170 if (gen == GEN_COMPCMD) {
171@@ -397,14 +397,14 @@ main(int argc, char **argv)
172 fprintf(stderr, "compile_commands generation error\n");
173 free(pathbuf);
174 freesubgraph(&sg);
175- return 1;
176+ return 2;
177 }
178 }
179 if (gen == GEN_NINJA && genninja(&sg.graph, "build.ninja") < 0) {
180 fprintf(stderr, "ninja generation error\n");
181 free(pathbuf);
182 freesubgraph(&sg);
183- return 1;
184+ return 2;
185 }
186 free(pathbuf);
187 freesubgraph(&sg);
+35,
-5
1@@ -97,6 +97,29 @@ nowork_only() {
2 [ "$1" = "ninja: no work to do." ]
3 }
4
5+rewrite_ninja_error() {
6+ line=$1
7+ case $line in
8+ "ninja: error: '"*", needed by '"*", missing and no known rule to make it")
9+ rest=${line#"ninja: error: '"}
10+ target=${rest%%"', needed by '"*}
11+ rest=${rest#*"', needed by '"}
12+ needer=${rest%%"', missing and no known rule to make it"}
13+ printf "%s: *** No rule to make target '%s', needed by '%s'. Stop.\n" \
14+ "${0##*/}" "$target" "$needer"
15+ return 0
16+ ;;
17+ "ninja: error: unknown target '"*"'")
18+ target=${line#"ninja: error: unknown target '"}
19+ target=${target%"'"}
20+ printf "%s: *** No rule to make target '%s'. Stop.\n" \
21+ "${0##*/}" "$target"
22+ return 0
23+ ;;
24+ esac
25+ return 1
26+}
27+
28 while [ "$#" -gt 0 ]; do
29 case "$1" in
30 -v|--version)
31@@ -184,9 +207,14 @@ if [ -z "$makefile" ]; then
32 fi
33 fi
34
35-if probemk; then
36+probemk
37+probe_rc=$?
38+if [ "$probe_rc" -eq 0 ]; then
39 exit 0
40 fi
41+if [ "$probe_rc" -eq 2 ]; then
42+ exit 2
43+fi
44
45 if [ "$makefile_set" -eq 1 ]; then
46 set -- "$shin_bin" -f "$makefile"
47@@ -216,7 +244,7 @@ if "$@"; then
48 :
49 else
50 rc=$?
51- exit "$rc"
52+ exit 2
53 fi
54
55 set -- "$ninja_bin" --quiet -f build.ninja
56@@ -251,8 +279,10 @@ if [ "$dryrun" -eq 0 ]; then
57 probe_out=$(eval "$probe_cmd -n" 2>&1)
58 probe_status=$?
59 if [ "$probe_status" -ne 0 ]; then
60- printf '%s' "$probe_out"
61- exit "$probe_status"
62+ if ! rewrite_ninja_error "$probe_out"; then
63+ printf '%s' "$probe_out"
64+ fi
65+ exit 2
66 fi
67 if nowork_only "$probe_out"; then
68 target=$(uptodate_target)
69@@ -268,7 +298,7 @@ if [ "$dryrun" -eq 0 ]; then
70 printf '%s\n' "$run_out"
71 fi
72 if [ "$run_status" -ne 0 ]; then
73- exit "$run_status"
74+ exit 2
75 fi
76 target=$(uptodate_target)
77 if [ -n "$target" ]; then