commit f4e3930
Emilia Smólska
·
2026-08-08 10:45:20 +0000 UTC
parent fce7485
implement deps
6 files changed,
+60,
-28
+2,
-0
1@@ -0,0 +1,2 @@
2+obj/*
3+build.ninja
+3,
-1
1@@ -1,3 +1,5 @@
2 local neu = require("neutrino")(arg)
3
4-neu.bin("main", { "main.c" })
5+local lib = neu.lib("lib", { "lib.c" })
6+
7+neu.bin("main", { "main.c" }, { deps = { lib } })
A
lib.c
+6,
-0
1@@ -0,0 +1,6 @@
2+#include <stdio.h>
3+#include "lib.h"
4+
5+void meow(void) {
6+ printf("meow\n");
7+}
A
lib.h
+6,
-0
1@@ -0,0 +1,6 @@
2+#ifndef __lib_h
3+#define __lib_h
4+
5+extern void meow(void);
6+
7+#endif // __lib_h
M
main.c
+2,
-2
1@@ -1,6 +1,6 @@
2-#include <stdio.h>
3+#include "lib.h"
4
5 int main(void) {
6- printf("hello, shrub\n");
7+ meow();
8 return 0;
9 }
+41,
-25
1@@ -3,9 +3,7 @@
2 local neu = {}
3
4 local function check(s)
5- if not s:match("^[%u_]+$") then
6- error(("name '%s' invalid"):format(s))
7- end
8+ assert(s:match("^[%u_]+$"), ("name '%s' invalid"):format(s))
9 end
10
11 local function memq(elt, tbl)
12@@ -16,9 +14,7 @@ end
13 local bools = {}
14 function neu.bool(name)
15 check(name)
16- if bools[name] then
17- error(("option '%s' redeclared"):format(name))
18- end
19+ assert(not bools[name], ("option '%s' redeclared"):format(name))
20 bools[name] = #(os.getenv(name) or "") > 0
21 return bools[name]
22 end
23@@ -26,24 +22,21 @@ end
24 local enums = {}
25 function neu.enum(name, set)
26 check(name)
27- if enums[name] then
28- error(("option '%s' redeclared"):format(name))
29- end
30+ assert(not enums[name], ("option '%s' redeclared"):format(name))
31 local val = os.getenv(name)
32 if not val then enums[name] = set[1]
33- elseif not memq(val, set) then
34- local s = table.concat(set, "', '")
35- error(("value '%s' not in { '%s' }"):format(val, s))
36- else enums[name] = val end
37+ else
38+ assert(memq(val, set), ("value '%s' not in { '%s' }")
39+ :format(val, table.concat(set, " ")))
40+ enums[name] = val
41+ end
42 return enums[name]
43 end
44
45 local strs = {}
46 function neu.str(name, dfl)
47 check(name)
48- if strs[name] then
49- error(("option '%s' redeclared"):format(name))
50- end
51+ assert(not strs[name], ("option '%s' redeclared"):format(name))
52 strs[name] = os.getenv(name) or dfl
53 return strs[name]
54 end
55@@ -66,24 +59,32 @@ local function writerule(name, tbl)
56 for k, v in pairs(tbl) do writevar(" " .. k, v, "\n") end
57 end
58
59-local function writebuild(tgt, rule, prereq, impl)
60+local function writebuild(tgt, rule, prereq, ideps)
61 if type(prereq) == "table" then
62 prereq = table.concat(prereq, " ")
63 end
64- if type(impl) == "table" then
65- impl = table.concat(impl, " ")
66+ if type(ideps) == "table" then
67+ ideps = table.concat(ideps, " ")
68 end
69- impl = impl and "|" .. impl or ""
70- bn:write("build ", tgt, ":", rule, " ", prereq, impl, "\n")
71+ ideps = ideps and "|" .. ideps or ""
72+ bn:write("build ", tgt, ":", rule, " ", prereq, ideps, "\n")
73 end
74
75-local function aggr(name, rule, srcs, opts)
76+local depmeta = {}
77+local function blessdep(tbl) return setmetatable(tbl, depmeta) end
78+local function isdep(tbl) return getmetatable(tbl) == depmeta end
79+
80+local function aggr(name, rule, srcs, opts, ideps, vars)
81 opts = opts or {}
82 opts.std = opts.std or "c17"
83 local stds = { c17 = true, c23 = true }
84 local objs = {}
85+ local lf = {}
86 for i, x in ipairs(srcs) do objs[i] = src2obj(x) end
87- writebuild("obj/" .. name, rule, objs)
88+ writebuild("obj/" .. name, rule, objs, ideps)
89+ if vars then
90+ for k, v in pairs(vars) do writevar(" " .. k, v) end
91+ end
92 for i = 1, #srcs do
93 writebuild(objs[i], "cc", srcs[i])
94 local cf = {}
95@@ -98,10 +99,25 @@ local function aggr(name, rule, srcs, opts)
96 end
97 end
98
99-function neu.bin(bin, srcs, opts) aggr(bin, "ld", srcs, opts) end
100+function neu.bin(bin, srcs, opts)
101+ local ideps = {}
102+ local lf = {}
103+ if opts.deps then
104+ for _, d in ipairs(opts.deps) do
105+ assert(isdep(d), "deps contain invalid object")
106+ if d.file then table.insert(ideps, "obj/" .. d.file) end
107+ table.insert(lf, d.ldflags)
108+ end
109+ end
110+ aggr(bin, "ld", srcs, opts, ideps, {
111+ _ldflags = table.concat(lf, " "),
112+ })
113+end
114
115 function neu.lib(lib, srcs, opts)
116- aggr("lib" .. lib .. ".a", "ar", srcs, opts)
117+ local fn = table.concat({ "lib", lib, ".a" })
118+ aggr(fn, "ar", srcs, opts)
119+ return blessdep({ file = fn, ldflags = "-Lobj -l" .. lib })
120 end
121
122 if not package.searchpath then