toaruos/util/auto-dep.py
2017-01-15 23:30:32 +09:00

134 lines
5.5 KiB
Python
Executable File

#!/usr/bin/env python3
# coding: utf-8
import os
import sys
try:
TOOLCHAIN_PATH = os.environ['TOOLCHAIN']
except KeyError:
# This is not good, but we need to let it happen for the make file
TOOLCHAIN_PATH = ""
force_static = ["GLU"]
class Classifier(object):
dependency_hints = {
# Core libraries
'<math.h>': (None, '-lm', []),
'<cairo.h>': ('cairo', '-lcairo', ['<ft2build.h>', '<pixman.h>', '<png.h>']),
'<ft2build.h>': ('freetype2', '-lfreetype', ['<zlib.h>']),
'<pixman.h>': ('pixman-1', '-lpixman-1', ['<math.h>']),
'<GL/osmesa.h>': (None, '-lOSMesa', []),
'<GL/glu.h>': (None, '-lGLU', ['<GL/osmesa.h>']),
'<ncurses.h>': ('ncurses', '-lncurses', []),
'<panel.h>': (None, '-lpanel', ['<ncurses.h>']),
'<menu.h>': (None, '-lmenu', ['<ncurses.h>']),
'<zlib.h>': (None, '-lz', ['<math.h>']),
'<png.h>': (None, '-lpng15', ['<zlib.h>']),
'<Python.h>': ('python/include/python3.6m', '-lpython3.6m', ['<math.h>']),
# Toaru Standard Library
'<toaru.h>': (None, '-ltoaru', ['<png.h>','<ft2build.h>','<cairo.h>']),
'"lib/toaru_auth.h"': (None, '-ltoaru-toaru_auth', ['"lib/sha2.h"']),
'"lib/kbd.h"': (None, '-ltoaru-kbd', []),
'"lib/list.h"': (None, '-ltoaru-list', []),
'"lib/hashmap.h"': (None, '-ltoaru-hashmap', ['"lib/list.h"']),
'"lib/tree.h"': (None, '-ltoaru-tree', ['"lib/list.h"']),
'"lib/testing.h"': (None, '-ltoaru-testing', []),
'"lib/pthread.h"': (None, '-ltoaru-pthread', []),
'"lib/sha2.h"': (None, '-ltoaru-sha2', []),
'"lib/pex.h"': (None, '-ltoaru-pex', []),
'"lib/graphics.h"': (None, '-ltoaru-graphics', ['<png.h>']),
'"lib/shmemfonts.h"': (None, '-ltoaru-shmemfonts', ['"lib/graphics.h"', '<ft2build.h>']),
'"lib/rline.h"': (None, '-ltoaru-rline', ['"lib/kbd.h"']),
'"lib/confreader.h"': (None, '-ltoaru-confreader', ['"lib/hashmap.h"']),
'"lib/network.h"': (None, '-ltoaru-network', []),
'"lib/http_parser.h"': (None, '-ltoaru-http_parser', []),
'"lib/dlfcn.h"': (None, '-ltoaru-dlfcn', []),
# Yutani Libraries
'"lib/yutani.h"': (None, '-ltoaru-yutani', ['"lib/kbd.h"', '"lib/list.h"', '"lib/pex.h"', '"lib/graphics.h"', '"lib/hashmap.h"']),
'"lib/decorations.h"': (None, '-ltoaru-decorations', ['"lib/shmemfonts.h"', '"lib/graphics.h"', '"lib/yutani.h"','"lib/dlfcn.h"']),
'"gui/terminal/lib/termemu.h"': (None, '-ltoaru-termemu', ['"lib/graphics.h"']),
}
def __init__(self, filename):
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)
_, _, other = self.dependency_hints[k]
depends = self._calculate(depends, other)
return depends
def _sort(self, depends):
"""Sort the list of dependencies so that elements appearing first depend on elements following."""
satisfied = []
a = depends[:]
while set(satisfied) != set(depends):
b = []
for k in a:
if all([x in satisfied for x in self.dependency_hints[k][2]]):
satisfied.append(k)
else:
b.append(k)
a = b[:]
return satisfied[::-1]
def _depends(self):
"""Calculate include and library dependencies."""
lines = []
depends = []
with open(self.filename,'r') as f:
lines = f.readlines()
for l in lines:
if l.startswith('#include'):
depends.extend([k for k in list(self.dependency_hints.keys()) if l.startswith('#include ' + k)])
depends = self._calculate([], depends)
depends = self._sort(depends)
includes = []
libraries = []
for k in depends:
dep = self.dependency_hints[k]
if dep[0]:
includes.append('-I' + TOOLCHAIN_PATH + '/include/' + dep[0])
if dep[1]:
libraries.append(dep[1])
return includes, libraries
def todep(name):
"""Convert a library name to an archive path or object file name."""
if name.startswith("-l"):
name = name.replace("-l","",1)
if name in force_static:
return (False, "%s/lib%s.a" % (TOOLCHAIN_PATH + '/lib', name))
else:
return (True, "%s/lib%s.so" % ('hdd/usr/lib', name))
else:
return (False, name)
if __name__ == "__main__":
if len(sys.argv) < 3:
print("usage: util/auto-dep.py command filename")
exit(1)
command = sys.argv[1]
filename = sys.argv[2]
c = Classifier(filename)
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":
results = [todep(x) for x in c.libs]
normal = [x[1] for x in results if not x[0]]
order_only = [x[1] for x in results if x[0]]
print(" ".join(normal) + " | " + " ".join(order_only))