2021-04-28 00:41:55 +03:00
|
|
|
#!/bin/kuroko
|
|
|
|
import os, kuroko, fileio
|
2018-04-17 15:49:56 +03:00
|
|
|
|
2021-05-31 04:47:02 +03:00
|
|
|
let cflags = "-O2 -g -I. -Iapps -fplan9-extensions -Wall -Wextra -Wno-unused-parameter"
|
2018-04-17 15:49:56 +03:00
|
|
|
|
2021-05-31 04:47:02 +03:00
|
|
|
def basename(path: str) -> str:
|
2021-04-28 00:41:55 +03:00
|
|
|
return path.strip('/').split('/')[-1]
|
2018-04-17 15:49:56 +03:00
|
|
|
|
2021-04-28 00:41:55 +03:00
|
|
|
class Classifier:
|
2018-04-17 15:49:56 +03:00
|
|
|
dependency_hints = {
|
|
|
|
# Toaru Standard Library
|
|
|
|
'<toaru/kbd.h>': (None, '-ltoaru_kbd', []),
|
|
|
|
'<toaru/list.h>': (None, '-ltoaru_list', []),
|
|
|
|
'<toaru/hashmap.h>': (None, '-ltoaru_hashmap', ['<toaru/list.h>']),
|
|
|
|
'<toaru/tree.h>': (None, '-ltoaru_tree', ['<toaru/list.h>']),
|
|
|
|
'<toaru/pex.h>': (None, '-ltoaru_pex', []),
|
2018-05-10 16:33:32 +03:00
|
|
|
'<toaru/auth.h>': (None, '-ltoaru_auth', []),
|
2018-04-17 15:49:56 +03:00
|
|
|
'<toaru/graphics.h>': (None, '-ltoaru_graphics', []),
|
2020-04-21 05:04:26 +03:00
|
|
|
'<toaru/inflate.h>': (None, '-ltoaru_inflate', []),
|
2018-04-17 15:49:56 +03:00
|
|
|
'<toaru/drawstring.h>': (None, '-ltoaru_drawstring', ['<toaru/graphics.h>']),
|
2018-12-05 07:01:16 +03:00
|
|
|
'<toaru/jpeg.h>': (None, '-ltoaru_jpeg', ['<toaru/graphics.h>']),
|
2020-04-21 10:36:13 +03:00
|
|
|
'<toaru/png.h>': (None, '-ltoaru_png', ['<toaru/graphics.h>','<toaru/inflate.h>']),
|
2018-04-17 15:49:56 +03:00
|
|
|
'<toaru/rline.h>': (None, '-ltoaru_rline', ['<toaru/kbd.h>']),
|
|
|
|
'<toaru/confreader.h>': (None, '-ltoaru_confreader', ['<toaru/hashmap.h>']),
|
2020-03-28 16:20:20 +03:00
|
|
|
'<toaru/markup.h>': (None, '-ltoaru_markup', ['<toaru/hashmap.h>']),
|
|
|
|
'<toaru/json.h>': (None, '-ltoaru_json', ['<toaru/hashmap.h>']),
|
2018-04-17 15:49:56 +03:00
|
|
|
'<toaru/yutani.h>': (None, '-ltoaru_yutani', ['<toaru/kbd.h>', '<toaru/list.h>', '<toaru/pex.h>', '<toaru/graphics.h>', '<toaru/hashmap.h>']),
|
2021-07-06 07:22:59 +03:00
|
|
|
'<toaru/decorations.h>': (None, '-ltoaru_decorations', ['<toaru/menu.h>', '<toaru/text.h>', '<toaru/graphics.h>', '<toaru/yutani.h>']),
|
2018-04-17 15:49:56 +03:00
|
|
|
'<toaru/termemu.h>': (None, '-ltoaru_termemu', ['<toaru/graphics.h>']),
|
2018-04-24 14:25:42 +03:00
|
|
|
'<toaru/icon_cache.h>': (None, '-ltoaru_icon_cache', ['<toaru/graphics.h>', '<toaru/hashmap.h>']),
|
2021-07-06 07:22:59 +03:00
|
|
|
'<toaru/menu.h>': (None, '-ltoaru_menu', ['<toaru/yutani.h>', '<toaru/icon_cache.h>', '<toaru/graphics.h>', '<toaru/hashmap.h>']),
|
|
|
|
'<toaru/button.h>': (None, '-ltoaru_button', ['<toaru/graphics.h>','<toaru/text.h>', '<toaru/icon_cache.h>']),
|
2021-07-05 16:50:25 +03:00
|
|
|
'<toaru/text.h>': (None, '-ltoaru_text', ['<toaru/graphics.h>', '<toaru/hashmap.h>']),
|
2021-07-27 04:53:12 +03:00
|
|
|
'<toaru/markup_text.h>': (None, '-ltoaru_markup_text', ['<toaru/graphics.h>', '<toaru/markup.h>', '<toaru/text.h>']),
|
2021-01-01 11:19:44 +03:00
|
|
|
# Kuroko
|
2021-05-31 04:47:02 +03:00
|
|
|
'<kuroko/kuroko.h>': ('../../../kuroko/src', '-lkuroko', []),
|
2018-04-17 15:49:56 +03:00
|
|
|
}
|
|
|
|
|
2021-05-31 04:47:02 +03:00
|
|
|
def __init__(self, filename: str):
|
2018-09-22 11:34:20 +03:00
|
|
|
self.export_dynamic_hint = False
|
2018-04-17 15:49:56 +03:00
|
|
|
self.filename = filename
|
|
|
|
self.includes, self.libs = self._depends()
|
|
|
|
|
|
|
|
def _calculate(self, depends, new):
|
|
|
|
"""Calculate all dependencies for the given set of new elements."""
|
|
|
|
for k in new:
|
|
|
|
if not k in depends:
|
|
|
|
depends.append(k)
|
2021-04-28 00:41:55 +03:00
|
|
|
let other = self.dependency_hints[k][2]
|
2018-04-17 15:49:56 +03:00
|
|
|
depends = self._calculate(depends, other)
|
|
|
|
return depends
|
|
|
|
|
2021-05-31 04:47:02 +03:00
|
|
|
def _sort(self, depends: list[str]) -> list[str]:
|
2018-04-17 15:49:56 +03:00
|
|
|
"""Sort the list of dependencies so that elements appearing first depend on elements following."""
|
2021-04-28 00:41:55 +03:00
|
|
|
let satisfied = []
|
|
|
|
let a = depends[:]
|
2018-04-17 15:49:56 +03:00
|
|
|
|
|
|
|
while set(satisfied) != set(depends):
|
2021-04-28 00:41:55 +03:00
|
|
|
let b = []
|
2018-04-17 15:49:56 +03:00
|
|
|
for k in a:
|
2021-04-28 00:41:55 +03:00
|
|
|
if all(x in satisfied for x in self.dependency_hints[k][2]):
|
2018-04-17 15:49:56 +03:00
|
|
|
satisfied.append(k)
|
|
|
|
else:
|
|
|
|
b.append(k)
|
|
|
|
a = b[:]
|
2021-04-28 00:41:55 +03:00
|
|
|
return reversed(satisfied)
|
2018-04-17 15:49:56 +03:00
|
|
|
|
2021-05-31 04:47:02 +03:00
|
|
|
def _depends(self) -> (list[str],list[str]):
|
2018-04-17 15:49:56 +03:00
|
|
|
"""Calculate include and library dependencies."""
|
2021-04-28 00:41:55 +03:00
|
|
|
let lines = []
|
|
|
|
let depends = []
|
|
|
|
with fileio.open(self.filename,'r') as f:
|
2018-04-17 15:49:56 +03:00
|
|
|
lines = f.readlines()
|
|
|
|
for l in lines:
|
|
|
|
if l.startswith('#include'):
|
2021-04-28 00:41:55 +03:00
|
|
|
depends.extend(k for k in list(self.dependency_hints.keys()) if l.startswith('#include ' + k))
|
2018-09-22 11:34:20 +03:00
|
|
|
elif l.startswith('/* auto-dep: export-dynamic */'):
|
|
|
|
self.export_dynamic_hint = True
|
2018-04-17 15:49:56 +03:00
|
|
|
depends = self._calculate([], depends)
|
|
|
|
depends = self._sort(depends)
|
2021-04-28 00:41:55 +03:00
|
|
|
let includes = []
|
|
|
|
let libraries = []
|
2018-04-17 15:49:56 +03:00
|
|
|
for k in depends:
|
2021-04-28 00:41:55 +03:00
|
|
|
let dep = self.dependency_hints[k]
|
2018-04-17 15:49:56 +03:00
|
|
|
if dep[0]:
|
2018-09-21 06:12:28 +03:00
|
|
|
includes.append('-I' + 'base/usr/include/' + dep[0])
|
2018-04-17 15:49:56 +03:00
|
|
|
if dep[1]:
|
|
|
|
libraries.append(dep[1])
|
|
|
|
return includes, libraries
|
|
|
|
|
|
|
|
|
2021-05-31 04:47:02 +03:00
|
|
|
def todep(name: str) -> (bool, str):
|
2018-04-17 15:49:56 +03:00
|
|
|
"""Convert a library name to an archive path or object file name."""
|
|
|
|
if name.startswith("-l"):
|
|
|
|
name = name.replace("-l","",1)
|
2018-09-21 06:12:28 +03:00
|
|
|
if name.startswith('toaru'):
|
2021-04-28 00:41:55 +03:00
|
|
|
return (True, "{}/lib{}.so".format('base/lib', name))
|
2021-01-01 11:19:44 +03:00
|
|
|
elif name.startswith('kuroko'):
|
2021-04-28 00:41:55 +03:00
|
|
|
return (True, "{}/lib{}.so".format('base/lib', name))
|
2018-09-21 06:12:28 +03:00
|
|
|
else:
|
2021-04-28 00:41:55 +03:00
|
|
|
return (True, "{}/lib{}.so".format('base/usr/lib', name))
|
2018-04-17 15:49:56 +03:00
|
|
|
else:
|
|
|
|
return (False, name)
|
|
|
|
|
2021-05-31 04:47:02 +03:00
|
|
|
def toheader(name: str) -> str:
|
2018-04-17 16:30:19 +03:00
|
|
|
if name.startswith('-ltoaru_'):
|
|
|
|
return name.replace('-ltoaru_','base/usr/include/toaru/') + '.h'
|
2018-09-21 06:12:28 +03:00
|
|
|
else:
|
|
|
|
return ''
|
2018-04-17 16:30:19 +03:00
|
|
|
|
2018-04-17 15:49:56 +03:00
|
|
|
if __name__ == "__main__":
|
2021-04-28 00:41:55 +03:00
|
|
|
if len(kuroko.argv) < 3:
|
|
|
|
print("usage: util/auto-dep.krk command filename")
|
|
|
|
return 1
|
|
|
|
let command = kuroko.argv[1]
|
|
|
|
let filename = kuroko.argv[2]
|
|
|
|
let c = Classifier(filename)
|
2018-04-17 15:49:56 +03:00
|
|
|
|
|
|
|
if command == "--cflags":
|
|
|
|
print(" ".join([x for x in c.includes]))
|
|
|
|
elif command == "--libs":
|
|
|
|
print(" ".join([x for x in c.libs]))
|
|
|
|
elif command == "--deps":
|
2021-04-28 00:41:55 +03:00
|
|
|
let results = [todep(x) for x in c.libs]
|
|
|
|
let normal = [x[1] for x in results if not x[0]]
|
|
|
|
let order_only = [x[1] for x in results if x[0]]
|
2018-04-17 15:49:56 +03:00
|
|
|
print(" ".join(normal) + " | " + " ".join(order_only))
|
2018-10-15 13:00:53 +03:00
|
|
|
elif command == "--build":
|
2021-04-28 00:41:55 +03:00
|
|
|
os.system("gcc {cflags} {extra} {includes} -o {app} {source} {libraries}".format(
|
2018-10-15 13:00:53 +03:00
|
|
|
cflags=cflags,
|
2021-05-31 04:47:02 +03:00
|
|
|
app=basename(filename).replace('.c++','').replace(".c",""),
|
2018-10-15 13:00:53 +03:00
|
|
|
source=filename,
|
|
|
|
headers=" ".join([toheader(x) for x in c.libs]),
|
|
|
|
libraries=" ".join([x for x in c.libs]),
|
|
|
|
includes=" ".join([x for x in c.includes if x is not None]),
|
2021-05-31 04:47:02 +03:00
|
|
|
extra="-rdynamic" if c.export_dynamic_hint else "",
|
2021-04-28 00:41:55 +03:00
|
|
|
))
|
2018-10-15 13:00:53 +03:00
|
|
|
elif command == "--buildlib":
|
2021-05-31 04:47:02 +03:00
|
|
|
let libname = basename(filename).replace('.c++','').replace(".c","")
|
2021-04-28 00:41:55 +03:00
|
|
|
let _libs = [x for x in c.libs if not x.startswith('-ltoaru_') or x.replace("-ltoaru_","") != libname]
|
|
|
|
os.system("gcc {cflags} {includes} -shared -fPIC -olibtoaru_{lib}.so {source} {libraries}".format(
|
2018-10-15 13:00:53 +03:00
|
|
|
cflags=cflags,
|
|
|
|
lib=libname,
|
|
|
|
source=filename,
|
|
|
|
headers=" ".join([toheader(x) for x in c.libs]),
|
|
|
|
libraryfiles=" ".join([todep(x)[1] for x in _libs]),
|
|
|
|
libraries=" ".join([x for x in _libs]),
|
|
|
|
includes=" ".join([x for x in c.includes if x is not None])
|
2021-04-28 00:41:55 +03:00
|
|
|
))
|
2018-04-17 15:49:56 +03:00
|
|
|
elif command == "--make":
|
2021-05-31 04:47:02 +03:00
|
|
|
print("base/bin/{app}: {source} {headers} util/auto-dep.krk | {libraryfiles} $(LC)\n\t{comp} {extra} {includes} -o $@ $< {libraries}".format(
|
|
|
|
app=basename(filename).replace('.c++','').replace(".c",""),
|
2018-04-17 15:49:56 +03:00
|
|
|
source=filename,
|
2018-04-17 16:30:19 +03:00
|
|
|
headers=" ".join([toheader(x) for x in c.libs]),
|
2018-04-17 15:49:56 +03:00
|
|
|
libraryfiles=" ".join([todep(x)[1] for x in c.libs]),
|
2018-09-21 06:12:28 +03:00
|
|
|
libraries=" ".join([x for x in c.libs]),
|
2018-09-22 11:34:20 +03:00
|
|
|
includes=" ".join([x for x in c.includes if x is not None]),
|
2021-05-31 04:47:02 +03:00
|
|
|
comp="$(CC) $(CFLAGS)" if '.c++' not in filename else "$(CXX) $(CXXFLAGS)",
|
|
|
|
extra="-rdynamic" if c.export_dynamic_hint else ""
|
2018-09-21 06:12:28 +03:00
|
|
|
))
|
2018-04-17 16:18:15 +03:00
|
|
|
elif command == "--makelib":
|
2021-05-31 04:47:02 +03:00
|
|
|
let libname = basename(filename).replace('.c++','').replace(".c","")
|
2021-04-28 00:41:55 +03:00
|
|
|
let _libs = [x for x in c.libs if not x.startswith('-ltoaru_') or x.replace("-ltoaru_","") != libname]
|
2021-05-31 04:47:02 +03:00
|
|
|
print("base/lib/libtoaru_{lib}.so: {source} {headers} util/auto-dep.krk | {libraryfiles} $(LC)\n\t{comp} {includes} -shared -fPIC -o $@ $< {libraries}".format(
|
2018-04-17 16:18:15 +03:00
|
|
|
lib=libname,
|
|
|
|
source=filename,
|
2018-04-17 16:30:19 +03:00
|
|
|
headers=" ".join([toheader(x) for x in c.libs]),
|
2018-04-17 16:18:15 +03:00
|
|
|
libraryfiles=" ".join([todep(x)[1] for x in _libs]),
|
2018-09-21 06:12:28 +03:00
|
|
|
libraries=" ".join([x for x in _libs]),
|
2021-05-31 04:47:02 +03:00
|
|
|
includes=" ".join([x for x in c.includes if x is not None]),
|
|
|
|
comp="$(CC) $(CFLAGS)" if '.c++' not in filename else "$(CXX) $(CXXFLAGS)",
|
2018-09-21 06:12:28 +03:00
|
|
|
))
|
2021-01-01 11:19:44 +03:00
|
|
|
elif command == "--makekurokomod":
|
2021-05-31 04:47:02 +03:00
|
|
|
let libname = basename(filename).replace('.c++','').replace(".c","").replace("module_","")
|
2021-04-28 00:41:55 +03:00
|
|
|
let _libs = [x for x in c.libs if not x.startswith('-ltoaru_') or x.replace("-ltoaru_","") != libname]
|
|
|
|
print("base/lib/kuroko/{lib}.so: {source} {headers} util/auto-dep.krk | {libraryfiles} $(LC)\n\t$(CC) $(CFLAGS) {includes} -shared -fPIC -o $@ $< {libraries}".format(
|
2021-01-01 11:19:44 +03:00
|
|
|
lib=libname,
|
|
|
|
source=filename,
|
|
|
|
headers=" ".join([toheader(x) for x in c.libs]),
|
|
|
|
libraryfiles=" ".join([todep(x)[1] for x in _libs]),
|
|
|
|
libraries=" ".join([x for x in _libs]),
|
|
|
|
includes=" ".join([x for x in c.includes if x is not None])
|
|
|
|
))
|
2018-04-17 15:49:56 +03:00
|
|
|
|
2021-04-28 00:41:55 +03:00
|
|
|
|