commit 4a88c5b

shrub  ·  2026-04-24 23:01:27 +0000 UTC
parent bd8ad09
error better and makefile portability
4 files changed,  +103, -67
M README
+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