98 lines
3.1 KiB
Python
98 lines
3.1 KiB
Python
|
#!/usr/bin/env python3
|
||
|
|
||
|
"""Merges all the header files."""
|
||
|
from glob import glob
|
||
|
from os import path as pt, name as osname
|
||
|
from os.path import sep
|
||
|
import re
|
||
|
from collections import defaultdict
|
||
|
import sys, getopt
|
||
|
|
||
|
if len(sys.argv) < 3:
|
||
|
print("Usage: {} <CROW_HEADERS_DIRECTORY_PATH> <CROW_OUTPUT_HEADER_PATH> (-i(include) OR -e(exclude) item1,item2...)".format(sys.argv[0]))
|
||
|
print("Available middlewares are in `include/crow/middlewares`. Do NOT type the `.h` when including or excluding")
|
||
|
sys.exit(1)
|
||
|
|
||
|
header_path = sys.argv[1]
|
||
|
output_path = sys.argv[2]
|
||
|
|
||
|
middlewares = [x.rsplit(sep, 1)[-1][:-2] for x in glob(pt.join(header_path, ('crow'+sep+'middlewares'+sep+'*.h*')))]
|
||
|
|
||
|
with open(header_path+'/../LICENSE', 'r') as file:
|
||
|
lsc = '/*' + file.read() + '*/'
|
||
|
|
||
|
middlewares_actual = []
|
||
|
if len(sys.argv) > 3:
|
||
|
opts, args = getopt.getopt(sys.argv[3:],"i:e:",["include=","exclude="])
|
||
|
if (len(opts) > 1):
|
||
|
print("Error:Cannot simultaneously include and exclude middlewares.")
|
||
|
sys.exit(1)
|
||
|
if (opts[0][0] in ("-i", "--include")):
|
||
|
middleware_list = opts[0][1].split(',')
|
||
|
for item in middlewares:
|
||
|
if (item in middleware_list):
|
||
|
middlewares_actual.append(item)
|
||
|
elif (opts[0][0] in ("-e", "--exclude")):
|
||
|
middleware_list = opts[0][1].split(',')
|
||
|
for item in middlewares:
|
||
|
if (item not in middleware_list):
|
||
|
middlewares_actual.append(item)
|
||
|
else:
|
||
|
print("ERROR:Unknown argument " + opts[0][0])
|
||
|
sys.exit(1)
|
||
|
else:
|
||
|
middlewares_actual = middlewares
|
||
|
print("Middlewares: " + str(middlewares_actual))
|
||
|
|
||
|
re_depends = re.compile('^#include \"(.*)\"\n', re.MULTILINE)
|
||
|
re_pragma = re.compile('^(.*)#pragma once(.*)\n', re.MULTILINE)
|
||
|
headers = [x.rsplit(sep, 1)[-1] for x in glob(pt.join(header_path, '*.h*'))]
|
||
|
headers += ['crow'+sep + x.rsplit(sep, 1)[-1] for x in glob(pt.join(header_path, 'crow'+sep+'*.h*'))]
|
||
|
headers += [('crow'+sep+'middlewares'+sep + x + '.h') for x in middlewares_actual]
|
||
|
print(headers)
|
||
|
edges = defaultdict(list)
|
||
|
for header in headers:
|
||
|
d = open(pt.join(header_path, header), encoding='UTF-8').read()
|
||
|
match = re_depends.findall(d)
|
||
|
for m in match:
|
||
|
actual_m = m
|
||
|
if (osname == 'nt'): #Windows
|
||
|
actual_m = m.replace('/', '\\')
|
||
|
# m should included before header
|
||
|
edges[actual_m].append(header)
|
||
|
|
||
|
visited = defaultdict(bool)
|
||
|
order = []
|
||
|
|
||
|
|
||
|
|
||
|
def dfs(x):
|
||
|
"""Ensure all header files are visited."""
|
||
|
visited[x] = True
|
||
|
for y in edges[x]:
|
||
|
if not visited[y]:
|
||
|
dfs(y)
|
||
|
order.append(x)
|
||
|
|
||
|
for header in headers:
|
||
|
if not visited[header]:
|
||
|
dfs(header)
|
||
|
|
||
|
order = order[::-1]
|
||
|
for x in edges:
|
||
|
print(x, edges[x])
|
||
|
for x in edges:
|
||
|
for y in edges[x]:
|
||
|
assert order.index(x) < order.index(y), 'cyclic include detected'
|
||
|
|
||
|
print(order)
|
||
|
build = [lsc, '#pragma once']
|
||
|
for header in order:
|
||
|
d = open(pt.join(header_path, header), encoding='UTF-8').read()
|
||
|
d_no_depend = re_depends.sub(lambda x: '', d)
|
||
|
d_no_pragma = re_pragma.sub(lambda x: '', d_no_depend)
|
||
|
build.append(d_no_pragma)
|
||
|
#build.append('\n')
|
||
|
|
||
|
open(output_path, 'w', encoding='UTF-8').write('\n'.join(build))
|