commit 23c6f88
shrub
·
2026-05-18 18:12:53 +0000 UTC
parent c74e668
move implcit rules and var seeding to a new file; make default vars more posix compliant
3 files changed,
+203,
-150
M
Makefile
+2,
-1
1@@ -13,7 +13,8 @@ SRCS = cli/main.c \
2 src/eval/dollar.c \
3 src/graph/graph.c \
4 src/graph/subgraph.c \
5- src/posix.c \
6+ src/sufrule.c \
7+ src/defaults.c \
8 src/targets.c \
9 src/gnu/pattern.c \
10 backends/ninja.c \
+201,
-0
1@@ -0,0 +1,201 @@
2+#include "posix.h"
3+
4+#include <unistd.h>
5+#include <stdio.h>
6+#include <stdlib.h>
7+#include <string.h>
8+
9+extern char **environ;
10+
11+struct DefaultVar {
12+ const char *name;
13+ const char *val;
14+};
15+
16+static void
17+seeddefaults(struct Env *env, const struct DefaultVar *vars)
18+{
19+ size_t i;
20+
21+ for (i = 0; vars[i].name; i++)
22+ envsetvar(env, vars[i].name, xstrdup(vars[i].val), 1, ORIGIN_DEFAULT, 0);
23+}
24+
25+/* rules shared by all dialects except the .c.o rule, which differs */
26+#define IMPRULES_COMMON \
27+ ".c:\n" \
28+ "\t$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $<\n" \
29+ ".sh:\n" \
30+ "\tcp $< $@\n" \
31+ "\tchmod a+x $@\n" \
32+ ".y.o:\n" \
33+ "\t$(YACC) $(YFLAGS) $<\n" \
34+ "\t$(CC) $(CPPFLAGS) $(CFLAGS) -c y.tab.c\n" \
35+ "\trm -f y.tab.c\n" \
36+ "\tmv y.tab.o $@\n" \
37+ ".l.o:\n" \
38+ "\t$(LEX) $(LFLAGS) $<\n" \
39+ "\t$(CC) $(CPPFLAGS) $(CFLAGS) -c lex.yy.c\n" \
40+ "\trm -f lex.yy.c\n" \
41+ "\tmv lex.yy.o $@\n" \
42+ ".y.c:\n" \
43+ "\t$(YACC) $(YFLAGS) $<\n" \
44+ "\tmv y.tab.c $@\n" \
45+ ".l.c:\n" \
46+ "\t$(LEX) $(LFLAGS) $<\n" \
47+ "\tmv lex.yy.c $@\n"
48+
49+/* posix 2008 includes fortran; posix 2024 dropped it */
50+#define IMPRULES_POSIX_2008 \
51+ ".SUFFIXES: .o .c .f .y .l .sh\n" \
52+ IMPRULES_COMMON \
53+ ".f:\n" \
54+ "\t$(FC) $(FFLAGS) $(LDFLAGS) -o $@ $<\n" \
55+ ".c.o:\n" \
56+ "\t$(CC) $(CFLAGS) -c $<\n" \
57+ ".f.o:\n" \
58+ "\t$(FC) $(FFLAGS) -c $<\n"
59+
60+#define IMPRULES_POSIX_2024 \
61+ ".SUFFIXES: .o .c .y .l .sh\n" \
62+ IMPRULES_COMMON \
63+ ".c.o:\n" \
64+ "\t$(CC) $(CFLAGS) -c $<\n"
65+
66+#define IMPRULES_GNU \
67+ ".SUFFIXES: .o .c .f .y .l .sh\n" \
68+ IMPRULES_COMMON \
69+ ".f:\n" \
70+ "\t$(FC) $(FFLAGS) $(LDFLAGS) -o $@ $<\n" \
71+ ".c.o:\n" \
72+ "\t$(CC) $(CPPFLAGS) $(CFLAGS) -c -o $@ $<\n" \
73+ ".f.o:\n" \
74+ "\t$(FC) $(FFLAGS) -c -o $@ $<\n"
75+
76+static int
77+loadimprules(struct SufRules *rules, const char *src)
78+{
79+ struct Ast ast;
80+ size_t i;
81+ int rc;
82+
83+ rc = parse("<built-in-rules>", src, &ast);
84+ if (rc < 0)
85+ return -1;
86+ for (i = 0; i < ast.n; i++) {
87+ struct Node *node = &ast.v[i];
88+
89+ if (node->kind != NODE_RULE)
90+ continue;
91+ if (issufrule(&node->data.rule)) {
92+ addsufs(&rules->active, &node->data.rule.prereqs);
93+ continue;
94+ }
95+ (void)collectsufrule(rules, &node->data.rule);
96+ }
97+ freeast(&ast);
98+ return 0;
99+}
100+
101+void
102+seedenv(struct Env *env, int isposix, int envoverride, enum ShinMode mode)
103+{
104+ char *cwd;
105+ size_t i;
106+ static const struct DefaultVar posix[] = {
107+ {"AR", "ar"},
108+ {"ARFLAGS", "-rv"},
109+ {"YACC", "yacc"},
110+ {"YFLAGS", ""},
111+ {"LEX", "lex"},
112+ {"LFLAGS", ""},
113+ {"LDFLAGS", ""},
114+ {"CFLAGS", "-O 1"},
115+ {0, 0},
116+ };
117+ static const struct DefaultVar posix2024[] = {
118+ {"CC", "c17"},
119+ {0, 0},
120+ };
121+ static const struct DefaultVar posix2008[] = {
122+ {"MAKE", "make"},
123+ {"CC", "c99"},
124+ {"FC", "fort77"},
125+ {"FFLAGS", "-O 1"},
126+ {0, 0},
127+ };
128+ static const struct DefaultVar gnu[] = {
129+ {"CC", "cc"},
130+ {"CFLAGS", ""},
131+ {"CXX", "c++"},
132+ {"CPP", "$(CC) -E"},
133+ {"FC", "fort77"},
134+ {"FFLAGS", ""},
135+ {"AR", "ar"},
136+ {"ARFLAGS", "-rv"},
137+ {"RANLIB", "ranlib"},
138+ {"AS", "as"},
139+ {"GET", "get"},
140+ {"GFLAGS", ""},
141+ {"LD", "ld"},
142+ {"LDFLAGS", ""},
143+ {"LEX", "lex"},
144+ {"LFLAGS", ""},
145+ {"SCCSFLAGS", ""},
146+ {"SCCSGETFLAGS", "-s"},
147+ {"YACC", "yacc"},
148+ {"YFLAGS", ""},
149+ {"SHELL", "/bin/sh"},
150+ {"MAKE", "make"},
151+ /* we lie about being the latest version of gnu make. i think it's
152+ * kinda selfish they made this be MAKE_VERSION instead of GMAKE_VERSION,
153+ * what if bsd make wanted to add a similar one? */
154+ {"MAKE_VERSION", "4.4.1"},
155+ {"RM", "rm -f"},
156+ {0, 0},
157+ };
158+
159+ if (mode == MODE_POSIX_2024) {
160+ seeddefaults(env, posix);
161+ seeddefaults(env, posix2024);
162+ } else if (mode == MODE_POSIX_2008 || isposix) {
163+ seeddefaults(env, posix);
164+ seeddefaults(env, posix2008);
165+ } else {
166+ seeddefaults(env, gnu);
167+ cwd = getcwddup();
168+ /*TODO: do this properly, this only expands at evaluation time,
169+ * unsure about behaviour under directory change condition or
170+ * in submakes. should work for most simple cases. */
171+ envsetvar(env, "CURDIR", cwd, 1, ORIGIN_FILE, 0);
172+ }
173+ for (i = 0; environ && environ[i]; i++) {
174+ const char *eq;
175+ char *name;
176+
177+ eq = strchr(environ[i], '=');
178+ if (!eq || eq == environ[i])
179+ continue;
180+ name = xstrndup(environ[i], (size_t)(eq - environ[i]));
181+ envsetvar(env, name, xstrdup(eq + 1), 1,
182+ envoverride ? ORIGIN_ENV_OVERRIDE : ORIGIN_ENV, 0);
183+ free(name);
184+ }
185+}
186+
187+void
188+imprules(struct SufRules *rules, int posix, enum ShinMode mode)
189+{
190+ const char *src;
191+
192+ if (mode == MODE_POSIX_2024)
193+ src = IMPRULES_POSIX_2024;
194+ else if (mode == MODE_POSIX_2008 || posix)
195+ src = IMPRULES_POSIX_2008;
196+ else
197+ src = IMPRULES_GNU;
198+ if (loadimprules(rules, src) < 0) {
199+ fprintf(stderr, "failed to load built-in implicit rules\n");
200+ exit(1);
201+ }
202+}
R src/posix.c =>
src/sufrule.c
+0,
-149
1@@ -215,155 +215,6 @@ expandauto(const char *s, const struct Target *t, const char *stem)
2 return out;
3 }
4
5-/* rules shared by all dialects except the .c.o rule, which differs */
6-#define IMPRULES_COMMON \
7- ".c:\n" \
8- "\t$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $<\n" \
9- ".sh:\n" \
10- "\tcp $< $@\n" \
11- "\tchmod a+x $@\n" \
12- ".y.o:\n" \
13- "\t$(YACC) $(YFLAGS) $<\n" \
14- "\t$(CC) $(CPPFLAGS) $(CFLAGS) -c y.tab.c\n" \
15- "\trm -f y.tab.c\n" \
16- "\tmv y.tab.o $@\n" \
17- ".l.o:\n" \
18- "\t$(LEX) $(LFLAGS) $<\n" \
19- "\t$(CC) $(CPPFLAGS) $(CFLAGS) -c lex.yy.c\n" \
20- "\trm -f lex.yy.c\n" \
21- "\tmv lex.yy.o $@\n" \
22- ".y.c:\n" \
23- "\t$(YACC) $(YFLAGS) $<\n" \
24- "\tmv y.tab.c $@\n" \
25- ".l.c:\n" \
26- "\t$(LEX) $(LFLAGS) $<\n" \
27- "\tmv lex.yy.c $@\n"
28-
29-/* posix 2008 includes fortran; posix 2024 dropped it */
30-#define IMPRULES_POSIX_2008 \
31- ".SUFFIXES: .o .c .f .y .l .sh\n" \
32- IMPRULES_COMMON \
33- ".f:\n" \
34- "\t$(FC) $(FFLAGS) $(LDFLAGS) -o $@ $<\n" \
35- ".c.o:\n" \
36- "\t$(CC) $(CFLAGS) -c $<\n" \
37- ".f.o:\n" \
38- "\t$(FC) $(FFLAGS) -c $<\n"
39-
40-#define IMPRULES_POSIX_2024 \
41- ".SUFFIXES: .o .c .y .l .sh\n" \
42- IMPRULES_COMMON \
43- ".c.o:\n" \
44- "\t$(CC) $(CFLAGS) -c $<\n"
45-
46-#define IMPRULES_GNU \
47- ".SUFFIXES: .o .c .f .y .l .sh\n" \
48- IMPRULES_COMMON \
49- ".f:\n" \
50- "\t$(FC) $(FFLAGS) $(LDFLAGS) -o $@ $<\n" \
51- ".c.o:\n" \
52- "\t$(CC) $(CPPFLAGS) $(CFLAGS) -c -o $@ $<\n" \
53- ".f.o:\n" \
54- "\t$(FC) $(FFLAGS) -c -o $@ $<\n"
55-
56-static int
57-loadimprules(struct SufRules *rules, const char *src)
58-{
59- struct Ast ast;
60- size_t i;
61- int rc;
62-
63- rc = parse("<built-in-rules>", src, &ast);
64- if (rc < 0)
65- return -1;
66- for (i = 0; i < ast.n; i++) {
67- struct Node *node = &ast.v[i];
68-
69- if (node->kind != NODE_RULE)
70- continue;
71- if (issufrule(&node->data.rule)) {
72- addsufs(&rules->active, &node->data.rule.prereqs);
73- continue;
74- }
75- (void)collectsufrule(rules, &node->data.rule);
76- }
77- freeast(&ast);
78- return 0;
79-}
80-
81-void
82-seedenv(struct Env *env, int posix, int envoverride, enum ShinMode mode)
83-{
84- char *cwd;
85- size_t i;
86-
87- envsetvar(env, "CC", xstrdup("cc"), 1, ORIGIN_DEFAULT, 0);
88- envsetvar(env, "CFLAGS", xstrdup(""), 1, ORIGIN_DEFAULT, 0);
89- envsetvar(env, "CXX", xstrdup("c++"), 1, ORIGIN_DEFAULT, 0);
90- envsetvar(env, "CPP", xstrdup("$(CC) -E"), 0, ORIGIN_DEFAULT, 0);
91- envsetvar(env, "FC", xstrdup("fort77"), 1, ORIGIN_DEFAULT, 0);
92- envsetvar(env, "FFLAGS", xstrdup(""), 1, ORIGIN_DEFAULT, 0);
93- envsetvar(env, "AR", xstrdup("ar"), 1, ORIGIN_DEFAULT, 0);
94- envsetvar(env, "ARFLAGS", xstrdup("-rv"), 1, ORIGIN_DEFAULT, 0);
95- envsetvar(env, "RANLIB", xstrdup("ranlib"), 1, ORIGIN_DEFAULT, 0);
96- envsetvar(env, "AS", xstrdup("as"), 1, ORIGIN_DEFAULT, 0);
97- envsetvar(env, "GET", xstrdup("get"), 1, ORIGIN_DEFAULT, 0);
98- envsetvar(env, "GFLAGS", xstrdup(""), 1, ORIGIN_DEFAULT, 0);
99- envsetvar(env, "LD", xstrdup("ld"), 1, ORIGIN_DEFAULT, 0);
100- envsetvar(env, "LDFLAGS", xstrdup(""), 1, ORIGIN_DEFAULT, 0);
101- envsetvar(env, "LEX", xstrdup("lex"), 1, ORIGIN_DEFAULT, 0);
102- envsetvar(env, "LFLAGS", xstrdup(""), 1, ORIGIN_DEFAULT, 0);
103- envsetvar(env, "SCCSFLAGS", xstrdup(""), 1, ORIGIN_DEFAULT, 0);
104- envsetvar(env, "SCCSGETFLAGS", xstrdup("-s"), 1, ORIGIN_DEFAULT, 0);
105- envsetvar(env, "YACC", xstrdup("yacc"), 1, ORIGIN_DEFAULT, 0);
106- envsetvar(env, "YFLAGS", xstrdup(""), 1, ORIGIN_DEFAULT, 0);
107- envsetvar(env, "SHELL", xstrdup("/bin/sh"), 1, ORIGIN_DEFAULT, 0);
108- envsetvar(env, "MAKE", xstrdup("make"), 1, ORIGIN_DEFAULT, 0);
109- envsetvar(env, "RM", xstrdup("rm -f"), 1, ORIGIN_DEFAULT, 0);
110- cwd = getcwddup();
111- /*TODO: do this properly, this only expands at evaluation time,
112- * unsure about behaviour under directory change condition or
113- * in submakes. should work for most simple cases. */
114- envsetvar(env, "CURDIR", cwd, 1, ORIGIN_FILE, 0);
115- if (posix || mode != MODE_GNU) {
116- const char *cc = "c99";
117-
118- if (mode == MODE_POSIX_2024)
119- cc = "c17";
120- envsetvar(env, "CC", xstrdup(cc), 1, ORIGIN_DEFAULT, 0);
121- envsetvar(env, "CFLAGS", xstrdup("-O1"), 1, ORIGIN_DEFAULT, 0);
122- envsetvar(env, "FFLAGS", xstrdup("-O1"), 1, ORIGIN_DEFAULT, 0);
123- }
124- for (i = 0; environ && environ[i]; i++) {
125- const char *eq;
126- char *name;
127-
128- eq = strchr(environ[i], '=');
129- if (!eq || eq == environ[i])
130- continue;
131- name = xstrndup(environ[i], (size_t)(eq - environ[i]));
132- envsetvar(env, name, xstrdup(eq + 1), 1,
133- envoverride ? ORIGIN_ENV_OVERRIDE : ORIGIN_ENV, 0);
134- free(name);
135- }
136-}
137-
138-void
139-imprules(struct SufRules *rules, int posix, enum ShinMode mode)
140-{
141- const char *src;
142-
143- if (mode == MODE_POSIX_2024)
144- src = IMPRULES_POSIX_2024;
145- else if (mode == MODE_POSIX_2008 || posix)
146- src = IMPRULES_POSIX_2008;
147- else
148- src = IMPRULES_GNU;
149- if (loadimprules(rules, src) < 0) {
150- fprintf(stderr, "failed to load built-in implicit rules\n");
151- exit(1);
152- }
153-}
154
155 int
156 issufrule(const struct RuleNode *rule)