-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathluabuild.lua
297 lines (263 loc) · 6.56 KB
/
luabuild.lua
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
--#!/usr/bin/env luajit
EXPORT = {}
local version = "0.1.0"
local lanes = require("lanes").configure({
demote_full_userdata = true
})
local argparse = require("argparse")
local nproc = 0
do
local h = io.popen("nproc", "r")
local n = h:read("*a"):match("%d+")
h:close()
if n and tonumber(n) then
nproc = tonumber(n)
end
end
_NPROC = nproc
local tags = {
["info"] = "\27[36mINFO\27[0m",
["warning"] = "\27[93mWARNING\27[0m",
["error"] = "\27[91mERROR\27[0m",
["build"] = "\27[35mBUILD\27[0m",
["ok"] = "\27[92mOK\27[0m",
["link"] = "\27[34mLINK\27[0m",
["pack"] = "\27[95mPACK\27[0m",
}
function lastmod(path)
end
local function wait_start(t)
while t.status == "pending" do lanes.sleep() end
end
local function getwh()
local f = io.popen("stty size", "r")
local w, h = f:read("*n"), f:read("*n")
f:close()
return tonumber(w), tonumber(h)
end
local function draw_bar(tag, object, max, current)
if (#object > 15) then
object = object:sub(1, 12).."..."
end
os.execute("stty raw -echo 2> /dev/null") -- i cannot comprehend what retardation lead me to have to do this
io.stdout:write("\27[6n")
io.stdout:flush()
local lc = ""
while lc ~= "\27" do
-- print(string.byte(lc) or "<none>")
lc = io.stdin:read(1)
-- print(string.byte(lc))
end
io.stdin:read(1)
local buf = ""
while lc ~= "R" do
lc = io.stdin:read(1)
buf = buf .. lc
end
os.execute("stty sane 2> /dev/null")
--print(buf)
local y, x = buf:match("(%d+);(%d+)")
x = tonumber(x)
y = tonumber(y)
--print(os.getenv("LINES"), os.getenv("COLUMNS"))
--local l = tonumber(os.getenv("LINES"))
--local c = tonumber(os.getenv("COLUMNS"))
--print(l, c)
local l, c = getwh() -- WHY
if (y == l) then
print("")
y = y - 1
end
local mx = string.format("%x", max)
local cur = string.format("%."..#mx.."x", current)
local bar = (current/max)*(c-(26+#mx*2))
if bar ~= bar then bar = 0 end
io.stdout:write("\27["..l.."H")
local pad = 6-#tag
local opad = 16-#object
--print(math.floor(bar))
local hashes = string.rep("#", math.floor(bar))
local dashes = string.rep("-", c-(26+#mx*2+#hashes))
io.stdout:write(tags[tag], string.rep(" ", pad), object, string.rep(" ", opad), cur, "/", mx, " [", hashes, dashes, "]")
io.stdout:write("\27[", x, ";", y, "H")
end
function status(tag, msg)
print(tags[tag], msg)
end
local threads = {}
local stat = status
local function run(cmd)
if not status then status = stat end
local h = io.popen(cmd.." 2>&1", "r")
local out = h:read("*a")
local rtn = h:close()
return rtn, out
end
local tasks = {}
local reflect = {}
function task(name, stuff)
tasks[#tasks+1] = {name, stuff, false}
end
reflect.task = task
reflect._NPROC = nproc
reflect.status = status
reflect.draw_bar = draw_bar
function dep(name)
if not status then setmetatable(_G, {__index=reflect}) end
for i=1, #tasks do
if (tasks[i][1] == name) then
if not tasks[i][3] then
tasks[i][3] = true
tasks[i][2]()
end
return
end
end
status("error", "Task `"..name.."' not found!")
os.exit(1)
end
reflect.dep = dep
local function sync()
local errors = {}
while #threads > 0 do
for i=1, #threads do
if (threads[j].status ~= "running") then
if not threads[j][1] then
errors[#errors+1] = threads[j][2]
end
table.remove(threads, j)
break
end
end
end
return errors
end
reflect.sync = sync
local CC_STATE = {
compiler = "clang",
flags = {},
args = {},
libs = {},
}
local run_t = lanes.gen("*", run)
local function compile(file)
local compiler_command = compiler .. " -fdiagnostics-color=always "
for i=1, #CC_STATE.flags do
compiler_command = compiler_command .. "-f"..CC_STATE.flags[i].." "
end
for i=1, #CC_STATE.args do
compiler_command = compiler_command .. CC_STATE.args[i].." "
end
compiler_command = compiler_command .. file
return run_t(compiler_command)
end
local function link(target, files)
local nfiles = {}
for i=1, #files do
nfiles[i] = files[i]:gsub("%.c$", ".o")
end
local compiler_command = compiler .. " -fdiagnostics-color=always "
for i=1, #CC_STATE.libs do
compiler_command = compiler_command .. "-l"..CC_STATE.args[i].." "
end
compiler_command = compiler_command "-o "..target.. " " .. table.concat(files, " ")
run(compiler_command)
end
function build(target, files)
status("build", target.." ("..#files.." source files)")
draw_bar("build", target, 0, #files)
for i=1, #files do
if (#threads == nproc) then
while true do
for j=1, #threads do
if (threads[j].status ~= "running") then
if not threads[j][1] then
status("error", "Error in compile, waiting for all threads to finish...")
local errors = sync()
print(threads[j][2])
for k=1, #errors do
print(errors[k])
end
os.exit(1)
else
threads[j] = compile(files[i])
wait_start(threads[j])
break
end
end
end
lanes.sleep()
end
else
threads[#threads+1] = compile(files[i])
end
draw_bar("build", target, #files, i)
end
local errors = sync()
if #errors > 0 then
for i=1, #errors do
print(errors[i])
end
os.exit(1)
end
status("link", target)
draw_bar("link", target, 1, 1)
link(target, files)
end
reflect.build = build
reflect.EXPORT = EXPORT
function find(path)
local entries = {}
local h = io.popen("find "..path, "r")
for l in h:lines() do
entries[#entries+1] = l
end
return entries
end
reflect.find = find
local files = find(".build")
for i=1, #files do
if (files[i]:match("%.lua$")) then
dofile(files[i])
end
end
task("list", function()
for i=1, #tasks do
print(tasks[i][1])
end
end)
local dep_t = lanes.gen("*", dep)
local function run_task(task)
local t = dep_t(task)
wait_start(t)
while true do
if (t.status ~= "running") then
if (t.status ~= "done") then
status("error", "Task '"..task.."' has run into an error!")
print(t[1])
end
break
end
end
lanes.sleep()
end
local parser = argparse("luabuild", "High-speed lua build system.")
parser:option("-j --threads", "Number of threads", nproc)
parser:argument("tasks", "Tasks to run"):args("*")
local args = parser:parse()
status("info", "luabuild version is "..version)
status("info", "lua verison is ".._VERSION)
if not tonumber(args.threads) then
status("error", "Number of threads must be a number!")
os.exit(1)
end
nproc = tonumber(args.threads)
status("info", "core count: "..nproc)
for i=1, #args.tasks do
status("info", "Current task: "..args.tasks[i])
local st = os.clock()
run_task(args.tasks[i])
local dur = os.clock()-st
status("ok", "Task `"..args.tasks[i].."' completed in "..string.format("%.2fs", dur))
end
status("ok", "Build completed in "..string.format("%.2fs", os.clock()))